4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Claude Code 2.1.33】memory frontmatterでサブエージェントに"記憶"を持たせてみた

Posted at

はじめに

Claude Code 2.1.33 で、サブエージェントやスキルの YAML frontmatter に memory フィールドが追加されました。これにより、エージェントがセッションをまたいで「学習した知識」を永続的に保持できるようになります。

従来の CLAUDE.md がプロジェクト全体の知識を管理するのに対し、memory frontmatter はエージェント単位の継続学習を実現します。

memory frontmatter とは

サブエージェント(.claude/agents/)やスキル(.claude/skills/)の YAML frontmatter に memory フィールドを1行追加するだけで、そのエージェントに永続メモリが付与されます。

---
name: code-reviewer
description: コードレビューを行うエージェント
memory: user
---

あなたはコードレビュアーです。レビュー中に発見したパターンや規約、
繰り返し見つかる問題をメモリに記録してください。

これで code-reviewer エージェントは、過去のセッションで学んだことを次のセッションでも覚えています。

3つのスコープ

memory フィールドには3つのスコープを指定できます。

スコープ 保存場所 用途
user ~/.claude/agent-memory/<agent-name>/ 全プロジェクト共通の知識
project .claude/agent-memory/<agent-name>/ プロジェクト固有(git管理可能)
local .claude/agent-memory-local/<agent-name>/ プロジェクト固有(git管理しない)

公式ドキュメントでは user がデフォルト推奨とされています。projectlocal は、その知識が特定プロジェクトにのみ関連する場合に使います。

全プロジェクトで使える汎用知識? → user(推奨デフォルト)
プロジェクト固有でチーム共有したい? → project
プロジェクト固有で個人用? → local

仕組み

memory を有効にすると何が起きるか

memory フィールドを設定すると、以下が自動で行われます。

  1. システムプロンプトの拡張: メモリディレクトリの読み書き方法がエージェントのシステムプロンプトに注入される
  2. MEMORY.md の自動ロード: メモリディレクトリ内の MEMORY.md の先頭200行がシステムプロンプトに含まれる
  3. ツール自動有効化: Read、Write、Edit ツールが自動で使えるようになる
    • ただし tools フィールドを明示的に指定している場合は、そちらが優先されます。メモリを使うなら Write と Edit を含める ことを忘れずに
  4. 自動キュレーション指示: MEMORY.md が200行を超えた場合、エージェントに整理するよう指示が出る

メモリはいつ書き込まれるか

ここが重要なポイントですが、メモリの書き込みは自動ではありません

エージェントが自分の判断で Write/Edit ツールを使って MEMORY.md に書き込みます。つまり、エージェントのプロンプトに「メモリに記録して」と指示しないと、何も蓄積されません。

エージェント起動
  ↓
MEMORY.md を自動読み込み(先頭200行 → システムプロンプトに注入)
  ↓
タスク実行
  ↓
エージェントが自分の判断で MEMORY.md に書き込み ← 自動ではない!
  ↓
次回起動時に MEMORY.md が再読み込みされ、過去の知識が活きる

公式ドキュメントでも以下のようなプラクティスが推奨されています。

プロンプトにメモリ更新の指示を含める:

コードパスやパターン、ライブラリの場所、重要なアーキテクチャ上の決定を
発見したら、エージェントメモリを更新してください。
これにより会話をまたいだ知識基盤が構築されます。

タスク完了後に明示的に依頼する:

レビューが終わったら、学んだことをメモリに保存して。

タスク開始前にメモリを参照させる:

このPRをレビューして。まず過去のメモリで見つけたパターンを確認して。

実践:セットアップから動作確認まで

Step 1: エージェントファイルを作成

.claude/agents/code-reviewer.md を作成します。

---
name: code-reviewer
description: プロジェクトのコーディング規約を学習するレビュアー。コード変更後に積極的に使用する。
memory: project
tools: Read, Write, Edit, Grep, Glob, Bash
---

あなたはコードレビュアーです。

## レビュー方針
1. git diff で最近の変更を確認する
2. 変更されたファイルに集中する
3. レビューを開始する

## レビューチェックリスト
- コーディング規約の違反
- パフォーマンスの問題
- セキュリティリスク
- エラーハンドリングの不足

