Claude Codeの永続メモリ:セッションをまたぐコンテキストの実際の仕組み
金曜日、あなたは三時間のセッションを終えてノートパソコンを閉じます。その間にClaude Codeは認証モジュールをリファクタリングし、チームでは例外を投げる代わりに独自の Result<T> ラッパーを使っていることを学び、さらに、なぜ UserService が次のモジュールからインポートできないのかをようやく理解しました。 billing/。月曜日に新しいセッションを開くと、Claudeは自信満々に新しい関数をtry/catchで囲み、禁止されたモジュールをインポートします。学んだことはすべて失われています。
これこそが、エージェント型コーディングツールの使い勝手を左右する問題です。モデルにはエピソード記憶がありません。毎回のセッションは、ゼロの状態に手動で書き残した情報を加えたところから始まります。うまくいかない部分も含めて率直に見ながら、技術的な工夫でこの問題を解決していきましょう。
根本的な問題:セッションは設計上ステートレス
Claude Codeのセッションは会話です。終了すると会話記録はアーカイブされ、作業中のコンテキスト、つまり何十回ものツール呼び出しを通じて積み重ねられた理解は消えてしまいます。次のセッションは、次の三つの情報源からコンテキストを再構築します。
- あなたの
CLAUDE.mdfiles (project and user scope) - セッション中にClaudeが読むファイル
- あなたが入力する内容
これらはいずれも、 作業を通じて得られた 知識を記録していません。すでに試して行き詰まった方法、奇妙な回避策が存在する理由、方法Aを試したらCIが失敗したという事実などです。その知識を再び導き出すために、毎回のセッションでトークンと実時間を費やすことになります。
自然に思いつくのは、メモリ層を構築することです。起きたことを記録し、圧縮し、起動時に関連する部分を再び注入します。オープンソースの claude-mem プロジェクトは、まさにこのパターンの明快な参考実装であり、採用するかどうかにかかわらず、研究する価値があります。
Claude Codeの永続メモリを支えるアーキテクチャパターン
Claude Codeの永続メモリに本格的に取り組む方法は、いずれも同じ段階的なループに従います。各段階を個別に理解すれば、それぞれを自作するか、購入するか、省略するかを判断できます。
段階1:キャプチャ
セッションで何が起きたかを観測する必要があります。Claude Codeはライフサイクルの フック を公開しています。これはイベント発生時に実行されるシェルコマンドです。関連するものは次のとおりです。
| フック | 実行タイミング | 用途 |
|---|---|---|
SessionStart | セッションの開始時 | メモリの注入 |
SessionEnd | セッションの終了時 | キャプチャの起動 |
PostToolUse | 各ツール呼び出しの後 | 詳細なアクティビティのストリーミング |
Stop | エージェントの応答完了時 | チェックポイント |
次の場所に設定する最小限のキャプチャフック .claude/settings.json:
{
"hooks": {
"SessionEnd": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/mem/capture.sh"
}
]
}
]
}
}
フックは、イベントを記述するJSONを標準入力で受け取ります。 SessionEnd ではセッションIDとトランスクリプトのパスを取得できるため、 capture.sh で会話ログ全体を読み取れます。
#!/usr/bin/env bash
INPUT=$(cat)
TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
# Hand the raw transcript to the compression stage
python3 "$CLAUDE_PROJECT_DIR/.claude/mem/compress.py" \
--transcript "$TRANSCRIPT" \
--session "$SESSION_ID"
よくある落とし穴として、フックにはタイムアウトがあり、大きなトランスクリプトを同期的にLLMへ渡すと制限時間を超えてしまいます。実際には、キャプチャは実行後に完了を待たない方式にするのが望ましいです。フック内で直接処理するのではなく、トランスクリプトのパスをキューに書き込み、バックグラウンドワーカーで処理します。
段階2:圧縮
生のトランスクリプトはメモリとして役に立ちません。巨大で、ファイルのダンプ、大量のツール出力、入力ミスといったノイズが多すぎるからです。圧縮段階ではLLMを使い、セッションから長く使える事実を抽出します。ここではOpusではなくHaiku 4.5を呼び出します。要約はまさに、Haikuの料金設定が想定する、大量に発生する失敗の影響が小さいタスクです。
import anthropic
client = anthropic.Anthropic()
PROMPT = """You are a memory compressor. From this coding session
transcript, extract ONLY durable facts worth remembering next session:
- Architectural decisions and their rationale
- Conventions discovered (naming, error handling, imports)
- Dead ends already explored (so we don't repeat them)
- Unresolved TODOs
Output JSON: a list of {fact, category, files[], confidence}.
Omit anything transient. If nothing durable happened, output []."""
resp = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1500,
system=PROMPT,
messages=[{"role": "user", "content": transcript_text}],
)
memories = resp.content[0].text
次の confidence フィールドと、次を出力するよう明示した指示に注目してください。 []どちらも、後述する失敗パターンの被害を抑えるための対策です。出力は検索可能な場所に保存します。埋め込み列を持つSQLiteや、プロジェクトとファイルパスをキーとするベクトルストアなどです。
段階3:注入
セッション開始時に、関連するメモリを取得して注入します。 SessionStart フックは標準出力に書き込むことができ、その出力はClaudeのコンテキストに追加されます。
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/mem/inject.sh" }
]
}
]
}
}
エンジニアリング上の重要な判断は、 関連性によるフィルタリングです。すべてのメモリを注入するのは単純な方法ですが、誤りです。コンテキストが膨れ上がり、有用な事実が埋もれてしまいます。よりよい方法は、そのセッションで扱いそうな内容に基づいて取得することです。まだ判断できない場合は、確信度の高いプロジェクト全体の事実だけを注入し、それ以外は MCPサーバー を通じて公開して、Claudeが必要に応じてメモリを検索できるようにします。
# A tiny MCP tool the agent calls when it wants history
@mcp.tool()
def recall(query: str, files: list[str] = []) -> list[dict]:
"""Retrieve relevant memories about this codebase."""
return memory_store.search(query, files=files, min_confidence=0.6)
実際には、このプル型モデルがプッシュ型モデルより優れています。起動時に何が関連するかを推測する代わりに、必要になったその時点で、エージェントが「この課金コードを以前に扱ったことがあるか」と尋ねられるようにします。フックは常時参照する小さな要約を投入し、MCPサーバーは対象を絞った想起を担います。
どこで破綻するのか――実際に破綻します
私はメモリ層を十分長く運用してきたため、その信頼性には懐疑的です。失敗パターンは現実に存在し、積み重なっていきます。
AIが圧縮したメモリはハルシネーションを起こします。 圧縮を行うのも言語モデルです。実際には却下された案を「決定事項」として記録したり、選択の根拠を逆に捉えたりすることがあります。すると、もっともらしい誤ったメモリが起動時に注入され、エージェントはそれを必要以上に信用してしまいます。確信を持って間違えるため、メモリがない場合より悪い状態です。 confidence フィールドと、人によるメモリストアのレビューだけが、実効性のある緩和策です。
古くなったコンテキストは、気づかないうちに深刻な問題を引き起こします。 火曜日に次をリファクタリングしたとします。 UserService 月曜日のメモリには、依然として「認証処理は次の場所にある」と記録されています。 UserServiceこれを無効化する仕組みはありません。コードが変わった瞬間からメモリの正確さは損なわれ、有効期限切れにするための明確なシグナルもありません。メモリをファイルハッシュやコミットSHAに紐付け、元のファイルが移動したら、そのメモリを疑って扱ってください。
トークンコストはセッションごとに増えます。 注入されたメモリは、使われるかどうかにかかわらず、毎ターン料金が発生するコンテキストです。起動時に4Kトークンを注入するメモリ層は、セッション全体を通じて、その分を入力コストに上乗せします。プル型のMCPモデルは役立ちますが、キャプチャと圧縮にもそれぞれ継続的な費用がかかります。
率直に比較すると、次のようになります。
| アプローチ | 導入コスト | 継続的なトークン消費 | 情報が古くなるリスク | 適した用途 |
|---|---|---|---|---|
CLAUDE.md のみ | 数分 | 少なく、予測可能 | 自分で管理可能 | ほとんどのプロジェクト |
| 対象範囲を限定したMCPツール | 数時間 | 必要なときのみ | 低い | リアルタイムのシステム状態 |
| 完全なメモリ層 | 数日 | 多く、セッションごとに発生 | 高い | 長期にわたる探索的な作業 |
受け入れにくい事実:おそらく必要ありません
こうした仕組みを作る前に、まず適切な CLAUDE.mdを書いてください。手作業で整えたファイルに「私たちは次を使い、 Result<T>決して例外をスローしない。 UserService は次をインポートしてはならない。 billing/認証処理は次の場所に移動した。 auth/ 移動時期は第2四半期」と記すだけで、ハルシネーションのリスクなく、予測可能なコストでメモリ問題の80%を解決できます。人が書くため、その成り立ちから信頼できます。
メモリ層がコストに見合う価値を発揮する範囲は、宣伝で語られるより狭いものです。それは、長期にわたる探索的な作業で、 作業を通じて得られた 知識、つまり行き詰まった試みや途中の調査を、まだ知らないために事前には本当に書けない場合です。通常の機能開発であれば、 CLAUDE.md と、対象範囲を限定したいくつかのMCPサーバーを組み合わせる方が、自動化されたメモリパイプラインより広く対応でき、しかも嘘をつきません。
パイプラインを構築する場合、コストへの配慮が最も重要になるのは圧縮段階です。Haikuで頻繁に要約しても費用は安く済みますが、それはそもそもトークン単価が妥当である場合に限ります。チームが、この種の大量のバックグラウンド処理をAI Prime Techのようなプロバイダー経由で実行する理由のひとつです。
実践上の要点
- セッションはステートレスです。 実際に失われるのは、行き詰まった試み、判断の根拠、慣習といった、作業から得られた知識です。そして、それを再び導き出すには大きなコストがかかります。
- 基本パターンは、キャプチャ → 圧縮 → 注入です。 キャプチャと注入を次の
SessionEnd/SessionStartフックで接続し、フックのタイムアウトを避けるためにキャプチャを非同期で実行します。 - プッシュ型よりプル型を優先してください。 起動時にはごく小さな要約を投入し、その後、
recallMCPツールを公開して、関連する場合にだけエージェントがメモリを取得できるようにします。 - Haiku 4.5で圧縮し、すべてのメモリに確信度とソースファイルのハッシュを付け、ファイルが変わったらメモリを疑って扱ってください。
- 自動化されたメモリは嘘をつくことがあります。 ハルシネーションによるコンテキストや古くなったコンテキストは、権威ある情報として扱われるため、何もない場合より悪いものです。メモリストアの管理には人の確認を組み込んでください。
- まず
CLAUDE.mdを試してください。 ほとんどのプロジェクトでは、手書きのコンテキストファイルと対象範囲を限定したツールを組み合わせる方が、完全なメモリ層よりもコスト、信頼性、保守の面で優れています。永続化を導入するのは、作業が本当に長期的かつ探索的な場合に限りましょう。
Claude Opus 5.5、Sonnet 5、Haiku 4.5、Fable 5.1に加え、GPT-6のモデルを、単一のAPIキーで利用できます。従量課金制で、サブスクリプションは不要です。
APIキーを取得 →