Hooksでfrontmatter更新を強制する3層防御の設計
Claude Code hooks を「品質チェッカー」だと思って導入したのに、結局運用が破綻した経験はないでしょうか。私自身、最大の学びは hooks を 「Claudeへのフィードバック層」 として捉え直したことでした。本記事では、frontmatter 自動更新の運用ルールを AI コーディング 自動化 強制で徹底するための、3層防御の設計思想を、実装手順・落とし穴付きで共有します。
frontmatter 駆動運用の致命的弱点
私のモノレポでは、クライアント案件を YAML frontmatter で一元管理しています。各案件の CLAUDE.md 冒頭に、client / stage / next_action / next_action_by / session_at / amount_estimated / amount_actual / source といったメタデータを置き、AI参謀(私はArgusという名前のサブエージェントを置いています)がこれを「真実」として読みに来る構造です。
この設計は強力です。十数件並行する案件を、ダッシュボード無しでも frontmatter の一覧化だけで stage と next_action_by が見渡せる。期限切れ・見積待ち・納品後フォロー漏れの案件が、git管理下のテキストだけで完結する。
ところが運用2ヶ月で致命的な穴が表面化しました。frontmatter が古いまま放置されるのです。クライアントとのやり取りが進んでも、messages/ 配下に新しいmdが追加されるだけで、CLAUDE.md 冒頭の stage や next_action が更新されない。
結果、Argusは古い情報を一次情報として読み、誤った提案を返します。「期限超過」と警告された案件は前日に進行済み、「次は見積提示」と言われた案件は実は契約成立済み。鏡が曇ると、AIが映す判断もすべて曇るのです。
なぜfrontmatter 自動更新が習慣化しないのか
更新漏れの原因は、根性論ではなく構造にあります。私が自分の運用を分解したところ、4つの根本原因が見えてきました。
1. 更新タイミングがルール化されていない
「いつ更新すべきか」が言語化されていない。messages/に新規ファイルを置いた瞬間か、その日の終わりか、週末か。タイミングが曖昧だと「気づいたら数日経っていた」状態になります。
2. CLAUDE.mdを開いて編集する摩擦が高い
frontmatter の更新は「物理的に別のファイルを開く」作業です。messages/に書き込んだ直後に CLAUDE.md を開き直し、該当行を探し、stage や next_action を書き換える。この数十秒の摩擦が、人間の習慣化の最大の敵になります。
3. 自分の頭にあるから違和感なく動ける
これが最も厄介です。運用者本人は、frontmatter が古くても困らない。頭で覚えているからです。困るのは AI 秘書、つまりArgusだけ。自分一人では「曇った鏡」に気づけません。
4. messages/作成と CLAUDE.md 編集が連動していない
本来この2つは不可分なはずです。「メッセージ記録=関係性が動いた=frontmatterも動かす」のに、ツール操作上は独立した2つの編集作業になっている。連動を「人間の規律」だけに任せた時点で必ず破綻します。
frontmatter更新は意志の問題ではなく、システム設計の問題。これが私の結論でした。
解決策:3層防御で AI コーディング 自動化 強制を実現する
そこで設計したのが、ルール / PostToolUse Hook / Stop Hook の3層防御です。それぞれが異なるタイミングで異なる役割を担い、漏れを段階的に拾います。

