auto-compact後のClaude Codeが設計ルールを忘れる — PreCompact Hookで記憶を引き継ぐ実装ログ

「CLAUDE.mdに書いてあるルールなのに、長いセッションの後半でなぜか守られなくなる」——Claude Codeを毎日動かしていると、この経験が必ず来ます。
結論から言うと、問題はCLAUDE.mdのルールが「消えた」のではなく、そのルールを「どう適用するか」のセッション内コンテキストが圧縮されたことにあると気づきました。そして最初に入れたPreCompact hookは「自分(人間)のリカバリ手段」でしかなく、Claude側の動作は変わりませんでした。この記事は、その気づきと切り替え後の設計を実装ログとして公開します。
結論:2種類のPreCompact hookは目的が違う
| 種類 | 目的 | Claudeの動作への影響 |
|---|---|---|
| バックアップ型(ファイルコピー) | 人間が圧縮前の文脈を読み返せる | ない(Claudeの状態は変わらない) |
| ルール注入型(stdout出力) | 圧縮サマリーに有効制約を含める | ある(Claudeが要約に含める) |
2026-05-14にバックアップ型を入れて「解決した」と思っていたが、これは人間側のリカバリ手段だった。Claudeが「なぜこのルールが今のタスクで重要か」を要約に含めるには、注入型が必要だと判断しました。
この記事の前提
- Claude Code を sns-automation・masatoman.net のルーティンで 2026-05 から daily 運用
- 複数リポジトリを1セッションで横断するため、長時間セッションが発生しやすい構成
- 2026-05-14 に Stop/PreCompact/UserPromptSubmit の 3 hook を初期実装
- CLAUDE.mdベースの設計ルール(slug変更禁止・CTA 1つ制限・ターゲット定義など)を運用中
読者のよくある詰まり
「CLAUDE.mdに書いてあるのに compact 後は無視される」——実際には、この認識は半分正確で半分ズレています。
CLAUDE.mdのルール自体は compact 後も消えない。 CLAUDE.mdはセッション開始時にシステムプロンプトとして読み込まれ、auto-compactで圧縮されるのは会話履歴であってシステムプロンプトではありません。
消えるのは「適用コンテキスト」。 「このタスクでは slug を変更しない」「今日の記事では CTA は NewsletterCTA だけにする」——そうした会話の中で積み上がった判断経緯・優先順位・制約の背景が、圧縮で要約に置き換わります。ルールの「文字」は残るが、それがなぜ今重要なのかの「文脈」が薄くなる。
実際に起きたこと
バックアップ型 hookを入れた後の限界
2026-05-14 の hook 実装時、まず入れたのは precompact-backup.sh——圧縮直前にセッションログを _inbox/ へコピーするものです。
# ~/.claude/hooks/precompact-backup.sh
#!/bin/bash
INBOX="$HOME/_inbox/claude-sessions"
mkdir -p "$INBOX"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
SESSION_LOG="$HOME/.claude/current-session.jsonl"
if [ -f "$SESSION_LOG" ]; then
cp "$SESSION_LOG" "$INBOX/session_${TIMESTAMP}.jsonl"
echo "PreCompact backup: $INBOX/session_${TIMESTAMP}.jsonl"
fi
これで「圧縮前に何を決めたか」を自分が読み返せるようになりました。ただ、この hook が動いても Claude 自身の挙動は変わりません。stdout に出した "PreCompact backup: ..." はステータス表示であり、Claude が要約時に参照するものではない。
気づき:「自分が読む」と「Claudeが要約に含める」は別
PreCompact hookのstdout出力がどう扱われるかを確認したことで、設計の方向性が変わりました。バックアップ型は「人間側のリカバリ」。Claude側に引き継ぐには、圧縮処理が参照できる形で有効制約を出力する必要があります。
原因分析:ルール喪失ではなく適用文脈の希薄化
auto-compact後のClaude動作を見ると、「ルールを守らなくなった」のではなく、**「今このタスクでのルールの重み付けが変わった」**ように見えます。
CLAUDE.md を読んでいれば「slug は変更しない」と知っている。しかし「なぜ今日の記事で特にそれが重要か(過去の SEO 事故の経緯 / 今回の実験条件)」は会話の中にある。圧縮後のClaudeは、ルールは知っているが適用の優先度判断に使う文脈が薄くなっています。
判断軸:どちらの hook が必要か
| 状況 | 必要なアプローチ |
|---|---|
| 圧縮前の詳細ログを人間が読み返したい | バックアップ型(ファイルコピー) |
| 圧縮後もClaudeが設計判断の優先度を維持してほしい | ルール注入型(stdout出力) |
| 両方必要 | 両方を hooks 配列に並べる(Claude Codeは複数hookを順次実行) |
バックアップ型は「事後リカバリ」、注入型は「状態維持」。用途が違うので、排他選択ではなく併用が自然です。
ルール注入型の実装方針
# ~/.claude/hooks/precompact-active-rules.sh
#!/bin/bash
# active-rules.md(現在タスクで有効な制約)をstdoutに出力する
# PreCompact時にClaudeがこの内容を要約に含める
ACTIVE_RULES="${PWD}/active-rules.md"
if [ -f "$ACTIVE_RULES" ]; then
echo ""
echo "=== CompactサマリーへのActive Rules注入 ==="
cat "$ACTIVE_RULES"
echo "==="
fi
// ~/.claude/settings.json(hooks部分の抜粋)
{
"hooks": {
"PreCompact": [
{
"type": "command",
"command": "bash ~/.claude/hooks/precompact-backup.sh"
},
{
"type": "command",
"command": "bash ~/.claude/hooks/precompact-active-rules.sh"
}
]
}
}
active-rules.md は CLAUDE.md とは別に、今このセッションで特に有効な制約を書く小さなファイルです。セッション開始時に更新し、PreCompact時にClaudeの要約生成へ含める意図で渡します。CLAUDE.mdの「全ルール」を渡すのではなく、今の優先度に絞った制約リストにすることで要約が薄まるのを防ぎます。
今日やること(3つ以内)
- バックアップ型hookだけ入れている場合:それが「人間側のリカバリ」だと認識して、Claude側の挙動改善には別アプローチが必要だと理解する
- active-rules.mdを用意する:CLAUDE.mdとは別に、今のセッションで最重要な制約を3〜5行で書いたファイルを作る
- PreCompact hookを配列で複数設定する:既存のバックアップhookに注入型を追加し、両方を並列で動かす
masatoman のメルマガ — 毎週月曜の朝に手紙を 1 通
masatoman.net の今週の記事 1 本を、読者目線で深掘りした手紙が毎週月曜 9:00 に届きます。「これ自分のことだ」が見つかる予告編。登録特典に「個人開発の収益化チェックリスト 15 項目」。
masatoman のメルマガ — 毎週月曜の朝に 1 通
masatoman.net で今週公開した記事の中から 1 本を、読者目線で深掘りした手紙が届きます。「自分も同じことやってる」「ここで詰まってた」が見つかる予告編。