## メモリの管理
レビュー中に発見した以下の情報をメモリに記録してください:
- プロジェクト固有のコーディングパターン
- 頻出する問題のパターン
- チームの命名規則
- 使用しているライブラリの注意点

フィードバックは優先度順に整理してください:
- Critical(必ず修正)
- Warning(修正推奨)
- Suggestion(改善の余地あり)

Step 2:(任意)MEMORY.md を事前に用意する

エージェントに初期知識を与えたい場合、MEMORY.md を手動で作成できます。

mkdir -p .claude/agent-memory/code-reviewer

.claude/agent-memory/code-reviewer/MEMORY.md:

# Code Review Memory

## プロジェクト規約
- TypeScript + React を使用
- 命名規則: コンポーネントは PascalCase、関数は camelCase
- エラーハンドリング: カスタム AppError クラスを使用

## 既知のパターン
(ここにレビューで発見したパターンが蓄積されていく)

事前に書いておけば、初回からプロジェクト固有の知識を持った状態でレビューを開始できます。書かなくても、エージェントが実行中に自分で作成します。

Step 3: エージェントを使う

# エージェントを直接起動する場合
claude --agent code-reviewer

# 通常セッション内で委譲させる場合
# → Claude が description を見て自動的に委譲する

通常セッション内で使う場合は、以下のように明示的に指定することもできます。

code-reviewer エージェントを使って、最近の変更をレビューして

Step 4: メモリの蓄積を確認

レビュー後に蓄積されたメモリを確認できます。

cat .claude/agent-memory/code-reviewer/MEMORY.md

2回目以降の実行では、このファイルの内容がシステムプロンプトに自動注入されます。

実際にやってみた

レビュー対象のコード

意図的に問題を仕込んだ src/user-service.ts を用意しました。

import axios from "axios"

export class userService {
  API_URL = "http://localhost:3000"

  async GetUsers() {
    const res = await axios.get(this.API_URL + "/users")
    return res.data
  }

  async getUserById(id: any) {
    const res = await axios.get(this.API_URL + "/users/" + id)
    return res.data
  }

  async createUser(name: string, email: string, password: string) {
    console.log("creating user:", name, email, password)
    const res = await axios.post(this.API_URL + "/users", {
      name: name,
      email: email,
      password: password,
    })
    return res.data
  }

  async searchUsers(query: string) {
    const res = await axios.get(this.API_URL + "/users?q=" + query)
    return res.data
  }

  async updateUser(id: number, data: any) {
    var result = await axios.put(this.API_URL + "/users/" + id, data)
    return result.data
  }
}

仕込んだ問題:命名規則の不統一、any 型、console.log でのパスワード出力、クエリ未エスケープ、var の使用、エラーハンドリングなし、など。

エージェントを実行

claude --agent code-reviewer -p "src/user-service.ts をレビューして。発見したパターンはメモリに記録して。"

レビュー結果は標準出力に表示されます(ファイルには保存されません)。12件の指摘が返ってきました。

レビュー結果(指摘事項)はターミナルに表示されるだけで消えます。永続化されるのは メモリ(学習した知識)だけ です。レビューの「結論」ではなく「パターン」を覚える、という設計です。

蓄積されたメモリを確認

なんかたくさん出た!?
完全に想定外ですMEMORY.mdだけ出ると思っていたら色々出てきました中身をみてみましょう。

image.png

MEMORY.md
# Code Reviewer Memory

## プロジェクト概要
- **言語**: TypeScript
- **HTTPクライアント**: axios

## 発見したコーディングパターン

### 命名規則の傾向
- クラス名に camelCase を使用する誤りあり(`userService` → `UserService` が正しい)
- メソッド名に PascalCase が混在(`GetUsers` → `getUsers` が正しい)
- → 詳細: naming-conventions.md

### 頻出する問題パターン
- **`any` 型の乱用**: 型安全性を放棄する `any` が多用される
- **エラーハンドリングの欠如**: try/catch が全メソッドで未実装
- **`var` の使用**: `const`/`let` ではなく `var` が残存
- → 詳細: common-issues.md