Layer 1: ルール(教育・基盤層)
第1層は、Claude Code がプロジェクト起動時に必ず読み込む .claude/rules/client-project-structure.md に、frontmatter スキーマと更新タイミングを明文化します。
具体的には次のような記述を入れています。「frontmatter には client / source / stage / next_action / next_action_by / amount_estimated / amount_actual / session_at を必ず記載する」「messages/ に新規ファイルを置いたら、同じセッション内で必ず CLAUDE.md の stage と next_action を見直す」「stageの遷移は lead → estimate → negotiating → active → delivered の順で、戻ることはあっても飛ばさない」。
これは 教育・基盤層です。Claudeはプロジェクトコンテキストとしてこれを必ず読むので、行動方針として体に入る。ただしルールだけでは漏れは防げません。人間も AI も、忙しいときにルールだけでは動けない。だからこそ第2層、第3層が必要になります。
Layer 2: PostToolUse Hook(リアルタイムリマインダー層)
第2層は PostToolUse Hook です。これは Claude が Write / Edit / MultiEdit などのツールを実行した直後に、shell スクリプトを起動できる仕組みです。
私の設定では、Write/Edit が **/clients/**/messages/*.md や **/coconala/projects/**/messages/*.md 配下のファイルに触ったとき、hookが起動して次のメッセージをClaudeに返します。「messages/ を更新しました。同じプロジェクトの CLAUDE.md frontmatter(stage / next_action / next_action_by)を見直しましたか?必要なら今この場で更新してください」。
ポイントは2つです。1つ目、blockではなく reminderに留めること。完全blockすると対話のテンポを壊し、Claudeが脱線する原因になる。「気づかせて、判断はClaudeに委ねる」が正解です。2つ目、Claudeへのフィードバック層として設計すること。hookは人間に通知を出すツールではなく、AIに次のアクションを促すフィードバック信号として使うのが本質です。
Layer 3: Stop Hook(セッション終了時の監査層)
第3層は Stop Hook、セッションが終わるタイミングで起動します。これが最後の安全網です。
shellスクリプトで git diff を解析し、「messages/ 配下のファイルに変更があったプロジェクトを抽出」「同じプロジェクトの CLAUDE.md に変更がない」という条件で警告を出す。具体的にはこんなロジックです。
changed_msgs=$(git diff --name-only | grep "messages/.*\.md$")
projects=$(echo "$changed_msgs" | sed -E 's|/messages/.*||' | sort -u)
for p in $projects; do
if ! git diff --name-only | grep -q "^$p/CLAUDE.md$"; then
echo "WARN: $p の messages/ が更新されたが CLAUDE.md が未更新"
fi
doneセッション中はリアルタイムリマインダー(Layer 2)で促し、それでも漏れたものを Layer 3 が最後にすくい上げる。「促す→監査する」という二段構えで、人間の規律に頼らずに整合性を保つ仕組みになります。
Claude Code Hooks の基本仕様を整理する
3層防御の中核である Claude Code hooks の基本仕様を、ここで整理しておきます。これを押さえておかないと、Layer 2 / Layer 3 の設計で迷子になります。

定義場所と読み込み順
hookは settings.json(user / project / local の3スコープ)で定義します。例えばこんな構造です。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{ "type": "command", "command": "bash ~/.claude/hooks/check-frontmatter.sh" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "bash ~/.claude/hooks/audit-session.sh" }
]
}
]
}
}matcherには正規表現が使え、ツール名でフィルタできます。複雑なフィルタ(パス・引数)はshellスクリプト側でやる方が柔軟です。
主要イベントの使い分け
- PreToolUse: ツール実行 前。危険な操作のblock・パスのバリデーションに使う
- PostToolUse: ツール実行 後。今回のリマインダーや、副作用(lint・format・git status確認)の起点に使う
- UserPromptSubmit: ユーザー入力直後。プロンプトに自動でコンテキストを注入する用途
- Stop: セッション終了時。監査・サマリ・通知に使う
- SubagentStop: サブエージェント終了時。並列タスクの集約に使う
exit codeで挙動を制御する
hookのshellスクリプトはexit codeで挙動を変えられます。exit 0 は通常終了で stdout が context として Claude に渡る、exit 2 は非block警告、exit 1 で完全block(PreToolUseのみ)。今回のfrontmatterリマインダーは exit 0 で、stdout にClaudeへのリマインダー文章を出力する形にしています。
実装上の注意点:私が踏んだ落とし穴
3層防御を実装する過程で、いくつもハマりました。先回りして共有します。
過剰なblockは対話を阻害する
最初、私はPreToolUse hookで「frontmatter未更新を検知したらmessages/への書き込みをblock」する強硬策を試しました。結果、Claudeが書き込めずに同じトライを繰り返し、セッションが空転しました。blockは「絶対に通したくない操作」だけに留め、規律系はreminderに徹するのが鉄則です。
matcherを広げすぎると通知ノイズになる
逆に matcher を Write|Edit 全てに広げると、無関係なファイル更新でもリマインダーが飛び、Claudeのコンテキストが汚れます。shellスクリプト側で対象パスかをまず判定し、対象外なら無音でexit 0するのが必須です。
Stop hookは fault tolerance がすべて
Stop hookで git diff を見るとき、対象を絞り込まないと偽陽性が増えます。scripts/logs/ や assets/ は除外するなど、最初からフィルタを入れておく。1日10件偽陽性が出る監査hookは、3日で誰も読まなくなります。
なぜfrontmatter 自動更新が「鍵」なのか
ここまで実装の話を中心にしてきましたが、最後にもう一度「なぜそこまでして frontmatter を守るのか」に戻ります。

AIエージェントは frontmatter を「真実」として扱う
AIエージェントを業務に組み込むということは、「人間が頭の中で持っていた状態を、テキストとして外部化する」作業です。ダッシュボードを作る場合も、SaaSのDBを使う場合も、本質は同じ。AIに判断を委ねるなら、その判断材料が一次情報として整っていなければならない。
frontmatter駆動運用は、この「外部化」を最小コストで実現する手段です。git管理下、テキストエディタで編集可能、Markdown/YAMLという普遍フォーマット。SaaSロックインも、複雑なAPI連携もいりません。だからこそ、frontmatterの精度がそのまま AI 判断の精度になる。鏡が曇ったら、映る世界もすべて曇る。
「frontmatter更新の徹底」が AI 秘書運用の前提条件
私が今回のhooks整備で得た最大の学びは、「AI秘書を作る前にやるべきは、AIに見せる情報源を綺麗に保つ仕組み」だということでした。クラウド側でCronを回して定期的にレポートを送ってくる Routine 自動化は、その後の話です。手元の情報源が曇っているのに、クラウドで自動化しても、ノイズが量産されるだけになる。
ローカルのディシプリンが、AIの能力を解放する
AI コーディング 自動化 強制という言葉は、一見、ツールの話に見えます。しかし実態は運用のディシプリンの話です。hooksは「強制」のための機構ですが、その役割は人を縛ることではなく、「Claudeにフィードバックを返し続ける」こと。これに気づいてから、私は他の運用ルール(commit message規約、テスト実行、lint)も同じ思想で hooks 化するようになりました。
frontmatter 自動更新の徹底は、地味で派手さがありません。けれど、これを土台に置けるかどうかで、AI秘書を持てるか、AI付きの単なる便利ツールで終わるかが分かれます。クラウド側の派手な自動化に手を出す前に、まずローカルの規律を hooks で整える。これが、私が今いるフェーズで強くお勧めしたい順番です。
まとめ:3層防御を今日から始める手順
最後に、今日から始める手順をまとめます。
- Layer 1(ルール): 自分の運用で守りたいルールを
.claude/rules/*.mdに書く。frontmatterスキーマ・更新タイミング・stage遷移を明文化する - Layer 2(PostToolUse Hook): 対象ファイルが触られたら、Claudeにリマインダーを返すshellスクリプトを設置。blockではなくreminderに徹する
- Layer 3(Stop Hook): セッション終了時にgit diffを解析して、整合性が崩れている箇所を警告する。fault toleranceを高めにチューニング
hooksを「Claudeへのフィードバック層」として捉え、人間の意志ではなくシステムで規律を担保する。これが、frontmatter駆動運用を破綻させずに継続するための、私が辿り着いた答えです。
関連する仕組みについては、こちらの記事も合わせてどうぞ。
御社の業務に合わせたClaude Code導入支援
「AIツールを導入したが、現場で使われない」を終わらせる。
業務課題のヒアリングから設計、ハンズオン実践、運用定着まで一貫して支援します。