このガイドは、Hidekazu Konishi 自身のサイトで、Claude Code のハーネスと環境のエンジニアリングに関するより広範な彼のガイドを深掘りする姉妹編として公開されたものであり、Claude Code におけるエージェントフックを強制のレイヤーとして扱い、端から端まで解説している。その前提は 2 つの文で述べられている。「システムプロンプトは要望である。フックは保証である。」フックとは、ユーザーが定義したコマンド(あるいは HTTP エンドポイント、MCP ツール、サブモデルによる評価)であり、モデルではなくハーネスが、ツールと会話のライフサイクルの決まった時点で実行する。そのため、プロンプトが確率的でしかないところで、強制が決定論的になる。

このガイドは settings.json とコンポーネントのフロントマターを通じて CLI 向けに設定されるフックを対象としており、イベント名、入力フィールド、終了コードの意味、JSON フィールドは執筆時点で公式のフックリファレンスと照合済みだと述べている。イベントの種類は増え続けているため、そのリファレンスを正とするとしている。想定読者は、プラットフォームエンジニアやセキュリティエンジニア、そして決定論的なガードレールを手放さずにエージェントを自律的に動かしたい開発者である。

要点

  • ガイドはフックイベントをターンの各フェーズに対応づけている。すなわち、セッション、プロンプト、ツール呼び出しごとに繰り返されるツールループ、サブエージェントとタスク、コンテキストのコンパクション、ターンの終了、そして表示・ファイル・MCP のイベントである。執筆時点でイベントはおよそ 30 あり、そのうち実際に大半の役割を担うのは一握り(PreToolUse、PostToolUse、UserPromptSubmit、Stop、SessionStart、SubagentStop、PreCompact)だとしている。
  • PreToolUse を最も強力な制御面として説明している。そこからの deny はどのパーミッションモードのチェックよりも先に評価されるため、bypassPermissions の下でもツールをブロックする。一方で allow は対話的な確認をスキップするだけで、一致する deny や ask のルールを上書きすることはできない。つまり、フックはパーミッションシステムを厳しくすることはできても、緩めることは決してできない。
  • フックは 2 つのチャネルで応答する。1 つは終了コードで、2 はブロッキングエラーとなりその stderr が理由になり、それ以外の非ゼロのコードは非ブロッキングエラーとなる。もう 1 つは標準出力上の JSON オブジェクトである。判断を下せるイベントの多くはトップレベルの decision: "block" を使うが、PreToolUse は hookSpecificOutput.permissionDecision に allow、deny、ask、defer のいずれかを指定する。ガイドは、この 2 つの形式の混同こそが最もよくあるフックのバグだとしている。誤った形式は何も起こさず黙って無視されるからである。
  • すべてのイベントが終了コード 2 でブロックするわけではない。PostToolUse では stderr をモデルに見せるだけであり、SessionStart のような情報提供のためのイベントでは何もブロックしない。UserPromptSubmit、UserPromptExpansion、SessionStart からのプレーンテキストの標準出力はモデルのコンテキストに注入され、ガイドはこれをコンテキストを追加する最も簡単な方法として紹介している。
  • 英字、数字、_、| だけからなるマッチャーは完全一致であり、それ以外はすべて JavaScript の正規表現として扱われる。ガイドは、これが MCP ツールにもたらす罠を指摘している。mcp__memory は mcp__memory__create_entities に決して一致しないので、サーバー全体に一致させるには mcp__memory__.* のようなパターンが必要になる。
  • すべての設定レイヤーのフックは、Managed > Local > Project > Plugin > User という解決順序でマージされる。そのため、マネージドポリシー設定にあるフックはユーザーが上書きできず、allowManagedHooksOnly: true はユーザー、プロジェクト、プラグインのフックをすべてブロックする。スキルやサブエージェントもフロントマターにフックを持つことができ、それはそのコンポーネントが読み込まれている間だけ有効になる。
  • 5 つのハンドラーの種類として、command、http、mcp_tool、prompt(Claude モデルが Yes/No の質問に答える)、そして実験的な agent を挙げている。実例としては、書き込み後の自動フォーマット、シークレットの編集や破壊的なシェルコマンドの拒否、非同期の監査ログ、コミットされていない変更がある間はターンの終了を一度だけブロックする Stop フック、セッション開始時のリポジトリ状態の注入、自動コンパクションの前のメモのチェックポイント、デプロイ凍結期間中のプロンプトの拒否、そして updatedInput による force-push の --force-with-lease への書き換えを示している。
  • 1 つの要件に対する 3 つの制御面を区別している。CLAUDE.md はモデルがたいていは従うガイダンスであり、パーミッションは決定論的で静的な許可/拒否のレイヤーであり、フックは内容を検査したり、ポリシーサービスを呼び出したり、呼び出しを書き換えたりできるプログラム可能な強制である。ガイドの言い回しでは「CLAUDE.md は説得し、パーミッションはふるいにかけ、フックは強制し反応する」のであり、堅牢な構成ではこの 3 つすべてを動かす。
  • そのセキュリティモデルは、フックがユーザーのシェル権限をすべて持って自動的に実行される任意のコードである、という点から出発する。クローンしたリポジトリの設定に含まれるフックは Makefile や postinstall スクリプトと同じようにレビューすべきであり、書き換えを行うフックはツール呼び出しの作成者となるためフック一式の中で最も安全性が重要なコードであり、http フックはフックの入力をマシンの外へ送り、監査ログにはシークレットが含まれうる。
  • 挙げられている落とし穴には、一致するすべてのツール呼び出しで実行される遅い同期フック、1 で終了してしまい結果として操作を通してしまうガード、終了条件のない Stop フックが永遠にループすること、サブエージェントがメインエージェントと同じように振る舞うと思い込むこと、そしてたまに見逃しても大した損失にならない好みの事柄にまでフックを掛けすぎることがある。

背景

このガイドは、Claude Code のハーネス、設定、サブエージェント、CI での利用を扱う同じ著者によるシリーズの 1 本として位置づけられており、対象を CLI 向けのフックに限定している。Claude Agent SDK のプログラムからのフックインターフェースは、著者の別の記事に委ねられている。正規表現ベースのシークレットとコマンドのガードについては、完全なセキュリティ境界ではなく多層防御として提示している。意図を持った攻撃者であれば、コマンドを難読化して正規表現をすり抜けることができるからである。