### セキュリティリスクパターン
- **機密情報のログ出力**: `console.log` でパスワード等を平文出力
- **未エスケープのユーザー入力**: URLクエリパラメータが未エスケープで結合
- → 詳細: security-patterns.md

## レビュー履歴
- `src/user-service.ts`: 12件の指摘(Critical 3, Important 5, Recommended 4)

エージェントが自主的に MEMORY.md を索引として使い、詳細を別ファイルに分離する構成 を取りました。

注目すべきポイント:

  • MEMORY.md が索引として機能: 詳細は別ファイルに分離し、200行制限に対応している
  • パターンとして記録: 個別の指摘ではなく「このプロジェクトで見られる傾向」として一般化している
  • 次回起動時に自動注入: この MEMORY.md の先頭200行が、次回のシステムプロンプトに含まれる
naming-conventions.md
# 命名規則パターン

## 発見された問題

### クラス名
- ❌ `userService` (camelCase)
- ✅ `UserService` (PascalCase)
- **ルール**: TypeScript/JavaScript のクラス名は PascalCase

### メソッド名
- ❌ `GetUsers()` (PascalCase)
- ✅ `getUsers()` (camelCase)
- **ルール**: メソッド名は camelCase

### 変数名の統一性
- 同じ用途の変数(HTTPレスポンス)に `res` と `result` が混在
- **ルール**: 同一パターンの変数名は統一する

### プロパティ
- `API_URL` はスネークケース大文字 → TypeScript では `apiUrl` (camelCase)
  または `readonly` 定数として `API_URL` は許容
- アクセス修飾子の省略(デフォルト public)→ 明示的に `private readonly` を指定すべき
common-issues.md
# 頻出する問題パターン

## 1. `any` 型の乱用
- **場所**: 関数引数、戻り値
- **影響**: TypeScript の型チェックが無効化される
- **対策**: インターフェース/型エイリアスを定義し、ジェネリクスを活用
- **例**: `axios.get<User[]>(url)` のように型パラメータを指定

## 2. エラーハンドリングの欠如
- **パターン**: async/await を使用するが try/catch なし
- **影響**: 未処理の Promise rejection、スタックトレース漏洩
- **対策**: 共通のエラーハンドラー or axios interceptor を設定

## 3. `var` の残存
- **影響**: ブロックスコープではなく関数スコープになる
- **対策**: `const` を基本、再代入が必要な場合のみ `let`

## 4. ハードコードされた設定値
- **パターン**: API URL、ポート番号等がソースコードに直書き
- **影響**: 環境ごとの切り替えが不可、機密情報の漏洩リスク
- **対策**: `process.env` または設定ファイルから読み込み

## 5. オブジェクト shorthand 未使用
- **パターン**: `{ name: name, email: email }`
- **対策**: `{ name, email }` (ES6 shorthand)

## 6. 文字列結合によるURL構築
- **パターン**: `url + "/path/" + id`
- **対策**: テンプレートリテラル `` `${url}/path/${id}` `` または URL API
security-patterns.md
# セキュリティリスクパターン

## 🔴 Critical

### 1. 機密情報のログ出力
- **パターン**: `console.log` にパスワード・トークン等を含める
- **影響**: ログ収集ツールに永続的に記録される。GDPR/個人情報保護法違反のリスク
- **検出方法**: `console.log` の引数に `password`, `token`, `secret`, `key` が
  含まれていないか確認
- **対策**: 機密情報は絶対にログ出力しない。専用のロガーでマスキングを実装

### 2. 未エスケープのユーザー入力によるURL構築
- **パターン**: `url + "?q=" + userInput`
- **影響**: URLインジェクション、意図しないAPIエンドポイントへのアクセス
- **対策**: `URLSearchParams` または `encodeURIComponent()` を使用

### 3. 平文パスワード送信
- **パターン**: パスワードをそのままHTTP POSTで送信
- **影響**: 中間者攻撃でパスワード傍受可能(特にHTTP通信時)
- **対策**: HTTPS必須化、サーバー側でのbcryptハッシュ化を確認

## 🟡 Important

### 4. HTTP通信(非HTTPS)
- **パターン**: `http://localhost:3000` がハードコード
- **影響**: 本番環境でも HTTP が使用される可能性
- **対策**: 環境変数で URL を管理し、本番は HTTPS を強制

このようにエージェントが「200行制限」を見越して、自主的にファイルを分離する構成を取ったのは興味深い結果です。

2回目:メモリは本当に活きるのか?

同じパターンの問題を仕込んだ別ファイル src/product-service.ts を作成し、再度レビューしました。

claude --agent code-reviewer -p "src/product-service.ts をレビューして。過去のメモリを参照して、前回と同じパターンの問題がないか確認して。新しい発見があればメモリを更新して。"

結果(抜粋):

前回の user-service.ts と今回の product-service.ts で、83%(12件中10件)が同一パターンの問題です。 これは個別ファイルの修正ではなく、チーム全体のアプローチで対処すべきです。

1回目では「このファイルにはこういう問題がある」という個別の指摘でしたが、2回目では 「前回と同じパターンが繰り返されている → チーム全体の問題」 というレベルに分析が引き上がっています。

MEMORY.md も更新され、以下のセクションが追加されていました:

### チーム全体の傾向
- **同一パターンの問題が複数ファイルで再発**: user-service.ts と product-service.ts で83%の問題が共通
- **根本原因**: コーディング規約が未整備 or 浸透していない可能性が高い
- **推奨**: ESLint ルール強化(`no-explicit-any`, `no-var`, `no-console`)+ PR レビューチェックリスト導入

## レビュー履歴
- `src/user-service.ts`: 12件の指摘(Critical 3, Important 5, Recommended 4)
- `src/product-service.ts`: 12件の指摘(Critical 3, Important 5, Recommended 4)← 前回と83%同一パターン

これがメモリの真価です。1回目の知識が2回目に活き、単なるファイル単位のレビューから、プロジェクト横断的な分析 へと進化しています。

CLAUDE.md との違い

CLAUDE.md memory frontmatter
対象 全セッション・全エージェント 特定のエージェントのみ
粒度 プロジェクト単位 エージェント単位
ロードタイミング セッション開始時 エージェント実行時
誰が管理するか 人間が手動管理 エージェント自身が管理
上限 なし(大きいとコンテキスト圧迫) 先頭200行で自動キュレーション
スコープ選択 ユーザー / プロジェクト user / project / local

使い分け:

  • CLAUDE.md: 「TypeScript + React を使う」「テストは vitest」のようなプロジェクト全体の指針
  • memory frontmatter: 「レビューで見つけたこのプロジェクト特有のパターン」のようなエージェント固有の学習データ

両者は排他ではなく、併用が前提です。CLAUDE.md で全体方針を定め、各エージェントが memory で専門知識を深めていくイメージです。

注意点

200行制限

MEMORY.md は先頭200行のみシステムプロンプトに注入されます。超えた場合はエージェントに自動でキュレーション(整理・要約)の指示が出ますが、情報を別ファイルに分離する運用も有効です。

.claude/agent-memory/code-reviewer/
  ├── MEMORY.md          # 先頭200行がシステムプロンプトに注入
  ├── patterns.md        # 詳細パターン集(必要時に Read で参照)
  └── known-issues.md    # 既知の問題リスト

メモリ書き込みは自動ではない

プロンプトに「メモリを更新して」という指示を必ず含めてください。指示がないとエージェントはメモリに書き込まず、何も蓄積されません。

バージョン管理

  • project スコープ: .claude/agent-memory/ に保存 → git コミット可能(チーム共有向き)
  • local スコープ: .claude/agent-memory-local/ に保存 → 自動で gitignore

対応バージョン

Claude Code 2.1.33 以降が必要です。

claude --version
# 2.1.33 以上であることを確認

まとめ

memory frontmatter を使えば、サブエージェントに「経験」を持たせることができます。

  • frontmatter に memory: user|project|local1行追加するだけ
  • MEMORY.md を通じてセッションをまたいだ知識が蓄積される
  • ただし書き込みは自動ではない → プロンプトで「メモリに記録して」と指示する

特にコードレビューやアーキテクチャ分析のように「繰り返し実行して知識を深めていく」タスクに向いています。使い込むほど、そのプロジェクトに精通したエージェントに育っていきます。

参考リンク

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?