Skip to main content
例を含むクイックスタート ガイドについては、フックでアクションを自動化するを参照してください。
フックは、Claude Code のライフサイクル内の特定のポイントで自動的に実行されるユーザー定義のシェル コマンド、HTTP エンドポイント、MCP ツール呼び出し、LLM プロンプト、またはサブエージェントです。Claude Code は、ターミナルでのセッション、IDE 拡張機能、デスクトップアプリ、クラウドセッションなど、どこで実行されていても同じフック イベントを発火します。このリファレンスを使用して、イベント スキーマ、設定オプション、JSON 入出力形式、非同期フック、HTTP フック、MCP ツール フックなどの高度な機能を検索してください。 プラグインは、Claude Code が自身のプロセス内で呼び出す JavaScript 関数としてフックを登録することもでき、これによりイベントに応じて動作するだけでなく、インターフェースに描画することもできます。そうしたプラグインは mod であり、それらの関数フックについてはここではなくイベントに反応するで説明しています。このページで説明するフックは、mod と併用しても引き続き動作します。

フック ライフサイクル

Claude Code は、セッション中の特定のポイントでフックを実行します。イベントが発火して matcher がマッチすると、Claude Code はイベントに関する JSON コンテキストをフック ハンドラーに渡します。コマンド フックの場合、入力は stdin に到着します。HTTP フックの場合、POST リクエスト本体として到着します。ハンドラーは入力を検査し、アクションを実行し、オプションで決定を返すことができます。 イベントは 3 つのケイデンスに分類されます。
  • セッションごとに 1 回:SessionStart と SessionEnd
  • ターンごとに 1 回:UserPromptSubmit、Stop、StopFailure
  • エージェント型ループ内のすべてのツール呼び出しで:PreToolUse と PostToolUse。ただし、EndConversation の呼び出しは両方をスキップします
オプションの Setup から SessionStart に流れ込み、その後、UserPromptSubmit、スラッシュコマンド用の UserPromptExpansion、ネストされたエージェント型ループ(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)、Stop または StopFailure を含むターンごとのループ、その後 TeammateIdle、PreCompact、PostCompact、SessionEnd が続くことを示すフック ライフサイクル図。Elicitation と ElicitationResult は MCP ツール実行内にネストされ、PermissionDenied は auto モードでの拒否のための PermissionRequest からの副分岐、WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged、DirectoryAdded はスタンドアロンの非同期イベント、PreModelSwitch は要求されたモデル切り替えの前に実行されるスタンドアロンの逐次イベント、PostModelSwitch はセッションのモデルが変更された後に実行されるスタンドアロンの非同期イベント、MessageDisplay はアシスタントのメッセージ テキストのストリーミング中に実行される表示専用イベントとして示されていますオプションの Setup から SessionStart に流れ込み、その後、UserPromptSubmit、スラッシュコマンド用の UserPromptExpansion、ネストされたエージェント型ループ(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)、Stop または StopFailure を含むターンごとのループ、その後 TeammateIdle、PreCompact、PostCompact、SessionEnd が続くことを示すフック ライフサイクル図。Elicitation と ElicitationResult は MCP ツール実行内にネストされ、PermissionDenied は auto モードでの拒否のための PermissionRequest からの副分岐、WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged、DirectoryAdded はスタンドアロンの非同期イベント、PreModelSwitch は要求されたモデル切り替えの前に実行されるスタンドアロンの逐次イベント、PostModelSwitch はセッションのモデルが変更された後に実行されるスタンドアロンの非同期イベント、MessageDisplay はアシスタントのメッセージ テキストのストリーミング中に実行される表示専用イベントとして示されています
以下の表は、各イベントがいつ発火するかをまとめています。フック イベントセクションでは、各イベントの完全な入力スキーマと決定制御オプションについて説明しています。

フックがどのように解決されるか

イベント、matcher、ハンドラーがどのように組み合わさるかを理解するために、破壊的なシェル コマンドをブロックする次の PreToolUse フックを考えてみましょう。
matcher は Bash ツール呼び出しに絞り込み、if 条件は rm * にマッチする Bash サブコマンドにさらに絞り込むため、block-rm.sh は両方のフィルターがマッチするときのみ生成されます。
スクリプトは stdin から JSON 入力を読み取り、コマンドを抽出し、rm -rf が含まれている場合は permissionDecision として "deny" を返します。Claude Code が実行できるように、プロジェクト内の .claude/hooks/block-rm.sh に保存し、chmod +x .claude/hooks/block-rm.sh で実行可能にしてください。
このスクリプトは、JSON 入力を解析するこのページの他の Bash の例と同様に jq を使用します。試す前に jq をインストールし、PATH 上にあることを確認してください。
ここで、macOS/Linux の設定に対して Claude Code が Bash "rm -rf /tmp/build" を実行することにしたとします。以下が起こります。
フック解決の図:PreToolUse が発火し、matcher が Bash へのマッチをチェックし、次に if 条件が Bash(rm *) へのマッチをチェックします。両方がマッチすると、フック コマンドが実行されて permissionDecision として deny を返すため、ツール呼び出しはブロックされ、Claude Code は処理を続行します。いずれかのチェックがマッチしない場合、フックはスキップされ、ツール呼び出しの続行が許可されます。フック解決の図:PreToolUse が発火し、matcher が Bash へのマッチをチェックし、次に if 条件が Bash(rm *) へのマッチをチェックします。両方がマッチすると、フック コマンドが実行されて permissionDecision として deny を返すため、ツール呼び出しはブロックされ、Claude Code は処理を続行します。いずれかのチェックがマッチしない場合、フックはスキップされ、ツール呼び出しの続行が許可されます。
1

イベントが発火

PreToolUse イベントが発火します。Claude Code はツール入力を JSON として stdin のフックに送信します。
2

matcher がチェック

matcher "Bash" がツール名にマッチするため、このフック グループがアクティブになります。matcher を省略するか "*" を使用すると、グループはイベントのすべての出現でアクティブになります。
3

If 条件がチェック

if 条件 "Bash(rm *)" は rm -rf /tmp/build が rm * にマッチするサブコマンドであるためマッチし、このハンドラーが生成されます。コマンドが npm test だった場合、if チェックは失敗し、block-rm.sh は実行されず、プロセス生成のオーバーヘッドを回避します。if フィールドはオプションです。なければ、マッチしたグループ内のすべてのハンドラーが実行されます。
4

フック ハンドラーが実行

スクリプトは完全なコマンドを検査し、rm -rf を見つけるため、stdout に決定を出力します。
コマンドが安全な rm バリアント(rm file.txt など)だった場合、スクリプトは代わりに exit 0 に到達します。出力なしの終了コード 0 は、フックが報告する決定がないことを意味するため、ツール呼び出しは通常の権限フローを通じて続行されます。フックは呼び出しを拒否できますが、沈黙を保つことは承認を意味しません。
5

Claude Code が結果に基づいて行動

Claude Code は JSON 決定を読み取り、ツール呼び出しをブロックし、Claude に理由を表示します。
以下の設定セクションでは完全なスキーマについて説明し、各フック イベントセクションでは、コマンドが受け取る入力と返すことができる出力について説明しています。

設定

フックは JSON 設定ファイルで定義されます。設定には 3 つのネストレベルがあります。
  1. 応答するフック イベントを選択します(PreToolUse や Stop など)
  2. 発火するタイミングをフィルタリングする matcher グループを追加します(「Bash ツールのみ」など)
  3. マッチしたときに実行する 1 つ以上のフック ハンドラーを定義します
完全なウォークスルーと注釈付きの例については、上記のフックがどのように解決されるかを参照してください。
このページでは各レベルに特定の用語を使用しています。フック イベントはライフサイクル ポイント、matcher グループはフィルター、フック ハンドラーはシェル コマンド、HTTP エンドポイント、MCP ツール、プロンプト、または実行されるエージェントです。「フック」単独は一般的な機能を指します。

フック位置

フックを定義する場所によって、そのスコープが決まります。 クラウドセッションは、ローカルの ~/.claude/settings.json を読み取りません。セルフホスト環境では、Claude Code はオペレーターがランナーホストの ~/.claude/ に用意したフックも実行します。また、ランナーイメージの管理設定ファイルが Claude Code が適用する管理ソースに含まれる場合は、そのファイル内のフックも実行します。デフォルトでは、これはサーバー管理設定も MDM で配布された Claude Code ポリシーも管理層を提供していない場合に限られます。どの設定ファイルとプラグイン、つまりどのフックがクラウドセッションに届くかについては、セットアップから引き継がれるものを参照してください。 設定ファイル解決の詳細については、設定を参照してください。 設定ファイル、管理ポリシー設定、プラグインからのフックは、サブエージェント内でも実行されます。サブエージェントがツールを呼び出すと、PreToolUse や PostToolUse などのツールイベントはメインの会話と同じ設定済みフックを発火させ、入力にはサブエージェントを識別する agent_id と agent_type の共通入力フィールドが含まれます。 管理者は管理設定で allowManagedHooksOnly を使用して、実行されるフックを制限できます。
  • ユーザー、プロジェクト、ローカル、プラグインのフックはブロックされます。管理設定の enabledPlugins で強制的に有効化されたプラグインのフックは除外されます
  • Claude Code は、statusLine、fileSuggestion、subagentStatusLine の設定も管理設定のものに限定します
  • Claude Code は、command ソースを持つプラグインも無効化します。これには管理設定の enabledPlugins で強制的に有効化されたプラグインも含まれます。ただし、disableCommandPluginSources が明示的に false に設定されている場合は除きます。command ソースには Claude Code v2.1.229 以降が必要です
  • Claude Code は、マーケットプレイスの headersHelper コマンドもブロックします。ただし、disableCommandPluginSources が明示的に false に設定されている場合は除きます。また、管理設定自体が宣言しているマーケットプレイスは対象外です
allowManagedHooksOnly の下で実行されるものを参照してください。 フックエントリは、設定レベル間で互いに置き換えられるのではなくマージされます。ユーザー、プロジェクト、ローカルの設定は管理フックを削除せずに独自のフックを追加します。また、disableAllHooks 設定は、管理設定の外からは管理フックを無効化できません。 HTTP フックの許可リストは、管理ポリシー設定を含むすべてのソースからのフックに適用されます。
  • allowedHttpHookUrls: いずれかの設定レベルで定義されている場合、Claude Code は URL がマージされた許可リストに一致する HTTP フックハンドラーのみを実行します
  • httpHookAllowedEnvVars: 定義されている場合、Claude Code はそのリストにある環境変数のみをフックヘッダーに補間します

Matcher パターン

matcher フィールドは、フックが発火するタイミングをフィルタリングします。matcher の評価方法は、含まれている文字に依存します。 正規表現パス上の matcher は JavaScript の RegExp.prototype.test でテストされます。これは値内のどこかでマッチすると成功します。Edit.* は Edit と NotebookEdit の両方にマッチします。完全文字列マッチが必要な場合は、^Edit$ のようにパターンを ^ と $ でラップしてください。 FileChanged と StopFailure は、文字、数字、_、| のみの狭い完全一致セットを使用します。これら 2 つのイベントの matcher にハイフン、スペース、またはカンマがあると、正規表現パスに留まり、| のみが代替を区切ります。後続の表で matcher サポートを持つ他のすべてのイベントは | または , を受け入れます。 FileChanged イベントは監視リストを構築するときにこれらのルールに従いません。FileChangedを参照してください。 各イベント タイプは異なるフィールドでマッチします。 StopFailure を cloud_credential_error でマッチさせるには Claude Code v2.1.267 以降が必要です。これは、認証情報の読み込み失敗を server_error や unknown ではなくこの値で報告する最初のバージョンです。 ほとんどのイベントでは、Claude Code は、フックに stdin で送信する JSON 入力のフィールドに対して matcher を評価します。ツール イベントの場合、そのフィールドは tool_name です。PreModelSwitch と PostModelSwitch では、PreModelSwitch で説明しているとおり、Claude Code は to_model から導出した正規名に対して matcher を評価します。各フック イベントセクションでは、matcher 値の完全なセットとそのイベントの入力スキーマをリストしています。 この例は、Claude がファイルを書き込むまたは編集するときにのみ linting スクリプトを実行します。
matcher をサポートしないイベントに matcher フィールドを追加すると、サイレントに無視されます。 ツール イベントの場合、個別のフック ハンドラーで if フィールドを設定することで、より狭くフィルタリングできます。if は権限ルール構文を使用してツール名と引数を一緒にマッチするため、"Bash(git *)" は git * に一致する Bash 入力のサブコマンドのいずれかに対して実行され、"Edit(*.ts)" は TypeScript ファイルのみに対して実行されます。

MCP ツールをマッチ

MCP サーバー ツールはツール イベント(PreToolUse、PostToolUse、PostToolUseFailure、PermissionRequest、PermissionDenied)で通常のツールとして表示されるため、他のツール名と同じ方法でマッチできます。 MCP ツールは mcp__<server>__<tool> という命名パターンに従います。例えば、
  • mcp__memory__create_entities: Memory サーバーの create entities ツール
  • mcp__filesystem__read_file: Filesystem サーバーの read file ツール
  • mcp__github__search_repositories: GitHub サーバーの search ツール
サーバーのすべてのツールをマッチするには、サーバー プレフィックスに .* を追加します。.* は必須です。mcp__memory や mcp__brave-search のような matcher は完全一致文字のみを含むため、完全一致として比較され、どのツールにもマッチしません。
  • mcp__memory__.* は memory サーバーのすべてのツールにマッチ
  • mcp__brave-search__.* は名前にハイフンを含むサーバーのすべてのツールにマッチ
  • mcp__.*__write.* は任意のサーバーの、名前が write で始まるツールにマッチ
プラグイン バンドル MCP サーバーからのツールは、プラグイン名を含むスコープ付きサーバー セグメントを使用します。mcp__plugin_<plugin-name>_<server-name>__<tool>。ベア サーバー キーに対して記述された matcher は、これらのツールに対して発火しません。db キーの下でサーバーをバンドルする my-plugin という名前のプラグインの場合、query ツールは mcp__plugin_my-plugin_db__query として表示されるため、そのサーバーのすべてのツールの matcher は mcp__plugin_my-plugin_db__.* です。ハンドラーの if フィールドで同じスコープ付きツール名を使用します。スコープ付き名がどのように構築されるかについては、プラグイン提供 MCP サーバーを参照してください。 この例は、すべてのメモリ サーバー操作をログに記録し、任意の MCP サーバーからの書き込み操作を検証します。

フック ハンドラー フィールド

内側の hooks 配列の各オブジェクトはフック ハンドラーです。matcher がマッチしたときに実行されるシェル コマンド、HTTP エンドポイント、MCP ツール、LLM プロンプト、またはエージェントです。5 つのタイプがあります。
  • コマンド フック (type: "command"): シェル コマンドを実行します。スクリプトはイベントの JSON 入力を stdin で受け取り、終了コードと stdout を通じて結果を通信します。
  • HTTP フック (type: "http"): イベントの JSON 入力を HTTP POST リクエストとして URL に送信します。エンドポイントは、コマンド フックと同じ JSON 出力形式を使用して、レスポンス本体を通じて結果を通信します。
  • MCP ツール フック (type: "mcp_tool"): 設定済みの MCP サーバー上のツールを呼び出します。ツールのテキスト出力はコマンド フック stdout のように扱われます。
  • プロンプト フック (type: "prompt"): Claude モデルにプロンプトを送信して、単一ターンの評価を行います。モデルは決定を JSON として返します。プロンプト ベースのフックを参照してください。
  • エージェント フック (type: "agent"): Read、Grep、Glob などのツールを使用して条件を検証してから決定を返すことができるサブエージェントを生成します。エージェント フックは実験的であり、変更される可能性があります。エージェント ベースのフックを参照してください。
イベントが発火すると、マッチしたフックは並列で実行されます。そのうち 12 個を超えるフックがプロンプトフックまたはエージェントフックである場合、それらのうち 12 個が同時に実行され、残りは実行中のフックが終了するにつれて開始されます。待機中の各フックの timeout は、そのフックが開始した時点からカウントされます。 同じハンドラーを複数の設定ファイルで定義した場合、実行は 1 回だけです。プラグインまたはスキルが持つ同じハンドラーのコピーは別個のものとして扱われます。 ハンドラーは Claude Code の環境を持つ現在のディレクトリで実行されます。現在のディレクトリが存在しなくなった場合(たとえば、別のシェルがセッション中に削除した worktree や一時ディレクトリなど)、Claude Code は次のうち最初に存在するディレクトリからコマンドフックを実行します。セッションを開始したディレクトリ、プロジェクトルート、ホームディレクトリ、またはシステムの一時ディレクトリです。Claude Code は、フォールバック先のディレクトリ名を含む警告をデバッグログに記録します。デスクトップアプリから開始する worktree セッションについては、worktree がメインのチェックアウトと共有するものを参照してください。 $CLAUDE_CODE_REMOTE 環境変数はリモート Web 環境で "true" に設定され、ローカル CLI では設定されません。Claude Code v2.1.199 以降では、ローカルセッションにアクティブな Remote Control 接続がある間、$CLAUDE_CODE_BRIDGE_SESSION_ID が Remote Control のセッション ID に設定されます。

共通フィールド

これらのフィールドはすべてのフック タイプに適用されます。 if フィールドは正確に 1 つの権限ルールを保持します。ルールを組み合わせるための &&、||、またはリスト構文はありません。複数の条件を適用するには、各条件に対して個別のフック ハンドラーを定義します。 ファイルツールの if 条件では、"Edit(src/**)" のような単一セグメントのディレクトリパターンは、作業ディレクトリ内の src ディレクトリとその配下のファイルにのみマッチします。任意の深さにある src という名前のディレクトリにマッチさせるには、"Edit(**/src/**)" と記述します。

if パターンが Bash コマンドにマッチする仕組み

if フィールドの Bash パターンの場合、フック コマンドが実行されるかどうかは、パターンの形状と Claude が呼び出している Bash コマンドに依存します。先頭の VAR=value 割り当ては、マッチング前に削除されます。 Bash 入力がどのコマンドを実行するかを Claude Code が判断できない場合、パターンに関係なくフックを実行します。if フィルターはベストエフォートであるため、ハードな許可または拒否を強制するには、フックではなく権限システムを使用してください。

コマンド フック フィールド

共通フィールドに加えて、コマンド フックはこれらのフィールドを受け入れます。 コマンド フックは args が設定されている場合は exec フォームで実行され、args が省略されている場合はシェル フォームで実行されます。フックがパス プレースホルダーを参照する場合は常に args を設定してください。各要素は引用符なしで 1 つの引数として渡されるためです。パイプや && などのシェル機能が必要な場合、または両方の懸念が適用されない場合は args を省略してください。 Exec フォームは args が存在する場合に実行されます。Claude Code は command を PATH 上の実行可能ファイルとして解決し、args を引数ベクトルとして直接生成します。シェルがないため、各 args 要素は記述されたとおりに正確に 1 つの引数であり、${CLAUDE_PLUGIN_ROOT} などのパス プレースホルダーは command と各 args 要素にプレーン文字列として置換されます。アポストロフィ、$、バッククォートなどの特殊文字は、シェルが解釈しないため、そのまま渡されます。どのプラットフォームでもシェル トークン化は発生しません。 シェル フォームは args が存在しない場合に実行されます。command 文字列はシェルに渡されます。macOS と Linux では sh -c、Windows では Git Bash、または Git Bash がインストールされていない場合は PowerShell。shell フィールドを設定して明示的に選択します。シェルは文字列をトークン化し、変数を展開し、パイプ、&&、リダイレクト、グロブを解釈します。
Windows では、exec フォームは command が .exe などの実際の実行可能ファイルに解決されることが必要です。npm、npx、eslint、およびその他のツールが node_modules/.bin にインストールする .cmd と .bat シムは実行可能ファイルではなく、シェルなしで生成することはできません。exec フォームでそれらを実行するには、基になるスクリプトを node で直接呼び出します。例えば "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]。node プラス スクリプト パス パターンは、node.exe が実際のバイナリであるため、すべてのプラットフォームで機能します。.cmd または .bat シムを名前で実行するには、シェル フォームを使用します。
この例は、プラグインにバンドルされた Node スクリプトを実行します。Exec フォームは解決されたスクリプト パスを引用符なしで 1 つの引数として渡します。
同等のシェル フォームは、スペースまたは特殊文字を含むパスを処理するために引用符が必要です。
両方のフォームは同じパス プレースホルダーをサポートし、両方とも生成されたプロセスで環境変数 CLAUDE_PROJECT_DIR、CLAUDE_PLUGIN_ROOT、CLAUDE_PLUGIN_DATA としてエクスポートするため、スクリプトは起動方法に関係なく process.env.CLAUDE_PLUGIN_ROOT を読み取ることができます。 プラグイン フックは追加で ${user_config.*} 値を置換します。exec フォームのみ: 値は command と各 args 要素にプレーン文字列として置換されるため、シェルは再解析しません。 command が ${user_config.*} を参照するシェル フォームのプラグイン フックは、実行される代わりにエラーで失敗します。シェル フォーム フックからオプション値を使用するには、$CLAUDE_PLUGIN_OPTION_<KEY> 環境変数(webhook_url オプションの場合は $CLAUDE_PLUGIN_OPTION_WEBHOOK_URL など)を読み取るか、args を設定してフックを exec フォームに切り替えます。v2.1.207 より前では、シェル フォーム プラグイン フック コマンドも ${user_config.*} を置換していました。
Exec フォームでは、command は実行可能ファイル名またはパスのみです。args とともに使用される command がパス区切り文字を含まないベア名で、かつ空白を含む場合、生成が失敗するため Claude Code は警告をログに記録します。node script.js という名前の実行可能ファイルは存在しないためです。余分なトークンを args に移動してください。C:\Program Files\nodejs\node.exe などのスペースを含む絶対パスは、単一の有効な実行可能ファイルであり、警告をトリガーしません。

HTTP フック フィールド

共通フィールドに加えて、HTTP フックはこれらのフィールドを受け入れます。 Claude Code はフックの JSON 入力を Content-Type: application/json の POST リクエスト本体として送信します。レスポンス本体はコマンド フックと同じ JSON 出力形式を使用します。 エラー処理はコマンド フックと異なります。HTTP レスポンスの処理を参照してください。 この例は PreToolUse イベントをローカル検証サービスに送信し、MY_TOKEN 環境変数からのトークンで認証します。

MCP ツール フック フィールド

共通フィールドに加えて、MCP ツール フックはこれらのフィールドを受け入れます。 この例は、各 Write または Edit の後、my_server MCP サーバー上の security_scan ツールを呼び出し、編集されたファイルのパスを渡します。
Claude Code は、終了コード 0 の解析ルールに従い、コマンドフックの stdout と同じ方法でツールのテキストコンテンツを読み取ります。ツールが isError: true を返した場合、フックは非ブロッキングエラーを生成し、実行は続行されます。 PreToolUse や Stop など、フックが結果をブロックまたは変更できるイベントでは、Claude Code は接続中のサーバーを待ってからツールを呼び出します。待機時間は最大で MCP_TIMEOUT までで、フック自体の timeout の範囲内です。Notification や SessionEnd などの観察用イベントでは待機しません。 cached ステータスを表示しているサーバーは、フックがそのツールを呼び出したときに接続します。その時点でサーバーが接続されていない場合、フックは非ブロッキングエラーを生成し、実行は続行されます。フックが OAuth フローを開始することはないため、先に /mcp からサーバーを認証してください。 起動時の SessionStart(--continue や --resume の場合を含む)とすべての Setup イベントは、セッションの MCP サーバーがフックから利用可能になる前に発火します。Claude Code はツールを呼び出さずにこれらの mcp_tool フックをスキップし、デバッグログには mcp_tool hooks are not available for the 'SessionStart' hook event (no MCP client context)、または Setup を示す同じメッセージが記録されます。/clear やコンテキスト圧縮の後など、セッションの後半で SessionStart が再び発火した場合は、その mcp_tool フックが実行されます。セッションが起動時に必要とするものについては、代わりに SessionStart で type: "command" フックを使用してください。

プロンプト フックとエージェント フック フィールド

共通フィールドに加えて、プロンプト フックとエージェント フックはこれらのフィールドを受け入れます。

パスでフック スクリプトを参照

フックが実行されるときの作業ディレクトリに関係なく、プロジェクトまたはプラグイン ルートを基準にしてフック スクリプトを参照するには、これらのプレースホルダーを使用します。
  • ${CLAUDE_PROJECT_DIR}: セッションを開始したプロジェクトルート。Claude Code はこの変数を stdio MCP サーバーとプラグイン LSP サーバーの環境にも設定します。
  • ${CLAUDE_PLUGIN_ROOT}: プラグインのインストールディレクトリ。プラグインにバンドルされたスクリプト用です。更新時にこのパスがどう扱われるかについては、プラグインの環境変数を参照してください。
  • ${CLAUDE_PLUGIN_DATA}: プラグインの永続データディレクトリ。プラグインの更新後も保持すべき依存関係と状態用です。
worktree の場合は異なります。 セッション中に Claude が worktree に入った場合、Claude Code は ${CLAUDE_PROJECT_DIR} を元の場所のまま維持し、worktree のパスは別の方法でフックに渡します。
  • ${CLAUDE_PROJECT_DIR} は変わらない: セッションを開始したプロジェクトルートを引き続き指すため、${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh のようなコマンドは、引き続きメインのチェックアウト内のスクリプトを実行します。
  • cwd は Claude に追従する: フックの入力 JSON の cwd フィールドは、Claude が worktree に入った後はその worktree のルートになり、Claude が cd を実行した後は新しいディレクトリになります。Claude がどのディレクトリで作業しているかをフックが知る必要がある場合は、このフィールドを読み取ってください。
デスクトップアプリから開始する worktree セッションで ${CLAUDE_PROJECT_DIR} がどこを指すかについては、worktree がメインのチェックアウトと共有するものを参照してください。
パス プレースホルダーを参照するフックには exec フォームを優先してください。シェル フォームでは、各プレースホルダーをダブル クォートで囲みます。
この例は ${CLAUDE_PROJECT_DIR} を使用して、Write または Edit ツール呼び出しの後、プロジェクトの .claude/hooks/ ディレクトリからスタイル チェッカーを実行します。

スキルとエージェントのフック

設定ファイルとプラグインに加えて、フックはスキルとサブエージェントでフロントマターを使用して直接定義できます。設定形式は設定ベースのフックと同じです。Claude Code がこれらを登録しておく期間は、コンポーネントによって異なります。
  • サブエージェントのフック: Claude Code は、そのサブエージェントの実行中にのみこれらを実行し、サブエージェントが終了すると削除します。ここでの Stop フックは、Claude Code によって SubagentStop に変換されます。これはサブエージェントが完了したときに発火するイベントです。
  • スキルのフック: Claude Code は、ユーザーまたは Claude がスキルを呼び出したときにこれらを登録し、スキル自体のターンの後のターンも含めて、セッションの残りの期間ずっと実行し続けます。代わりに最初の実行が成功した後で Claude Code にフックを削除させるには、そのフックに once: true を設定します。
このスキルは、各 Bash コマンドの前にセキュリティ検証スクリプトを実行する PreToolUse フックを定義します。
サブエージェントは YAML フロントマターで同じ形式を使用します。 プロジェクトスキルのフロントマターのフックは、設定ファイルのフックと同じワークスペース信頼ルールに従います。Claude Code は、ユーザーまたは Claude がスキルを呼び出したときにこれらを登録します。これには、信頼していないフォルダーでの -p 実行も含まれます。 プロジェクトサブエージェントのフロントマターのフックは、エージェントファイルの取得元フォルダーについてワークスペース信頼ダイアログを承認した後にのみ実行されます。-p セッションは承認したことになりません。フォルダーを信頼する前に実行されるものではこれを設定ファイルのルールと比較しており、サブエージェントのページにはどのスコープが対象外かが記載されています。v2.1.218 より前は、これらのフックは信頼していないフォルダーからも実行される可能性がありました。

スキルのフックの制限

ユーザーまたは Claude がスキルを呼び出した後にスキルのフロントマターのフックが発火しない場合は、そのセッションで /hooks を実行します。それらのフックが一覧に表示される場合は、フックが発火しないを参照してください。いずれも表示されない場合、スキルがプラグイン専用ロックの対象になっているか、フックの上限を超えている可能性があり、そのスキルはフロントマターのフックを一切使わずに実行されます。それぞれのケースを確認してください。
  • プラグイン専用ロック: 組織の管理者は、strictPluginOnlyCustomization 管理設定を使用して、フックをプラグインと管理設定に限定できます。このロックの下でスキルがフロントマターのフックを保持できるのは、プラグインスキル、バンドルスキル、または管理設定ディレクトリ内のスキルである場合のみです。ユーザー自身の設定ファイルのフックも実行されません。
    • 確認: Claude Code セッションで /status と入力します。Setting sources 行に Enterprise managed settings が含まれている場合は、strictPluginOnlyCustomization がフックをロックしているかどうかを管理者に確認してください。
    • 対処: プラグインスキルはフロントマターのフックを保持するため、スキルをプラグインに移動します。そのプラグインをマーケットプレイスに掲載し、そこからインストールします。Claude Code が is blocked by enterprise policy でマーケットプレイスを拒否する場合は、そのマーケットプレイスを許可するよう管理者に依頼してください。
  • フックの上限: Claude Code v2.1.304 以降では、スキルのソースごとにセッション単位の上限があります。プロジェクト、個人のスキルフォルダー、各プラグインは、それぞれ別のソースとして数えられます。1 つのソースのスキルが登録できるフックは最大 1,024 個です。それらのフックの matcher の合計は最大 16,384 文字です。配下に複数のフックを持つ matcher は、フックごとに 1 回ずつ数えられます。
    • 確認: デバッグログを有効にして、フックが発火しなかったセッションを再現します。
      1. シェルから claude --debug で新しいセッションを開始します。シェルからセッションを開始しない場合は、代わりに新しいセッションで最初に /debug と入力します。
      2. Claude が呼び出したものも含め、同じスキルを同じ順序で呼び出します。両方の合計はスキルごとに積み上がるためです。コマンドとして入力できないスキルは、呼び出すよう Claude に依頼してください。
      3. デバッグログで registers none of its hooks を検索します。このテキストを含む行に、上限を超えたスキルの名前が示されます。
    • 対処: そのスキル、または同じソースの他のスキルで宣言するフックを減らすか matcher を短くしてから、新しいセッションを開始します。それらのスキルを自分で編集できない場合は、作成者に変更を依頼してください。それまでは、新しいセッションを開始し、必要なスキルを同じソースの他のスキルより先に呼び出してください。
どちらのケースにも当てはまらない場合は、解析されなかったフロントマターがないか確認してください。

/hooks メニュー

Claude Code で /hooks と入力して、設定されたフックの読み取り専用ブラウザーを開きます。リストでは、各フックにその取得元(ユーザー設定、プロジェクト設定、ローカル設定、プラグイン、現在のセッションなど)を示すラベルが付けられます。 フックを選択すると、そのフックが実行する内容の全文と、定義されている場所(設定ファイルのパスやプラグインの名前など)が表示されます。 フックが設定されていないものも含めてすべてのフック イベントを参照するには、リストの末尾にある All events を選択します。

フックを無効化または削除

設定ファイルで定義されたフックを削除するには、そのファイルからエントリを削除します。 すべてのフックを削除せずに一時的に無効化するには、設定ファイルで "disableAllHooks": true を設定します。Claude Code は設定の優先順位を適用した後に残る値を読み取るため、プロジェクトの .claude/settings.json にある "disableAllHooks": false は、ユーザー設定の true を上書きします。プロジェクトの設定内容にかかわらず 1 回の実行だけフックをオフにするには、--settings '{"disableAllHooks": true}' を渡します。これはプロジェクト設定とローカル設定よりも優先されます。個別のフックを設定に保持したまま無効化する方法はありません。 disableAllHooks 設定は管理設定階層を尊重します。管理者が管理ポリシー設定を通じてフックを設定している場合、ユーザー、プロジェクト、またはローカル設定で設定された disableAllHooks は、それらの管理フックを無効化できません。管理設定レベルで設定された disableAllHooks のみが管理フックを無効化できます。各レベルの影響範囲の詳細については、disableAllHooks を参照してください。 設定ファイルのフックへの直接編集は通常、ファイル ウォッチャーによって自動的に取得されます。

フック入出力

コマンド フックは stdin 経由で JSON データを受け取り、終了コード、stdout、stderr を通じて結果を通信します。HTTP フックは同じ JSON を POST リクエスト本体として受け取り、HTTP レスポンス本体を通じて結果を通信します。このセクションでは、すべてのイベントに共通するフィールドと動作について説明します。フック イベントの各セクションには、その特定の入力スキーマと決定制御オプションが含まれています。 macOS と Linux では、コマンド フックは制御ターミナルのない独自のセッションで実行されます。フック プロセスと子プロセスは /dev/tty を開くことも、エスケープ シーケンスを Claude Code インターフェイスに直接送信することもできません。Windows には /dev/tty がありません。 任意のプラットフォームでユーザーにメッセージを表示するには、JSON 出力で systemMessage を返します。一部のイベントはこれを破棄するか別の場所に配信します。その点は各イベントのセクションに記載されています。デスクトップ通知をトリガーしたり、ウィンドウ タイトルを設定したり、ベルを鳴らしたりするには、代わりに terminalSequence を返します。

共通入力フィールド

フック イベントは、各フック イベントセクションで説明されているイベント固有のフィールドに加えて、これらのフィールドを JSON として受け取ります。コマンド フックの場合、この JSON は stdin 経由で到着します。HTTP フックの場合、POST リクエスト本体として到着します。 agent_id と agent_type は、サブエージェント、インプロセスのチームメイト、--agent で選択したエージェントなど、フックがどのエージェント内で発火したかをスクリプトに伝えます。 SessionStart フックのみが model フィールドを受け取ることができ、Claude Code が常にそれを含めるとは限りません。PreModelSwitch と PostModelSwitch フックは代わりに from_model と to_model を受け取るため、セッション中に変化するモデルを追跡するには PostModelSwitch フックを使用してください。 $CLAUDE_MODEL 環境変数はありません。シェルで $ANTHROPIC_MODEL を設定した場合、フックはそれを読み取ることができますが、セッション中に /model でモデルを切り替えてもその値は変わりません。 フック プロセスは親環境を継承します。ただし、Claude Code が起動するすべてのサブプロセスから削除する OTEL_* エクスポーター変数と、CLAUDE_CODE_SUBPROCESS_ENV_SCRUB が 1 に設定されている場合に除去される変数は除きます。HIPAA 設定が適用されるセッションでは、Claude Code はフックの環境から Anthropic の認証情報も削除します。 例えば、Bash コマンドの PreToolUse フックは stdin で以下を受け取ります。
tool_name、tool_input、tool_use_id フィールドはイベント固有です。各フック イベントセクションでは、そのイベントの追加フィールドについて説明しています。

終了コード出力

フックの実行が完了すると、Claude Code はその終了コードを使用して、ツール呼び出しやプロンプトなど、フックをトリガーしたアクションを続行するかどうかを判断します。
  • 成功: フックが 0 で終了します。Claude Code はフックが出力した JSON 出力フィールドを適用し、それらのフィールドがアクションをブロックまたは拒否しない限り、アクションは進行します。例外についてはバックグラウンド プロセスを開始するフックを参照してください。
  • ブロッキング エラー: フックが 2 で終了します。ブロック可能なイベントでは、Claude Code はアクションを停止します。
  • 非ブロッキング エラー: フックがその他のコードで終了するか、起動しない、無効な JSON を出力するなど、その他の方法で失敗します。アクションは進行します。ただし、onFailure を "block" に設定したフックなど、失敗時にアクションをブロックするフックは例外です。PreToolUse などのイベントでは、トランスクリプトに <hook name> hook error 通知が表示されます。
フックが stdout に出力する内容によって結果が変わることがあります。例えば、PreToolUse フックが 1 で終了しても、検証に合格する JSON を出力した場合、その JSON によって何が起こるかが決まることがあります。PreToolUse などのイベントでフックの結果を確認するには、stdout に出力した内容を最初の列で、終了コードを上部の行で照合してください。 一部のイベントには独自のルールがあります。
  • WorktreeCreate: JSON の内容にかかわらず、0 以外の終了コードで worktree の作成が失敗します。
  • WorktreeRemove: 0 以外の終了コードは、その後もディレクトリが存在する場合に worktree の削除を失敗させます。
  • Stop、SubagentStop、TaskCompleted、およびプラグインの UserPromptSubmit フック: フックが stdout に何も出力せずに 2 で終了し、stderr に No such file or directory のようにファイルが見つからないことが示されている場合、Claude Code はその実行を非ブロッキング エラーとして扱います。
  • Elicitation と ElicitationResult: Claude Code はフックが 0 で終了した場合に hookSpecificOutput を適用し、その他の終了コードでは無視します。
  • StopFailure などフック出力を破棄するイベント: Claude Code はすべての終了コードで JSON を無視します。ただし、terminalSequence のような副作用フィールドは引き続き発火します。
イベントで終了コード 2 が何をするかはイベントごとの終了コード 2 動作を、どの決定フィールドが尊重されるかは決定制御を参照してください。

終了コード 0

終了 0 は成功を意味し、構造化制御のために JSON を出力する場合に想定される終了コードです。フックが 0 で終了しても、解析できない JSON やスキーマ検証に失敗する JSON を出力した場合、失敗時にアクションをブロックするフックでない限り、アクションは進行します。その実行は、フィールドが適用された成功ではなく、非ブロッキング エラーになります。 出力を修正するには、<hook name> hook error 通知に含まれる解析または検証のメッセージを使用してください。非同期でないフックの場合、stdout が JSON 出力として扱われるのは、1 行または複数行にわたる 1 つの JSON オブジェクトを、前後に空白以外何もない状態で出力した場合のみです。Claude Code はそれ以外の stdout をプレーン テキストまたは解析失敗として読み取ります。
  • { で始まらない出力、または { で始まり } で終わらない出力: プレーン テキストとして扱われます。このルールにより、JSON 配列や引用符で囲まれた JSON 文字列はプレーン テキストになります。
  • それぞれが単独で JSON として解析できる 2 行以上の出力で、最初の行が { で始まり最後の行が } で終わるもの: フィールドを設定する JSON 出力オブジェクトである行がない場合はプレーン テキストになります。そのような行がある場合、出力は解析失敗になるため、そのオブジェクトだけを stdout に出力してください。
  • { で始まり } で終わるが有効な JSON ではないその他の出力: 解析失敗になります。
ほとんどのイベントでは、Claude Code は stdout をデバッグ ログに書き込み、トランスクリプトには表示しません。例外は UserPromptSubmit、UserPromptExpansion、SessionStart、PostModelSwitch で、Claude Code はプレーン テキストの stdout を Claude が見て行動できるコンテキストとして追加します。これらのイベントでは、Claude Code は解析に失敗した stdout を追加しません。 終了 0 のフックからの stderr を Claude が見ることはありません。PreToolUse などのイベントで自分で読むには、デバッグ ログを有効にしてください。PostToolUse または PostToolUseFailure フックから Claude に警告を表示するには、代わりに終了 2 を使用してください。そうすれば、ツールがすでに実行されていても Claude は stderr を確認できます。

終了コード 2

アクションをブロックするには、コード 2 で終了します。ブロック可能なイベントでは、Claude Code はアクションを停止します。例えば、PreToolUse フックはツール呼び出しをブロックし、UserPromptSubmit フックはプロンプトを拒否します。 ブロックに伴うメッセージはフックの stderr です。フックがブロッキング決定を行う JSON も出力した場合、Claude Code は代わりにその決定の理由を使用します。 終了 2 は、フックが JSON を出力した場合でもブロックします。
  • スキーマ検証に合格する JSON: Claude Code は JSON 出力フィールドを引き続き読み取りますが、それらでブロックを上書きすることはできません。permissionDecision が "allow" であっても、アクションは通過しません。Elicitation と ElicitationResult では、終了 2 のフックの hookSpecificOutput は無視されます。
  • スキーマ検証に失敗する JSON: フックは引き続きブロックします。Claude Code は stderr をブロッキング理由として使用し、検証の失敗をデバッグ ログに記録します。
このスクリプトは終了 2 によって rm コマンドをブロックし、それ以外のすべてのコマンドは通常の権限フローに任せます。
このスクリプトを Bash の PreToolUse フックとして登録すると、rm で始まるコマンドはブロックされ、Claude はイベント名、ツール名、フックのコマンドがプレフィックスとして付いたフックの stderr を、ツールのエラーとして受け取ります。

その他の終了コード

Failed with non-blocking status code: を含む <hook name> hook error 通知は、フックの終了コードが 0 でも 2 でもなく、stdout がプレーン テキストまたは空だったことを意味します。失敗時にアクションをブロックするフックでない限り、これは非ブロッキング エラーであるため、フックはアクションを停止していません。通知に表示される最初の行だけでなくフックの完全な stderr を取得するには、デバッグ ログを有効にしてください。 例えば、Bash の PreToolUse フックが stderr に something broke を出力して 1 で終了した場合、PreToolUse:Bash hook error 通知には次の行が含まれます。
次の行のように通知にシェルの No such file or directory メッセージが含まれている場合、スクリプト パスが存在しないなどの理由で、フックは一度も実行されていません。
パスが間違っている場合は、フックが設定されている場所で修正してください。シェル形式では、スクリプト パスが存在しないか実行可能でない場合、シェルは 127 などのコードで終了し、通知にはインタープリターのメッセージが含まれます。失敗時にアクションをブロックするフックでない限り、起動できないフックも非ブロッキング エラーになります。 ポリシー フックを設定するときは、最初の実行時にこの通知に注意してください。settings.json でパスを入力ミスすると、フックは一度も実行されません。フックが起動できないときにアクションをブロックするには、onFailure: "block" を設定してください。
1 が従来の Unix 失敗コードであっても、有効な JSON 出力のない終了コード 1 は、失敗時にアクションをブロックするフックでない限り非ブロッキング エラーになります。フックがポリシーを実施することを目的としている場合は、exit 2 を使用してください。

タイムアウト

async: true で実行するコマンド フックを除き、Claude Code は timeout に達した command、http、または mcp_tool フックをキャンセルし、フックの出力を破棄します。そのため、ほとんどのイベントでは、タイムアウトしたフックは決定を下しません。PreModelSwitch では、タイムアウトでキャンセルされたフックはモデルの切り替えをブロックします。 PreToolUse では、タイムアウトした command、http、または mcp_tool フックはツール呼び出しをブロックしません。ただし、失敗時にアクションをブロックするフックは例外です。呼び出しは通常の権限フローを通じて続行されるため、停止したフックがゲートとして機能することを当てにしないでください。command または http フックがタイムアウトしたときに呼び出しをブロックするには、onFailure: "block" を設定してください。タイムアウトを超えた Agent SDK コールバック フックはツール呼び出しをブロックします。

バックグラウンド プロセスを開始するフック

コマンド フックがバックグラウンド プロセスで決定を行ってから終了する場合、Claude Code が読み取りを停止した後にそのプロセスが出力した deny はツール呼び出しをブロックしません。非同期でないフックの場合、Claude Code はフック自身のプロセスが終了した直後にフックの出力の読み取りを終えます。 バックグラウンド プロセスを開始する前に決定を出力し、そのプロセスの stdout と stderr をリダイレクトしてください。スクリプトが allow を出力した後、そのプロセスの stdout と stderr をリダイレクトせずにバックグラウンド プロセスを開始した場合、Claude Code はツール呼び出しをブロックします。フック エラーには refusing to honor the suspect capture が含まれます。 この PreToolUse フック スクリプトは policy-check.sh で決定を出力し、その後バックグラウンドでメトリクスをアップロードします。
スクリプトの残りの部分は次の処理を行います。
  • || exit $?: チェックの終了コードをフック自身の終了コードにします。これにより、拒否のために 2 で終了するチェックは引き続きブロックします。これがない場合、フックは最後の行の終了コード(0)で終了します。
  • >/dev/null 2>&1 &: 出力をリダイレクトした状態で upload-metrics.sh をバックグラウンドで実行するため、フックの出力が開いたままになりません。
スクリプトをテストするには、policy-check.sh が 2 で終了するようにしてから、フックが一致するツール呼び出しをトリガーします。ツール呼び出しはブロックされます。

フックが失敗したときにアクションをブロックする

ほとんどのイベントでは、フックが失敗またはタイムアウトしても Claude Code はアクションを実行するため、パスが間違っていたりスクリプトがクラッシュしたりするポリシー フックはすべてを通過させてしまいます。代わりにアクションをブロックするには、command または http フックに "onFailure": "block" を設定します。Claude Code v2.1.295 以降が必要です。
Git Bash のない Windows では、onFailure が未設定のシェル形式の PreToolUse または PermissionRequest コマンド フックが失敗した場合、代わりにツール呼び出しをブロックすることがあります。
.claude/settings.json 内のこの PreToolUse フックは、各 Bash コマンドの前にプロジェクト スクリプトを実行し、スクリプトが失敗した場合はコマンドをブロックします。
試すには、check-command.js を存在しない状態のままにして、Claude に ls などの Bash コマンドの実行を依頼します。Claude Code は呼び出しをブロックし、エラーには failed; blocking because onFailure is "block" と、それに続く node 自身のエラー出力が含まれます(ここでは 1 行に切り詰めています)。
タイムアウト後は、メッセージに failed ではなく timed out と表示されます。onFailure が設定されていない場合、同じスクリプトの欠落は非ブロッキング エラーとなり、ls は実行されます。 次のそれぞれが失敗としてカウントされます。
  • 起動できない: コマンド フックが起動に失敗する(例えば、スクリプトや実行可能ファイルが存在しないため)
  • 0 または 2 以外の終了コード: permissionDecision: "allow" のようにアクションを許可する JSON を出力した場合でも、コマンド フックでは失敗としてカウントされます。JSON の決定を返すには、0 で終了してください
  • HTTP エラー: HTTP フックの接続が失敗するか、レスポンスのステータスが 2xx ではない
  • タイムアウト: フックが timeout に達する
  • 無効な出力: JSON 出力が解析できないか、スキーマ検証に失敗する。HTTP フックの場合、空でも JSON オブジェクトでもない 2xx 本体も該当します。コマンド フックからのプレーン テキストの stdout は失敗ではありません
"block" を設定すると、失敗はそのイベントでの終了コード 2 と同じ動作をします。ただし PermissionRequest は例外で、リクエストを拒否します。例えば、PreToolUse の失敗はツール呼び出しをブロックし、UserPromptSubmit の失敗はプロンプトをブロックします。 このフィールドは次のフックには効果がありません。
  • Stop、SubagentStop、TaskCompleted、TeammateIdle フック: これらのイベントでの終了コード 2 は Claude を作業に戻しますが、Claude は実行されないフックを修復できません
  • バックグラウンド コマンド フック: async または asyncRewake を設定したコマンド フック

Git Bash のない Windows で失敗したフック

ブロックされたツール呼び出しのエラーに次のテキストが含まれている場合、PreToolUse または PermissionRequest コマンド フックが失敗またはタイムアウトし、呼び出しをブロックしています。
フックが失敗した理由を調べるには、デバッグ ログを確認してください。フックに合った修正方法を選んでください。
  • フックが失敗したときにアクションを進行させたい: フックに "onFailure": "continue" を追加します
  • フックが Bash 向けに書かれている: shell が設定されていないシェル形式のフックは、Git Bash がインストールされていない場合は PowerShell で実行され、Bash 向けに書かれたスクリプトはそのままでは実行できないことがあります。Git for Windows をインストールするか、Claude Code が見つけられない場所に Git Bash がインストールされている場合は CLAUDE_CODE_GIT_BASH_PATH を設定してから、新しいセッションを開始します
  • フックが .cmd や .bat ファイルではなく 1 つの .exe を実行する: プログラムを command に、その引数を args に指定して exec 形式を使用し、"onFailure": "block" を追加します。これにより Claude Code はシェルを介さずにプログラムを起動します。"onFailure": "block" がない場合、プログラムが失敗した、存在しない、またはタイムアウトしたときに呼び出しが進行することがあります
  • フックは警告のために 1 で終了するが、クラッシュしたときはブロックする必要がある: "onFailure": "continue" では、警告であってもクラッシュであっても、終了コード 1 で呼び出しが進行します。代わりに "onFailure": "block" を追加し、警告する箇所ではスクリプトを終了コード 0 で終了させて、それらの呼び出しが進行するようにします。終了コード 0 の後に PreToolUse で警告を表示するには、1 つの JSON オブジェクトの systemMessage フィールドに入れて stdout に出力します
  • 失敗時にブロックする必要がある PowerShell のガード フック: onFailure が未設定の場合、Git for Windows がインストールされて Claude Code が Git Bash を見つけると、ブロックしなくなります。Git Bash の有無にかかわらず失敗やタイムアウトで呼び出しがブロックされるよう、"onFailure": "block" を追加します。また、それ以降も Git Bash ではなく PowerShell でフックが実行され続けるよう、"shell": "powershell" も設定します
このエラーを表示するフックでは、呼び出しを拒否しない JSON を出力した場合でも、0 または 2 以外の終了コードはすべて失敗としてカウントされます。 v2.1.309 より前は、メッセージは blocking because Git Bash wasn't found and this hook doesn't set "shell" to "powershell", so only exit code 0 or 2 counts as its verdict. でした。

イベントごとの終了コード 2 動作

終了コード 2 は、フックが「停止、これをしないでください」と通知する方法です。効果はイベントに依存します。一部のイベントはブロック可能なアクション(まだ発生していないツール呼び出しなど)を表し、他のイベントはすでに発生したか防止できないことを表すためです。 SessionStart、SubagentStart、および PostModelSwitch の場合、Claude Code は終了コード 2 の stderr を非ブロッキング エラーと同じ方法で、トランスクリプトに <hook name> hook error 通知としてレンダリングします。Claude はそれを見ず、セッションまたはサブエージェントは進行します。SubagentStart の場合、通知は親会話ではなく、サブエージェント自身のトランスクリプトに表示されます。

HTTP レスポンス処理

HTTP フックは終了コードと stdout の代わりに HTTP ステータス コードとレスポンス本体を使用します。リクエストが失敗した場合や 2xx 以外のステータスを返した場合にアクションをブロックするには、onFailure: "block" を設定してください。ツール呼び出しをブロックまたは権限を拒否するには、適切な決定フィールドを含む JSON 本体を持つ 2xx レスポンスを返します。 非ブロッキング エラーの後は、失敗時にアクションをブロックするフックでない限り、アクションは進行します。WorktreeCreate など、イベントごとの表に独自の失敗時の規約を持つイベントを除き、各レスポンスまたは失敗に対する結果は次のとおりです。
  • 2xx で空の本体: 成功、終了コード 0 で出力なしと同等
  • 2xx で JSON オブジェクト本体: コマンド フックと同じ JSON 出力スキーマを使用して解析。スキーマ検証に失敗した本体は非ブロッキング エラー
  • 2xx でその他の本体(プレーン テキストなど): 非ブロッキング エラー。2xx 以外のステータスと同じように処理されます。Claude Code はテキストを Claude のコンテキストに追加しません
  • 2xx 以外のステータス: 非ブロッキング エラー
  • 接続失敗: 非ブロッキング エラー
  • タイムアウト: タイムアウトで説明されているとおり、フックはキャンセルされます

JSON 出力

終了コードではブロックするか何もしないかしか選べませんが、JSON 出力はより細かい制御を提供します。終了コード 2 でブロックする代わりに、終了 0 して stdout に JSON オブジェクトを出力します。Claude Code はその JSON から特定のフィールドを読み取り、ブロック、許可、またはユーザーへのエスカレーションのための決定制御を含む動作を制御します。
フックごとに 1 つのアプローチを選択してください。終了コードのみでシグナリングするか、終了 0 して構造化制御のために JSON を出力するかのいずれかです。両方を混在させた場合、終了 2 はブロッキング効果を維持し、Claude Code は引き続き JSON フィールドを読み取ります。ただし、終了コード 2 で説明されている elicitation の例外が 1 つあります。
stdout には JSON オブジェクト以外何も出力しないでください。非同期でないフックの場合、シェル プロファイルがスタートアップ時に出力する行など、他のテキストがあると Claude Code はオブジェクトを JSON として読み取れなくなります。そのテキストを見つけて抑制する方法については、フックの JSON が効果を持たないを参照してください。 フックの additionalContext、systemMessage、initialUserMessage の文字列、およびプレーン stdout は 10,000 文字に制限されています。
  • スコープ: 同じイベントに対して複数のフックが実行される場合でも、Claude Code は各文字列を個別に計測します。JSON 出力の場合、各フィールドは個別に計測されます。プレーン stdout は全体として計測されます。
  • 制限を超えた場合: Claude Code は出力をセッション ディレクトリ内のファイルに保存し、ファイル パスと最初の最大 2,000 文字のプレビューに置き換えます。大きな有効な Bash 結果も同じ方法で処理されます(出力制限で説明)。その Bash の上限とは異なり、この上限を引き上げる設定や環境変数はありません。
  • ファイルの読み取り: Claude Code は Claude にファイルを読むよう求めないため、Claude が常に確認する必要があるものは上限内に収めてください。
JSON オブジェクトは 3 種類のフィールドをサポートしています。
  • continue などのユニバーサル フィールドは以下の表にリストされています。すべてのイベントがこれらを受け入れますが、一部のイベントはこれらを破棄するか、systemMessage をトランスクリプト以外の場所に配信します。各イベントのセクションにその旨が記載されています。terminalSequence もそれらのイベントで機能しますが、ターミナル通知を発行に記載されている例外があります。
  • トップレベルの decision と reason は一部のイベントで使用され、ブロックまたはフィードバックを提供します。
  • hookSpecificOutput はより豊かな制御が必要なイベント用のネストされたオブジェクトです。イベント名に設定された hookEventName フィールドが必要です。
Claude を完全に停止するには、次のようにします。
PreToolUse および PostToolUse フックの場合、Claude がまだ応答をストリーミングしている間にツール呼び出しが失敗または完了した場合でも、停止が適用されます。

ターミナル通知を発行

フックは制御ターミナルなしで実行されるため、エスケープ シーケンスを /dev/tty に直接書き込むことは失敗します。代わりに、エスケープ シーケンスを terminalSequence フィールドで返し、Claude Code は独自のターミナル書き込みパスを通じてそれを発行します。これはレース フリーで、tmux と GNU screen 内で機能し、/dev/tty がない Windows で機能します。 フィールドは 1 つ以上の許可リストに登録されたエスケープ シーケンスの文字列を受け入れます。
  • OSC 0、1、2: ウィンドウとアイコン タイトル
  • OSC 9: iTerm2、ConEmu、Windows Terminal、WezTerm 通知(9;4 タスクバー進捗を含む)
  • OSC 99: Kitty 通知
  • OSC 777: urxvt、Ghostty、Warp 通知
  • 裸の BEL
シーケンスは BEL または ST で終了する場合があります。許可リスト外のもの(CSI カーソルと色シーケンス、OSC パレット シーケンス、OSC 8 ハイパーリンク、OSC 52 クリップボード書き込み、OSC 1337 を含む)は拒否され、フィールドは無視されます。 Claude Code はフックの出力を処理するときにシーケンス自体を書き込むため、このフィールドは Notification や StopFailure など、systemMessage と continue を破棄するイベントでも機能します。ただし、2 つの制限があります。
  • Claude Code は対話セッションでのみ、かつそのインターフェイスが画面に表示されている間のみシーケンスを書き込みます。-p フラグを使用した非対話モードおよび Agent SDK では、このフィールドは無視されます。
  • WorktreeCreate コマンド フックは JSON を返せません。Claude Code はその stdout を worktree パスとして読み取るためです。HTTP WorktreeCreate フックは JSON を返すため、このフィールドを含めることができます。
以下の例は Notification フックからデスクトップ通知を発火します。エスケープ シーケンスは printf 8 進数エスケープで構築されるため、制御バイトはシェル コマンド ラインに表示されず、jq -n --arg は JSON 出力を構築するため、通知メッセージの引用符、バックスラッシュ、改行は正しくエスケープされます。
{ "terminalSequence": "..." } の形状は、任意のシェルまたは言語から同じです。

Claude 用にコンテキストを追加

additionalContext フィールドは、フックから Claude のコンテキストウィンドウに文字列を渡します。Claude Code は文字列をシステムリマインダーでラップし、フックが発火した時点で会話に挿入します。Claude は次のモデル リクエストでリマインダーを読み取りますが、インターフェイスではチャット メッセージとして表示されません。 hookSpecificOutput 内でイベント名と一緒に additionalContext を返します。
リマインダーが表示される場所はイベントに依存します。 複数のフックが同じイベントに対して additionalContext を返す場合、Claude はすべての値を受け取ります。 文字列に <system-reminder> または </system-reminder> タグが含まれている場合、Claude はそのタグの < が &lt; に置き換えられた文字列を受け取ります。 値が 10,000 文字を超える場合、Claude Code はテキストをセッション ディレクトリ内のファイルに書き込み、代わりにファイル パスと最初の最大 2,000 文字のプレビューを Claude に渡します。Claude はファイルを読むことができますが、Claude Code はそれを読むよう求めません。 Claude が現在の環境の状態または実行されたばかりの操作について知っておくべき情報に additionalContext を使用します。
  • 環境状態: 現在のブランチ、デプロイ ターゲット、またはアクティブな機能フラグ
  • 条件付きプロジェクト ルール: 編集されたばかりのファイルに適用されるテスト コマンド、この worktree で読み取り専用のディレクトリ
  • 外部データ: 割り当てられたオープン イシュー、最近の CI 結果、内部サービスから取得されたコンテンツ
変わらない指示については、CLAUDE.md を優先します。スクリプトを実行せずに読み込まれ、静的なプロジェクト規約の標準的な場所です。 テキストを命令型システム指示ではなく、事実的なステートメントとして記述します。「デプロイ ターゲットは本番環境です」または「このリポジトリは bun test を使用します」などのフレーズはプロジェクト情報として読み取られます。帯域外システム コマンドとしてフレーム化されたテキストは Claude のプロンプトインジェクション防御をトリガーする可能性があり、その場合 Claude はテキストをコンテキストとして扱う代わりにユーザーに提示します。 Claude Code は注入されたテキストをセッション トランスクリプトに保存します。PostToolUse や UserPromptSubmit などのセッション途中のイベントの場合、--continue または --resume で再開すると、Claude Code は過去のターンについてフックを再実行するのではなく保存されたテキストを再生するため、タイムスタンプやコミット SHA などの値は古くなります。SessionStart フックは再開時に source を "resume"(--fork-session を追加した場合は "fork")に設定して再度実行されるため、コンテキストをリフレッシュできます。

決定制御

すべてのイベントが JSON を通じたブロッキングまたは動作制御をサポートしているわけではありません。サポートするイベントは、その決定を表現するために異なるフィールド セットを使用します。フックを書く前に、このテーブルをクイック リファレンスとして使用してください。 いくつかのイベントは、許可またはブロックするだけでなく、コンテンツを書き直すこともできます。
  • PreToolUse: hookSpecificOutput の直下の updatedInput は、ツールが実行される前にそのツールの引数を置き換えます。PreToolUse 決定制御を参照してください
  • PermissionRequest: decision オブジェクト内の updatedInput。PermissionRequest 決定制御を参照してください
  • PostToolUse: updatedToolOutput はツールの結果を置き換えます。PostToolUse 決定制御を参照してください
  • UserPromptSubmit: プロンプトを置き換えることはできません。additionalContext をそれと一緒に注入するだけです
秘匿化や変換のユースケースの場合、アウトバウンド ツール入力の場合は PreToolUse で、インバウンド ツール結果の場合は PostToolUse で傍受します。 各パターンの実行例を以下に示します。
decision の唯一の値は "block" です。アクションを進行させるには、JSON から decision を省略するか、JSON なしで終了 0 で終了します。
Bash コマンド検証、プロンプト フィルタリング、自動承認スクリプトを含む拡張例については、ガイドの自動化できることと Bash コマンド バリデーター リファレンス実装を参照してください。

フックイベント

各イベントは、フックを実行できる Claude Code のライフサイクル上のポイントに対応しています。以下のセクションは、セッションのセットアップからエージェント型ループを経てセッション終了まで、ライフサイクルに沿った順序で並んでいます。各セクションでは、イベントが発火するタイミング、サポートされる matcher、受け取る JSON 入力、出力による動作の制御方法を説明します。

SessionStart

Claude Code が新しいセッションを開始するとき、または既存のセッションを再開するときに実行されます。既存の issue やコードベースへの最近の変更などの開発コンテキストの読み込みや、環境変数の設定に便利です。スクリプトを必要としない静的なコンテキストには、代わりに CLAUDE.md を使用してください。 SessionStart はすべてのセッションで実行されるため、これらのフックは高速に保ってください。type: "command" と type: "mcp_tool" のフックのみがサポートされます。mcp_tool フックが実行されるタイミングについては、MCP ツールフックのフィールドを参照してください。 matcher の値は、セッションがどのように開始されたかに対応します: 対話セッションを開始したとき、起動時に --continue または --resume で会話を再開したとき、または /clear を実行したとき、SessionStart フックはバックグラウンドで実行されます。すぐに入力を始めることができ、再開した会話はフックを待たずに表示されます。ただし、Claude の最初の応答はフックの完了を待つため、フックのコンテキストは Claude に届きます。 セッション内で /resume を使って会話を切り替える場合は、代わりに切り替えがフックの完了を待ちます。バックグラウンドのフックがまだ実行中に /clear を実行したり別の会話に切り替えたりすると、フックが返すものはセッションに一切適用されません。 同じ待機は起動時にも適用され、再開したセッションも含まれます。SessionStart フックがまだ実行中に送信したプロンプトは、フックが完了するまで Claude に届きません。 いずれの待機中も、Esc を押すと、プロンプトを送信せずに入力欄に戻せます。フックは実行を続けます。

SessionStart の入力

共通入力フィールドに加えて、SessionStart フックは source と、オプションで model、agent_type、session_title を受け取ります: 名前を付けていないセッションにも生成されたタイトルがある場合があります。そのタイトルはカスタムタイトルではなく、session_title には含まれません。 source が "resume" または "fork" で、トランスクリプトに Claude からの応答が少なくとも 1 つ含まれている場合、SessionStart フックは以下の 4 つのフィールドも受け取ります。フックはこれらを使って、古い会話を再開するコストを最初のリクエストの前に報告できます(たとえば systemMessage で)。これらのフィールドには Claude Code v2.1.251 以降が必要です。 この例は、最後の応答から 90 分後に再開されたセッションの入力を示しています:

SessionStart の決定制御

SessionStart フックは、Claude へのコンテキストの追加、最初のユーザーメッセージの提供、セッションタイトルの設定、ファイルの監視、スキルの再読み込みを行えます。すべてのフックで利用できる JSON 出力フィールドに加えて、それぞれに対応するフィールドを返します: この出力はコンテキストを追加し、セッションに名前を付けます:
コンテキストを追加するだけのフックは、JSON を組み立てずにそれを出力できます。Claude Code は SessionStart フックのプレーンテキストの stdout を Claude のコンテキストに追加するためです。 プラグインの SessionStart フックが initialUserMessage または sessionTitle を提供する場合は、セッション開始前にプラグインをインストールしてください。SessionStart フックの実行後にインストールが完了したプラグインからのこれら 2 つのフィールドは、Claude Code によって無視されます。

フックがインストールしたスキルを再読み込みする

SessionStart フックがインストールしたスキルを同じセッションで利用可能にするには、reloadSkills を返します。スキルの検出は通常 SessionStart フックが完了する前に実行されるため、これがないと、フックが ~/.claude/skills/ や .claude/skills/ に書き込んだファイルが最初のプロンプトの実行時に存在しない場合があります。 この例は共有スキルリポジトリを同期し、再スキャンを要求します:
リポジトリの URL はプレースホルダーです。独自のスキルリポジトリに置き換えてください。

環境変数を永続化する

SessionStart フックは CLAUDE_ENV_FILE 環境変数にアクセスできます。これは、セッション中に Claude が後で実行するシェルコマンド向けに環境変数を永続化できるファイルパスを提供します。 個々の環境変数を設定するには、export 文を CLAUDE_ENV_FILE に書き込みます。他のフックが設定した変数を保持するには、追記(>>)を使用してください:
セットアップコマンドによるすべての環境変更を取り込むには、変更前後でエクスポートされた変数を比較します:
各 Bash コマンドは、コマンド自体の前にこのファイルの内容をシェルコードとして実行するため、ファイル内の行では export PATH="$PATH:./node_modules/.bin" の $PATH 参照のように、Bash が評価するものなら何でも使用できます。 PowerShell コマンドも Claude Code v2.1.296 以降では CLAUDE_ENV_FILE から変数を受け取りますが、PowerShell がこのファイルを実行することはありません。代わりに、Claude Code がファイルから代入を読み取り、PowerShell コマンドの環境にコピーします。これが行われるのは、このセッションのすべてのフックが書き込んだ内容と、起動前に CLAUDE_ENV_FILE に設定したスクリプトの全体にわたって、すべての行が次のいずれかである場合に限られます:
  • 空行または # コメント
  • 行頭にある 1 つの代入で、export NAME=value、declare -x NAME=value、または NAME=value の形式で記述され、Bash が記述どおりにそのまま使用する値であるもの。値は次の部分を任意に組み合わせたものです:英字、数字、_ @ % + = : , . / - の文字のみを使用するクォートなしのテキスト、シングルクォートで囲まれたテキスト、内部の $、バッククォート、" がすべてバックスラッシュでエスケープされたダブルクォートで囲まれたテキスト
いずれかの行がそれ以外の種類である場合(エスケープされていない $PATH を含む export PATH="$PATH:./node_modules/.bin"、source コマンド、direnv export bash が出力する $'...' 文字列など)、PowerShell コマンドは変数を一切受け取らず、claude --debug は Session environment is not all plain assignments をログに記録します。Bash コマンドは引き続きすべての変数を受け取ります。Windows では、Git Bash と Windows でパスの書き方が異なるため、値に / または \ を含む変数も PowerShell コマンドには渡されません。サンドボックス化された PowerShell コマンドは変数を一切受け取りません。
CLAUDE_ENV_FILE は、SessionStart、Setup、CwdChanged、FileChanged フックで利用できます。他のフックイベントはこの変数にアクセスできず、PowerShell で実行されるフックも、"shell": "powershell" によるものか、Git Bash のない Windows でのデフォルトによるものかにかかわらず、アクセスできません。

Setup

--init-only を指定して Claude Code を起動した場合、または -p フラグを使用した非対話モードで --init または --maintenance を指定した場合にのみ発火します。通常の起動では発火しません。通常のセッション起動とは別に、CI やスクリプトから明示的にトリガーする一回限りの依存関係のインストールや定期的なクリーンアップに使用してください。セッションごとの初期化には、代わりに SessionStart を使用してください。 matcher の値は、フックをトリガーした CLI フラグに対応します: claude --init-only を実行すると、Claude Code は Setup フックと startup matcher の SessionStart フックを実行し、会話を開始せずに終了します。 -p で会話を開始または継続する場合は、引数として、または stdin へのパイプで、プロンプトも指定する必要があります。SessionStart フックが initialUserMessage を提供する場合や、遅延されたツール呼び出しを含むセッションを再開する場合は、プロンプトを省略できます。 成功した場合、--init-only はターミナルに何も出力しません。フックが実行されたことを確認するには、<path> をログファイルの場所に置き換えて claude --debug-file <path> --init-only で起動し、ログで Setup と SessionStart のフックのエントリを確認してください。 Setup はすべての起動で発火するわけではないため、依存関係のインストールを必要とするプラグインは Setup だけに頼ることはできません。実用的なパターンは、初回使用時に依存関係を確認し、存在しなければインストールすることです。たとえば、${CLAUDE_PLUGIN_DATA}/node_modules の存在をテストし、なければ npm install を実行するフックやスキルなどです。インストールした依存関係の保存場所については、永続データディレクトリを参照してください。マーケットプレイスを通じてプラグインを配布する場合、このパターンは不要な場合があります。Claude Code はプラグインをキャッシュする際に、対象となる Node.js パッケージの依存関係を自動的にインストールします。

Setup の入力

共通入力フィールドに加えて、Setup フックは "init" または "maintenance" のいずれかに設定された trigger フィールドを受け取ります:

Setup の決定制御

Setup フックはブロックできません。どの終了コードでも実行は継続されます。どの終了コードの場合も、Claude Code は Setup フックの JSON 出力フィールド(systemMessage、continue、hookSpecificOutput.additionalContext など)を破棄します。-p では、Setup フックの stdout、stderr、終了コードは、--output-format stream-json --verbose で起動した場合にのみ、hook_response イベントとして実行の出力に表示されます。 Setup フックは CLAUDE_ENV_FILE にアクセスできます。このファイルに書き込まれた変数は、SessionStart フックと同様に、セッションの後続の Bash コマンドに引き継がれます。Setup では type: "command" フックのみが実行されます。Setup の type: "mcp_tool" フックは、MCP ツールフックのフィールドで説明されているとおり、常にスキップされます。

InstructionsLoaded

CLAUDE.md または .claude/rules/*.md ファイルがコンテキストに読み込まれたときに発火します。このイベントは、即時に読み込まれるファイルについてはセッション開始時に発火し、ファイルが遅延読み込みされるときにも後で再度発火します。たとえば、ネストされた CLAUDE.md を含むサブディレクトリに Claude がアクセスしたときや、paths: フロントマターを持つ条件付きルールがマッチしたときです。このフックはブロックや決定制御をサポートしません。可観測性のために非同期で実行されます。 このイベントは、Claude が Project instructions 設定を通じて AGENTS.md を直接読み取る場合には発火しません。CLAUDE.md が AGENTS.md をインポートする場合は、他のインポートされたファイルと同様に load_reason が include に設定されて発火し、CLAUDE.md がそれへのシンボリックリンクである場合は、通常の CLAUDE.md の読み込みとして発火します。 matcher は load_reason に対して実行されます。たとえば、セッション開始時に読み込まれたファイルに対してのみ発火させるには "matcher": "session_start" を、遅延読み込みに対してのみ発火させるには "matcher": "path_glob_match|nested_traversal" を使用します。

InstructionsLoaded の入力

共通入力フィールドに加えて、InstructionsLoaded フックは次のフィールドを受け取ります:

InstructionsLoaded の決定制御

InstructionsLoaded フックには決定制御がありません。指示の読み込みをブロックしたり変更したりすることはできません。Claude Code はその JSON 出力フィールド(systemMessage や continue など)を破棄します。このイベントは、監査ログ、コンプライアンスの追跡、可観測性のために使用してください。

UserPromptSubmit

プロンプトが送信されたとき、Claude がそれを処理する前に実行されます。これにより、 プロンプトや会話に基づいて追加のコンテキストを加えたり、プロンプトを検証したり、 特定の種類のプロンプトをブロックしたりできます。 UserPromptSubmit フックは、入力したプロンプトに対してだけ発火するわけではありません。Claude Code は次の場合にも実行します: UserPromptSubmit フックのデフォルトのタイムアウトは、command、http、mcp_tool タイプで 30 秒です。これは、他のほとんどのイベントにおけるこれらのタイプのデフォルトである 600 秒より短い値です。このフックはすべてのプロンプトの前に実行され、完了するまでモデルの処理をブロックするため、フックが停止するとセッションも停止します。フックにより多くの時間が必要な場合は、フックエントリで timeout フィールドを設定してください。 async: true で実行するコマンドフックを除き、タイムアウトに達した UserPromptSubmit のコマンド、HTTP、MCP ツールのフックはキャンセルされ、その出力(additionalContext を含む)は破棄されます。プロンプトはそのコンテキストなしで Claude に届きます。代わりにプロンプトをブロックするには、コマンドフックまたは HTTP フックで onFailure: "block" を設定してください。トランスクリプトには、フック名、発生したタイムアウト、出力が破棄されたことを示す通知が表示されます。 UserPromptSubmit の Agent SDK コールバックフックがタイムアウトに達すると、フック名とタイムアウトを示すメッセージとともにプロンプトがブロックされます。そこでのコールバックは、フェイルオープンしてはならないポリシーゲートとして機能している可能性があるためです。セッションは継続します。

UserPromptSubmit の入力

共通入力フィールドに加えて、UserPromptSubmit フックは送信されたテキストを含む prompt フィールドを受け取ります。[Pasted text #N] プレースホルダーに折りたたまれた貼り付けコンテンツは、その場で展開された状態で届きます。Claude Code が貼り付けたテキストを Claude 向けにマークするセッションでは、展開されたコンテンツは <pasted_content id="…"> の行と </pasted_content id="…"> の行の間に置かれるため、フックがプロンプトを解析する場合はこれらの行を考慮してください。 UserPromptSubmit フックは、セッションにカスタムタイトルがある場合、session_title も受け取ります。意味は SessionStart の session_title フィールドと同じです。
プロンプトが入力したスキルまたはカスタムコマンド(/deploy staging など)の場合、フックは展開されたスキルの内容ではなく、入力したとおりの行を受け取ります。フックがプロンプトをブロックするとコマンドは実行されないため、スキルが !`<command>` で挿入するシェルコマンドも実行されません。代わりにコマンドの名前や引数で照合するには、UserPromptExpansion を使用してください。

UserPromptSubmit の決定制御

UserPromptSubmit フックは、送信されたプロンプトを処理するかどうかを制御し、コンテキストを追加できます。すべての JSON 出力フィールドが利用できます。 終了コード 0 で会話にコンテキストを追加する方法は 2 つあります:
  • プレーンテキストの stdout:Claude Code は、プレーンテキストとして扱う stdout を Claude のコンテキストに追加します
  • additionalContext を含む JSON:より細かく制御するには、以下の JSON 形式を使用します。additionalContext フィールドがコンテキストとして追加されます
どちらの方法でも、トランスクリプトに表示されるエントリは作成されません。プレーンな stdout と additionalContext の値は、それぞれフック名で始まるシステムリマインダーとして挿入され、Claude は両方を読み取ります。配信を確認するには、デバッグログを確認してください。 プロンプトをブロックするには、decision を "block" に設定した JSON オブジェクトを返します: 終了コード 2 でブロックするフックは、reason と同じように扱われます。ブロックメッセージには stderr のテキストがユーザーに表示され、コンテキストには追加されません。

ブロックされたプロンプトが残すもの

ブロックされたプロンプトが Claude に届くことはありませんが、そのテキストがあらゆる場所から削除されるわけではありません。デフォルトでは、ユーザーに表示されるブロックメッセージの末尾に Original prompt: と送信されたテキストが続き、Claude Code はそのメッセージをディスク上のセッションのトランスクリプトファイルに書き込みます。メッセージからテキストを除外するには、hookSpecificOutput 内に "suppressOriginalPrompt": true を含む JSON を出力します。これは、フックが decision: "block" でブロックする場合でも、終了コード 2 でブロックする場合でも機能します。 suppressOriginalPrompt が変更するのはブロックメッセージのみです。送信されたテキストは、セッションのトランスクリプトやプロンプト履歴などのローカルファイルに引き続き残る可能性があるため、ブロックするフックは機密情報をディスクに残さない手段にはなりません。これらのファイルを制限または削除するには、プレーンテキストでの保存とローカルデータの消去を参照してください。

UserPromptExpansion

ユーザーが入力したコマンドが、Claude に届く前にプロンプトに展開されるときに実行されます。特定のコマンドの直接呼び出しのブロック、特定のスキルへのコンテキストの挿入、ユーザーが呼び出したコマンドのログ記録に使用します。たとえば、deploy にマッチするフックは承認ファイルが存在しない限り /deploy をブロックでき、レビュースキルにマッチするフックはチームのレビューチェックリストを additionalContext として追加できます。 このイベントは、PreToolUse がカバーしない経路をカバーします。Skill ツールにマッチする PreToolUse フックは Claude がツールを呼び出したときにのみ発火しますが、/skillname を直接入力すると PreToolUse はバイパスされます。UserPromptExpansion はその直接の経路で発火します。 command_name にマッチします。すべてのプロンプト型コマンドで発火させるには、matcher を空のままにします。

UserPromptExpansion の入力

共通入力フィールドに加えて、UserPromptExpansion フックは expansion_type、command_name、command_args、command_source、および元の prompt 文字列を受け取ります。expansion_type フィールドは、スキルとカスタムコマンドの場合は slash_command、MCP サーバーのプロンプトの場合は mcp_prompt です。

UserPromptExpansion の決定制御

UserPromptExpansion フックは展開をブロックしたり、コンテキストを追加したりできます。すべての JSON 出力フィールドが利用できます。 終了コード 2 でブロックするフックは、reason と同じように扱われます。ブロックメッセージには stderr のテキストがユーザーに表示されます。

MessageDisplay

アシスタントメッセージが画面にストリーミングされている間に実行されます。Claude Code はメッセージを段階的に表示します。新たに完成した行のバッチが描画可能になるたびに、フックはそれらの行を受け取って 1 回実行され、Claude Code はその位置にフックの置換テキストを描画します。長いメッセージでは複数回呼び出され、短いメッセージでは 1 回だけの場合もあります。 MessageDisplay は次の用途に使用します:
  • 最小限の表示のために markdown を除去する
  • Agent SDK アプリケーションがユーザーに表示するテキストを変換する
  • Claude の応答から API キーや内部ホスト名を秘匿する
Claude Code はフックが返るまで各バッチを保持するため、フックは高速に保ってください。フックが失敗またはタイムアウトした場合、Claude Code は元のテキストを表示します。このイベントのデフォルトのタイムアウトは 10 秒です。フックにより多くの時間が必要な場合は、フックエントリで timeout フィールドを設定してください。 MessageDisplay は表示専用です。置換テキストによって変わるのは画面に描画される内容だけです。トランスクリプトと Claude が見る内容は元のテキストのままなので、Claude が置換テキストを見ることはなく、verbose モードでは元のテキストが表示されます。フックが受け取るのはアシスタントメッセージのテキストのみなので、ツールの結果やユーザーが入力したテキストは変更されずに描画されます。 MessageDisplay は matcher をサポートせず、テキストをストリーミングするすべてのアシスタントメッセージで発火します。ツール呼び出しのみの応答など、テキストを含まないメッセージではトリガーされません。 Agent SDK のクエリや claude -p を含む非対話の実行では、MessageDisplay は行のバッチごとではなく、アシスタントメッセージごとに 1 回実行されます。この 1 回の呼び出しはメッセージの完了後に行われ、メッセージの全文を含みます。index は 0、final は true で、delta にメッセージ全体が入ります。各メッセージの delta テキストを収集するフックは、どちらのモードでも同じ合計テキストを受け取ります。

MessageDisplay の入力

共通入力フィールドに加えて、MessageDisplay フックは、ターンとメッセージの識別子、メッセージ内でのこの呼び出しの位置、delta 内の新しいテキストを受け取ります。バッチの境界はテキストのストリーミング方法によって異なるため、行が特定の方法でグループ化されることを期待せず、index と final を使ってメッセージの進行状況を追跡してください。

MessageDisplay の出力

すべてのフックで利用できる JSON 出力フィールドに加えて、MessageDisplay フックは displayContent を返して画面上の delta を置き換えることができます: MessageDisplay フックには決定制御がありません。メッセージをブロックしたり、トランスクリプトに保存される内容や Claude に送信される内容を変更したりすることはできません。Claude Code は JSON 出力の displayContent に基づいて動作し、systemMessage と continue は破棄します。 この例では、プレーンテキストで表示するために Claude の応答から markdown の書式を除去します。スクリプトは stdin から各バッチを読み取り、delta から太字マーカーとインラインコードのバッククォートを削除して、結果を displayContent として返します。
設定ファイルでこのイベントのコマンドフックを登録します:
このスクリプトをプロジェクトの .claude/hooks/plain-display.sh に保存し、chmod +x で実行可能にします:
markdown を含まないバッチはそのまま通過します。スクリプトが失敗した場合(たとえば jq がない場合)、Claude Code は元のテキストを表示し、失敗はセッション内ではなくデバッグ出力でのみ通知されます。

PreToolUse

Claude がツールのパラメータを作成した後、ツール呼び出しを処理する前に実行されます。EndConversation を除くすべてのツール名にマッチします。Bash、PowerShell、Edit、Write、Read、Glob、Grep、Agent、Workflow、WebFetch、WebSearch、AskUserQuestion、ExitPlanMode などの組み込みツールと、任意の MCP ツール名が対象です。 何が書き込んだかにかかわらず、特定のファイルがディスク上で変更されたときにフックを実行するには、ファイル編集ツールを名前でマッチさせる代わりに FileChanged を使用してください。PreToolUse とは異なり、Claude Code は FileChanged フックを変更の後に実行し、決定制御もないため、書き込みをブロックすることはできません。
PreToolUse は Claude がツールを呼び出したときにのみ実行されます。デフォルトでは、プロンプト内で @ を使って参照したファイルは、ツール呼び出しなしで追加されます。Claude Code はプロンプトの構築中にその内容を挿入するため、Read にマッチするフックを含め、PreToolUse フックは発火しません。PreToolUse は EndConversation に対しても発火しません。特定のパスを @ 参照からブロックしたり、挿入をオフにしたりできます:
  • 特定のパスをブロックする:それらのパスに対する Read の拒否ルールを追加します
  • 挿入をオフにする:シェル、ユーザー設定、または管理設定で CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 を設定します。これにより Claude は、メンションされたパスを、ファイルツールで読み取るよう促す注記とともに受け取ります。Claude がそうした場合、マッチする PreToolUse フックが実行されます。この変数には Claude Code v2.1.299 以降が必要で、プロジェクト設定とローカル設定では Claude Code によって無視されます。
PreToolUse の決定制御を使用して、ツール呼び出しを許可、拒否、確認、または遅延します。 PreToolUse の Agent SDK コールバックフックがタイムアウトを超えると、ツール呼び出しはブロックされ、Claude はタイムアウトを示すエラー結果を受け取ります。

PreToolUse の入力

共通入力フィールドに加えて、PreToolUse フックは tool_name、tool_input、tool_use_id を受け取ります。 MCP ツールの場合、入力には mcp_server も含まれます。これは、サーバーの name と、サーバーの定義の出所を示す source を持つオブジェクトです。source の値には、plugin、sdk、および user や project などの設定スコープが含まれます。Agent SDK リファレンスの McpServerProvenance にすべての値が記載されており、認識できない値の扱い方も説明されています。信頼に関する判断は、name や mcp__<server>__ というツール名のプレフィックスではなく、source に基づいて行ってください。mcp_server フィールドには Claude Code v2.1.274 以降が必要です。 ファイルツールの Write、Edit、Read では、tool_input.file_path は常に絶対パスです:
  • Claude Code はフックの実行前に ~ と相対パスを展開するため、パスでマッチするフックが ~ や同じパスの相対表記によって回避されることはありません
  • Windows では、フックが $PWD が /c/project のように見える Git Bash で実行される場合でも、パスはバックスラッシュ区切りで届きます
  • /src/ のチェックなど、スラッシュで書かれた比較はバックスラッシュのパスには決してマッチせず、ツール呼び出しはフックがブロックするものがなかったかのように続行されます
  • 比較の前に区切り文字を正規化してください。Bash では FILE_PATH="${FILE_PATH//\\//}"、Python では file_path.replace("\\", "/") を使用します。その後、パスは絶対パスなので、^ で先頭を固定するのではなく、/src/ などのパスセグメントでマッチさせます
Windows での Write 呼び出しでは次が渡されます:
tool_input のフィールドはツールによって異なります: シェルコマンドを実行します。 Bash コマンドが Git リポジトリ内のファイルを変更すると、Claude Code は変更内容を記録できます。bashEditDiffEnabled 設定で記録がオンになっている場合は、すべての権限モードで変更を記録します。どのファイルでこの設定を行えるかは、その設定の項目を参照してください。それ以外の場合は、auto モードと bypassPermissions モードでのみ、かつ Claude Code が Bash を通じてファイルを編集するよう Claude に指示した場合にのみ記録します。記録をオフにするには、bashEditDiffEnabled を false に設定します。バックグラウンドのコマンドと読み取り専用のコマンドには差分は含まれません。 その後、PostToolUse フックは tool_response.bashEditDiff で変更されたファイルを受け取ります。このリストには、コマンドの実行中にリポジトリ配下で変更されたものが含まれます。Git が無視するファイルとサブモジュール内のファイルは含まれません。Claude Code v2.1.269 以降が必要です。
このリストはベストエフォートであり、パブリックベータです。Claude Code が変更を見逃したり、同時に別のプロセスが変更したファイルを含めたり、サイズ制限で打ち切ったりする場合があります。フィールドの形式は変更される可能性があります。このリストは、ポリシーの強制ではなく、レビューすべき対象を見つけるために使用してください。
changedFiles と files はコマンドが変更した内容を列挙し、残りのフィールドはそのリストがどの程度完全で信頼できるかを示します。 PowerShell コマンドを実行します。プラットフォームごとの利用可否については、PowerShell ツールを参照してください。 フィールドは Bash ツールと同じで、コマンド文字列は command に入ります: シェルコマンドを検査するフックでは Bash|PowerShell をマッチさせ、両方のツールをカバーしてください:
  • Windows では、PowerShell ツールが有効になっている場合は常に、Claude は PowerShell をプライマリシェルとして扱い、シェルコマンドをそれ経由で実行します。
  • Git Bash のない Windows では、このツールが自動的に有効になり、Claude Code は Bash ツールをまったく登録しません。
  • Bash のみにマッチするフックは、そこでは決して発火しません。
ファイルを作成または上書きします。 既存のファイル内の文字列を置換します。 ファイルの内容を読み取ります。 glob パターンにマッチするファイルを検索します。 正規表現でファイルの内容を検索します。 Web コンテンツを取得して処理します。 Web を検索します。 サブエージェントを起動します。 フォアグラウンドの Agent 呼び出しが完了すると、PostToolUse フックは tool_response でサブエージェントの結果と実行のテレメトリを受け取ります。これらのフィールドを読み取って実行内容を調べてください。totalTokens と usage は最終リクエストのみを対象とするため、サブエージェント全体のトークンとコストの集計には、query_source "subagent" で絞り込んだトークンとコストのカウンターを使用してください: Claude Code v2.1.271 以降では、Claude Code が auto モードで提供する SubagentHandback ツールを使って実行されるサブエージェントは、レポートをテキストとして返すのではなく、そのツールを通じて配信します。その場合、completed の結果の content フィールドには、レポート自体ではなく、その引き渡しに関する短い注記が入ります。レポートを読み取るには、SubagentHandback に PreToolUse または PostToolUse フックをマッチさせ、tool_input.message を読み取ってください。 バックグラウンドのサブエージェントの場合、ツールはタスクがバックグラウンドに移った時点で返るため、tool_response には使用量のフィールドは含まれません。バックグラウンドでの起動は即座に返り、Claude Code が実行途中でバックグラウンドに移したフォアグラウンドのタスクはその移行時点で返ります。レスポンスには status: "async_launched"、agentId、description、prompt、outputFile、resolvedModel が含まれます。 completed のレスポンスでは、resolvedModel はサブエージェントが開始時に使用したモデルを示します。これは、availableModels やその他の上書きが適用される場合など、tool_input の model の値と異なることがあります。async_launched のレスポンスでは、resolvedModel はエージェントがバックグラウンドに移動した時点で使用中だったモデルを示すため、バックグラウンドへの移動前に行われたモデルの切り替えはそこに反映されます。 ユーザーに 1〜4 個の多肢選択式の質問をします。 計画を提示し、Claude が plan モードを終了する前にユーザーに承認を求めます。Claude はツールを呼び出す前に計画をディスク上のファイルに書き込むため、モデルからのそのままの tool_input は通常空です。Claude Code は、入力をフックに渡す前に計画の内容とファイルパスを挿入します。 PostToolUse では、tool_response は承認された計画を保持する plan と filePath のフィールドと、内部のステータスフラグを持つオブジェクトです。計画の内容は、ディスクからファイルを読み直すのではなく、tool_response.plan から読み取ってください。

PreToolUse の決定制御

PreToolUse フックは、ツール呼び出しを続行するかどうかを制御できます。トップレベルの decision フィールドを使用する他のフックとは異なり、PreToolUse は hookSpecificOutput オブジェクト内で決定を返します。これにより、4 つの結果(allow、deny、ask、defer)に加えて、実行前にツールの入力を変更する機能という、より豊富な制御が可能になります。 複数の PreToolUse フックが異なる決定を返した場合、優先順位は deny > defer > ask > allow です。 終了コード 2 でブロックするフックは "deny" と同じように扱われます。Claude は stderr のメッセージを拒否の理由として受け取ります。 フックが "ask" を返すと、ユーザーに表示される権限プロンプトには、フックの出所を示すラベルが含まれます。任意の設定ファイルまたはエージェントのフロントマターからのフックでは [settings]、プラグインのフックでは [plugin:<name>]、スキルのフロントマターからのフックでは [skill] です。これにより、どの設定ソースが確認を求めているかをユーザーが把握できます。 フックの "ask" は、auto モードでも権限プロンプトを強制します。分類器は引き続きツール呼び出しを拒否できますが、呼び出しを黙って承認することはできません。
PreToolUse は以前はトップレベルの decision と reason フィールドを使用していましたが、このイベントではこれらは非推奨です。代わりに hookSpecificOutput.permissionDecision と hookSpecificOutput.permissionDecisionReason を使用してください。非推奨の値 "approve" と "block" は、それぞれ "allow" と "deny" に対応します。PostToolUse や Stop などの他のイベントは、引き続きトップレベルの decision と reason を現在の形式として使用します。

ユーザーの操作を必要とするツール

AskUserQuestion と ExitPlanMode はユーザーの操作を必要とします。-p フラグを使用した非対話モードでは、Claude Code は、Agent SDK の canUseTool コールバックなど、プロンプトを受け取る権限ホストが実行にある場合にのみ、これらのツールを提供します。 PreToolUse フックは、次のことを行うことでその要件を満たします:
  1. stdin からツールの入力を読み取る
  2. 独自の UI で回答を収集する
  3. 回答を保持する updatedInput とともに permissionDecision: "allow" を返し、プロンプトなしでツールが実行されるようにする
これらのツールでは、"allow" を返すだけでは不十分です。 AskUserQuestion では、元の questions 配列をそのまま返し、各質問のテキストを選択された回答に対応付ける answers オブジェクトを追加します。この出力は、1 つの質問に React と回答します:
サーバーが _meta["anthropic/requiresUserInteraction"] でマークした MCP ツールはより厳格です。フックは、updatedInput の有無にかかわらず、"allow" でその承認プロンプトをスキップすることはできません。ツールが必要とする操作をフックが収集したことを Claude Code が確認できないためです。

ツール呼び出しを後回しにする

"defer" は、Agent SDK アプリや Claude Code 上に構築したカスタム UI など、claude -p をサブプロセスとして実行し、その JSON 出力を読み取る統合向けです。これにより、呼び出し側のプロセスは、ツール呼び出しの時点で Claude を一時停止し、独自のインターフェースで入力を収集して、中断したところから再開できます。Claude Code がこの値を尊重するのは、-p フラグを使用した非対話モードの場合のみです。対話セッションでは警告をログに記録し、フックの結果を無視します。 典型的な例は AskUserQuestion ツールです。Claude はユーザーに何かを尋ねたいのですが、回答するためのターミナルがありません。-p の実行では、--permission-prompt-tool で渡す MCP ツールなどの権限ホストがある場合にのみ AskUserQuestion が提供されるため、権限ホストを指定して実行を開始してください。往復の流れは次のとおりです:
  1. Claude が AskUserQuestion を呼び出します。PreToolUse フックが発火します。
  2. フックが permissionDecision: "defer" を返します。ツールは実行されません。ターンは stop_reason: "tool_deferred" を含む結果で終了し、保留中のツール呼び出しはトランスクリプトに残ります。
  3. 呼び出し側のプロセスが SDK の結果から deferred_tool_use を読み取り、独自の UI で質問を表示して、回答を待ちます。
  4. 呼び出し側のプロセスが、同じ権限ホストを指定して claude -p --resume <session-id> を実行します。同じツール呼び出しが再び PreToolUse を発火させます。
  5. フックが updatedInput に回答を含めて permissionDecision: "allow" を返します。ツールが実行され、Claude が続行します。
deferred_tool_use フィールドには、ツールの id、name、input が含まれます。input は Claude がツール呼び出しのために生成したパラメータで、実行前に取得されたものです:
タイムアウトや再試行の上限はありません。セッションは再開するまでディスク上に残りますが、cleanupPeriodDays の保持期間によるクリーンアップの対象となります。このクリーンアップは、保持期間によるクリーンアップのルールに従い、デフォルトでは 30 日後にセッションファイルを削除します。 再開時に保留されたツールが利用できなくなっている場合、再開の最初の結果は stop_reason: "tool_deferred_unavailable" と is_error: true になり、フックは発生しません。これは、ツールを提供していた MCP サーバーが再開されたセッションで接続されていない場合に発生します。どのツールが失われたかを特定できるように、deferred_tool_use ペイロードは引き続き含まれます。
  • 再開時またはその後にプロンプトを送信しなかった場合、呼び出しはまだ保留中です。ツールが利用できる状態で再度再開すると、最初にそれが実行されます。
  • 再開時またはその後にプロンプトを送信した場合、Claude Code はツールの結果なしでプロンプトに応答し、保留された呼び出しを破棄します。引き続きツールを呼び出す必要がある場合は、ツールが利用可能になった時点で新しいプロンプトを送信してください。
プロンプトなしで再開したときに待っている回答がまだ準備できていない場合、フックは再び "defer" を返すことができます。プロンプトを送信した状態でフックが再び保留した場合、Claude Code はプロンプトを同じように扱います。つまり、ツールの結果なしで応答し、呼び出しを破棄します。フックが "allow" または "deny" を返すまでプロンプトなしで再開してください。これが、呼び出し元のプロセスがループを抜ける方法です。 "defer" は、Claude がそのターンで単一のツール呼び出しを行う場合にのみ機能します。Claude が一度に複数のツール呼び出しを行う場合、"defer" は警告とともに無視され、ツールは通常の権限フローで処理されます。この制約は、再開時に再実行できるツールが 1 つだけであるために存在します。バッチから 1 つの呼び出しだけを遅延させると、他の呼び出しが未解決のまま残ってしまいます。
遅延されたセッションを plan モードで再開するには、Claude Code が計画を提示して承認を求められるように、--resume とともに --permission-prompt-tool を渡してください。その他の条件については、-p で plan モードのまま再開するを参照してください。Claude Code v2.1.246 以降が必要です。-p で再開する場合、Claude Code はそれ以外の保存された権限モードを復元しません。新しい claude -p の実行が開始するのと同じ権限モードで実行を開始するため、遅延されたセッションで --permission-mode または --dangerously-skip-permissions を使用していた場合は、再度渡してください。-p を付けずに claude --resume <session-id> で再開する場合、Claude Code は保存された権限モードを復元します。例外は再開時の権限モードに記載されています。

PermissionRequest

Claude Code がツールの使用について権限を求めようとするときに実行されます。非対話モードのバックグラウンドのサブエージェントなど、プロンプトを表示できないセッションでも Claude Code はこれらのフックを実行し、どのフックも決定を返さない場合はツール呼び出しを拒否します。--permission-prompt-tool または Agent SDK の canUseTool コールバックに到達する呼び出しでは、フックはホストと並行して実行され、先に決定した方が適用されます。 PermissionRequest の決定制御を使用して、ユーザーの代わりに許可または拒否します。 Claude がツールの使用について権限を求めた瞬間にシグナルが必要な場合は、このイベントを使用してください。Claude Code は、プロンプトが約 6 秒待機した後にのみ、permission_prompt タイプの Notification フックを実行します。 Claude Code は、サンドボックス化されたコマンドのネットワークリクエストについては PermissionRequest フックを実行しません。そのプロンプトのシグナルを得るには、permission_prompt 通知タイプを使用してください。 PreToolUse と同じ値で、ツール名にマッチします。

PermissionRequest の入力

PermissionRequest フックは、PreToolUse フックと同様に tool_name と tool_input フィールドを受け取りますが、tool_use_id は含まれません。MCP ツールの場合は、mcp_server オブジェクトも受け取ります。オプションの permission_suggestions 配列には、許可ルールの追加や権限モードの変更など、Claude Code がこのリクエストに対して提案する権限の更新が含まれます。 各権限ダイアログはそれぞれ独自にオプションを構築するため、permission_suggestions 配列は表示されるオプションの正確なリストではありません。ファイル編集用のダイアログなど一部のダイアログは、この配列をまったく読み取らず、リクエスト自体からオプションを導出します。配列を読み取るダイアログでも、提案が配列に残っているオプションを表示しない場合があります。たとえば、allowManagedPermissionRulesOnly によってルールを保存するオプションが非表示になる場合です。また、Yes, and switch to auto mode のように、提案エントリを持たないオプションを提示することもあります。このオプションは、権限の更新を介さずに権限モードを直接変更します。 PreToolUse フックは、権限が必要かどうかにかかわらず、すべてのツール呼び出しの前に実行されます。PermissionRequest フックは、Claude Code がユーザーに権限を求めようとしているとき、またはプロンプトを表示できない呼び出しを本来なら自動的に拒否するときにのみ実行されます。どちらのイベントも EndConversation では発火しません。

PermissionRequest の決定制御

PermissionRequest フックは権限リクエストを許可または拒否できます。すべてのフックで利用できる JSON 出力フィールドに加えて、フックスクリプトは次のイベント固有のフィールドを持つ decision オブジェクトを返すことができます。 decision オブジェクトを返さずに終了コード 2 で終了するフックは権限フローを変更せず、その stderr は破棄されます。リクエストを許可または拒否するには、decision オブジェクトを返してください。

権限更新エントリ

updatedPermissions 出力フィールドと permission_suggestions 入力フィールドは、どちらも同じエントリオブジェクトの配列を使用します。各エントリには、他のフィールドを決定する type と、変更の書き込み先を制御する destination があります。
bypassPermissions を指定した setMode は、bypass モードがすでに利用可能な状態でセッションを起動した場合にのみ有効になります。具体的には、--dangerously-skip-permissions、--permission-mode bypassPermissions、--allow-dangerously-skip-permissions、または ユーザー設定、--settings、管理設定での permissions.defaultMode: "bypassPermissions" のいずれかです。それ以外の場合、この更新は何も行いません。また、permissions.disableBypassPermissionsMode によってこのモードが無効化されている場合や、セッションが制限モードで開始された場合も、この更新は何も行いません。destination にかかわらず、bypassPermissions が defaultMode として永続化されることはありません。
各エントリの destination フィールドによって、変更がメモリ内にとどまるか、設定ファイルに永続化されるかが決まります。 フックは、受け取った permission_suggestions のいずれかを、そのまま自身の updatedPermissions 出力として返すことができます。

PostToolUse

ツールが正常に完了した直後に実行されます。 ツール名で照合します。値は PreToolUse と同じです。 ツール名が適切なフィルターでない場合は、より広く照合します。
  • ツールが正常に完了した後に常にフックを実行するには、matcher を省略するか "*" に設定します。そのうえで、フック自身が何が変更されたかを調べます。たとえば git status --porcelain を実行すると、git diff では漏れる未追跡ファイルも一覧表示されます。失敗したツール呼び出しについては、同じフックを PostToolUseFailure に追加してください。
  • 書き込み元にかかわらず、特定のファイルがディスク上で変更されたときにフックを実行するには、FileChanged を使用します。Bash コマンドや Claude Code 外部のプロセスが同じファイルを書き換えた場合、Claude Code は Edit|Write に一致する PostToolUse フックを実行しません。

PostToolUse の入力

PostToolUse フックは、ツールがすでに正常に実行された後に発火します。入力には、ツールに送信された引数である tool_input と、ツールが返した結果である tool_response の両方が含まれます。どちらの正確なスキーマもツールによって異なります。ファイルツールの tool_input のパスは PreToolUse と同じ形式で渡されます。つまり、常に絶対パスで、プラットフォーム固有の区切り文字(Windows ではバックスラッシュ)が使われます。MCP ツールの場合、入力には mcp_server オブジェクトも含まれます。

PostToolUse の決定制御

PostToolUse フックは、ツール実行後に Claude にフィードバックを提供できます。すべてのフックで利用できる JSON 出力フィールドに加えて、フックスクリプトは次のイベント固有のフィールドを返すことができます。 次の例は、Bash 呼び出しの出力を置き換えます。置き換える値は Bash ツールの出力の形式と一致しています。
updatedToolOutput が変更するのは、Claude に表示される内容だけです。フックが発火する時点でツールはすでに実行されているため、書き込まれたファイル、実行されたコマンド、送信されたネットワークリクエストはすでに反映されています。OpenTelemetry のツールスパンや分析イベントなどのテレメトリも、フックの実行前に元の出力を記録します。ツール呼び出しを実行前に阻止または変更するには、代わりに PreToolUse フックを使用してください。置き換える値は、ツールの出力の形式と一致している必要があります。組み込みツールは、プレーンな文字列ではなく構造化されたオブジェクトを返します。たとえば Bash は、stdout、stderr、interrupted、isImage フィールドを持つオブジェクトを返します。組み込みツールの場合、ツールの出力スキーマと一致しない値は無視され、元の出力が使用されます。MCP ツールの出力は、スキーマ検証なしでそのまま渡されます。Claude が必要とするエラーの詳細を取り除くと、Claude が誤った前提のまま処理を進める可能性があります。

auto モードの分類器向けに結果に注釈を付ける

classifierContext を返すと、ツール呼び出しの結果に関する短いメモを、Claude ではなく auto モードの分類器に送信できます。分類器はツールの結果そのものを受け取ることはないため、このフィールドは、分類器が後続のアクションを審査する前に、呼び出しが返した内容について伝えるためのサポートされた方法です。このフィールドには Claude Code v2.1.236 以降が必要です。 次の例は、クエリの出力がどこから得られたかを分類器に伝えます。
分類器がこのメモをどの程度重視するかは、フックを設定した場所によって異なります。
  • Claude Code で設定されたフック:設定ファイル、プラグイン、スキル、エージェントのフロントマターに由来するフックの場合、分類器はメモを未検証のアプリケーション提供コンテキストとして扱います。メモがユーザーの意図を立証することはなく、メモがユーザーが何かを承認または要求したと主張している場合、分類器はその主張を会話内のユーザー自身のメッセージと照合します
  • プロセス内の Agent SDK コールバック:Claude Code を組み込んだアプリケーションがフックを TypeScript SDK コールバックとして登録し、実行中のセッションでメモを返す場合、分類器はメモで伝えられたユーザーの発言をユーザーの意図として考慮することがあります。そのような発言は、ユーザーが送信するメッセージであれば分類器が受け入れる同意要件を満たすことはできますが、ユーザー自身のメッセージでも解除できないブロックを解除することはありません。セッションが再開された後は、Claude Code は復元されたメモを未検証のコンテキストとして扱います。両方のグループのフックが同じ呼び出しに注釈を付けた場合、分類器は結合されたメモを未検証として扱います
Claude Code は、メモを配信する際に次の制限を適用します。
  • 長さ:Claude Code は 1 回のツール呼び出しに対するメモを 2,000 文字に制限し、残りを切り捨てます。この上限は、その呼び出しに応答するすべてのフックで共有されます
  • 同期応答のみ:バックグラウンドで実行されるフックの応答では、Claude Code はこのフィールドを無視します。その応答は、Claude Code がツールの結果を記録した後に届くためです
  • 分類器が記録しない呼び出し:分類器のトランスクリプトでは、ファイルの読み取りや検索などの読み取り専用の参照は省略されます。Claude Code は、そのような呼び出しに付けられたメモを破棄します
  • 書き換えとの相互作用:updatedToolOutput で置き換える出力についてメモを記述する場合は、同じフックの応答で両方のフィールドを返してください。その書き換えが拒否された場合や、別のフックの書き換えによって置き換えられた場合、Claude Code はメモを破棄します。書き換えなしで返したメモは、別のフックが出力を書き換えた場合でも配信されます
分類器は、classifierContext に記述された内容を、セッションをホストしているアプリケーションからの情報として読み取ります。そのため、信頼できないツールの出力やサードパーティのテキストをこのフィールドにコピーしないでください。メモは、その呼び出しの出所に関する事実や、その呼び出しに関するユーザーの発言など、この 1 回の呼び出しについての短い主張にとどめてください。無関係なメッセージやイベントのストリームを配信する目的でこのフィールドを使用しないでください。

PostToolUseFailure

実行を開始したツールが失敗したとき、つまりツールがエラーをスローした場合や、MCP ツールがエラー結果を返した場合に実行されます。失敗のログ記録、アラートの送信、Claude への是正フィードバックの提供に使用します。 ツール名で照合します。値は PreToolUse と同じです。
このイベントは、実行前に拒否されたツール呼び出し(不明なツール名、スキーマやツール固有の検証に失敗した入力、権限の拒否)では発火しません。検証による拒否は tool_use_error の結果として返され、フックの実行前に発生するため、PreToolUse も PostToolUseFailure も発火しません。権限の拒否では PreToolUse は発火しますが、このイベントは発火しません。PermissionDenied を参照してください。

PostToolUseFailure の入力

PostToolUseFailure フックは、PostToolUse と同じ tool_name と tool_input フィールドに加えて、トップレベルのフィールドとしてエラー情報を受け取ります。MCP ツールの場合は、mcp_server オブジェクトも受け取ります。たとえば、npm test コマンドが失敗した場合は次のように渡されます。
error 文字列は、一般に、失敗したツールの結果として Claude が受け取るテキストと同じです。その形式はツールや失敗の内容によって異なります。フックの判定には tool_name、is_interrupt、および 1 行目の Exit code N を使用し、文字列の残りの部分は安定した形式ではなく表示用のテキストとして扱ってください。
  • Bash と PowerShell では、実行されて終了したコマンドの場合、1 行目が Exit code N となり、その後にコマンドが生成した出力が、stdout と stderr が混在した 1 つのブロックとして続きます
  • Claude Code がシェルプロセス自体を起動できなかった場合、ペイロードには終了コードの行がない失敗メッセージのみが含まれることもあります
  • Claude Code は長い文字列を ... [N characters truncated] ... マーカーを挟んで中間部分を切り詰めます。また、Command timed out after 2m 0s のような独自の行を挿入することもあります

PostToolUseFailure の決定制御

PostToolUseFailure フックは、ツールの失敗後に Claude にコンテキストを提供できます。すべてのフックで利用できる JSON 出力フィールドに加えて、フックスクリプトは次のイベント固有のフィールドを返すことができます。

PostToolBatch

バッチ内のすべてのツール呼び出しが解決した後、Claude Code がモデルに次のリクエストを送信する前に 1 回実行されます。PostToolUse はツールごとに 1 回発火するため、Claude が並列にツールを呼び出すと同時に発火します。PostToolBatch はバッチ全体に対して正確に 1 回だけ発火するため、個々のツールではなく、実行されたツールの組み合わせに依存するコンテキストを注入するのに適しています。このイベントには matcher はありません。

PostToolBatch の入力

共通入力フィールドに加えて、PostToolBatch フックはバッチ内のすべてのツール呼び出しを記述する配列 tool_calls を受け取ります。
tool_response には、モデルが対応する tool_result ブロックで受け取るものと同じ内容が含まれます。値は、ツールが出力したとおりのシリアライズされた文字列またはコンテンツブロックの配列です。Read の場合は、生のファイル内容ではなく、行番号が先頭に付いたテキストになります。応答は大きくなる可能性があるため、必要なフィールドだけを解析してください。
tool_response の形式は PostToolUse のものとは異なります。PostToolUse は、Write の場合の {filePath: "...", type: "create"} のような、ツールの構造化された Output オブジェクトを渡します。PostToolBatch は、モデルに表示される、シリアライズされた tool_result の内容を渡します。

PostToolBatch の決定制御

PostToolBatch フックは、Claude 向けのコンテキストを注入できます。すべてのフックで利用できる JSON 出力フィールドに加えて、フックスクリプトは次のイベント固有のフィールドを返すことができます。
decision: "block" または continue: false を返すと、次のモデル呼び出しの前にエージェント型ループが停止します。ブロックメッセージは、JSON の reason または stopReason、あるいは終了コード 2 の場合の stderr から取得されます。このメッセージはトランスクリプトに警告として表示され、会話内に残るため、会話が続行されると Claude にも表示されます。

PermissionDenied

auto モードがツール呼び出しを拒否したときに実行されます。これには、auto モードとは別の安全性チェックが分類器自身のリクエストを拒否した場合や、分類器の応答を解析できなかった場合など、分類器の判定なしで拒否した場合も含まれます。このフックは auto モードでのみ発火します。権限ダイアログを手動で拒否した場合、PreToolUse フックが呼び出しをブロックした場合、deny ルールに一致した場合には実行されません。拒否のログ記録、設定の調整、またはツール呼び出しを再試行してよいことをモデルに伝えるために使用します。 ツール名で照合します。値は PreToolUse と同じです。

PermissionDenied の入力

共通入力フィールドに加えて、PermissionDenied フックは tool_name、tool_input、tool_use_id、reason を受け取ります。MCP ツールの場合は、mcp_server オブジェクトも受け取ります。

PermissionDenied の決定制御

PermissionDenied フックは、拒否されたツール呼び出しを再試行してよいことをモデルに伝えることができます。hookSpecificOutput.retry を true に設定した JSON オブジェクトを返します。
retry が true の場合、Claude Code はツール呼び出しを再試行してよいことをモデルに伝えるメッセージを会話に追加します。Claude Code が拒否そのものを取り消すことはありません。フックが JSON を返さない場合、または retry: false を返した場合、拒否はそのまま維持され、モデルは元の拒否メッセージを受け取ります。 分類器がアクションに対する判定を出さなかった場合、つまり分類器の応答を解析できなかった場合や、auto モードとは別の安全性チェックが分類器自身のリクエストを拒否した場合、Claude Code は retry: true を無視します。これらの拒否については、後で再試行するか次に進むかを、Claude Code が拒否メッセージの中ですでにモデルに伝えています。

Notification

Claude Code が通知を送信するときに実行されます。通知タイプで照合します。すべての通知タイプでフックを実行するには、matcher を省略します。 デスクトップ通知をオフにしていても、これらのフックイベントは受け取ります。preferredNotifChannel 設定(notifications_disabled を含む)が変更するのはユーザーへの通知方法だけであり、フックが実行されるかどうかには影響しません。 quota_auto_resume_fired、quota_auto_resume_stale、quota_auto_resume_disabled タイプには Claude Code v2.1.234 以降が必要です。 ターミナルセッションでは、サンドボックス化されたコマンドのネットワークリクエストに対する permission_prompt には Claude Code v2.1.246 以降が必要です。 チームメイトのターミナル設定に関する質問に対する agent_needs_input には Claude Code v2.1.248 以降が必要です。
permission_prompt、idle_prompt、elicitation_dialog、elicitation_url_dialog タイプはデスクトップ通知とタイミングを共有しているため、ターミナルセッションでは、ユーザーがターミナルから離れていると判断される場合にのみ表示されます。
  • permission_prompt は、ユーザーが約 6 秒間入力していないときに発火します。タイマーは権限プロンプトが表示されたときに開始され、キー入力のたびに延期されます。Claude がツールの使用権限を求めたときにすぐにフックを実行するには、代わりに PermissionRequest を使用してください。
  • idle_prompt は、Claude が応答を完了してから約 60 秒後に発火します。ただし、それ以降ユーザーが入力しておらず、バックグラウンドのサブエージェントなどのバックグラウンドエージェントが実行中でない場合に限ります。claude.ai の使用制限のリセットを待っている間、Claude Code は idle_prompt を送信しません。待機が自然に終了すると、代わりに quota_auto_resume_* タイプのいずれかが発火します。
  • elicitation_dialog(elicitation フォームの場合)または elicitation_url_dialog(ブラウザの URL リクエストの場合)は、ユーザーが約 6 秒間入力していないときに発火します。どちらも permission_prompt と同じ 6 秒間の条件を共有しており、タイマーはダイアログが表示されたときに開始され、キー入力のたびに延期されます。
別のダイアログが画面に表示されている間に届いた権限リクエストや elicitation にも、同じ 6 秒間の条件が適用され、タイマーはリクエストが届いた時点から計測されます。そのため、リクエストが開いているダイアログの後ろで待機している間に、その通知が届くことがあります。
Claude Code が権限リクエストを Agent SDK の canUseTool コールバックに送信するセッションでは、permission_prompt のタイミングが異なります。これは、Claude Desktop と VS Code 拡張機能が Claude Code をホストする方法です。
  • permission_prompt は、Claude が権限を求めてから約 6 秒後に発火します。ユーザーが入力している間も延期されません。
  • ユーザーまたは PermissionRequest フックがそれより早く応答した場合、Claude Code は permission_prompt を実行しません。
  • これらのセッションで permission_prompt をオフにするには、CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS を 1 に設定します。
v2.1.233 より前では、これらのセッションで permission_prompt は発火しませんでした。 通知タイプに応じて異なるハンドラーを実行するには、別々の matcher を使用します。次の設定では、Claude が権限の承認を必要とするときは権限専用のアラートスクリプトを、Claude がアイドル状態のときは別の通知を起動します。

Notification の入力

共通入力フィールドに加えて、Notification フックは通知テキストを含む message、オプションの title、どのタイプが発火したかを示す notification_type を受け取ります。
Notification フックは、通知をブロックしたり変更したりすることはできません。Claude Code はこれらのフックの systemMessage と continue フィールドを破棄しますが、terminalSequence は引き続き出力します。デスクトップ通知の例はこれを利用しています。Notification フックは、通知を外部サービスに転送するなどの副作用を目的としています。

SubagentStart

Claude が Agent ツールでサブエージェントを生成したとき、Claude がサブエージェントを再開したとき、およびプロセス内のエージェントチームのチームメイトが新しいメッセージを処理するたびに実行されます。エージェントタイプ名でフィルタリングする matcher をサポートしています。組み込みエージェントの場合、これは general-purpose、Explore、Plan などのエージェント名です。カスタムサブエージェントの場合は、ファイル名ではなく、エージェントのフロントマターの name フィールドです。 プラグインに含まれるサブエージェントの場合、エージェントタイプは素のフロントマターの名前ではなく、my-plugin:reviewer のようなプラグインスコープの識別子になります。コロンが含まれるとプラグインスコープの名前は正規表現として扱われるため、完全一致させるには matcher を ^ と $ で固定してください(^my-plugin:reviewer$)。

SubagentStart の入力

共通入力フィールドに加えて、SubagentStart フックは、サブエージェントの一意の識別子を含む agent_id と、matcher がフィルタリングに使用するエージェント名を含む agent_type を受け取ります。
SubagentStart フックはサブエージェントの作成をブロックできませんが、サブエージェントにコンテキストを注入できます。すべてのフックで利用できる JSON 出力フィールドに加えて、次のフィールドを返すことができます。
同じサブエージェントに対してフックが再度実行された場合、Claude Code は、サブエージェントのコンテキストに以前の実行時のコピーがまだ含まれていない場合にのみ、返されたコンテキストを注入します。起動時に注入されたコピーはそのまま残るため、サブエージェントのプロンプトキャッシュは維持されます。自動圧縮によってそのコピーが破棄された後は、Claude Code は次の実行時のコンテキストを再び注入します。

SubagentStop

Claude Code のサブエージェントが応答を完了したときに実行されます。エージェントタイプで照合します。値は SubagentStart と同じです。

SubagentStop の入力

共通入力フィールドに加えて、SubagentStop フックは stop_hook_active、agent_id、agent_type、agent_transcript_path、last_assistant_message を受け取ります。agent_type フィールドは、matcher のフィルタリングに使用される値です。transcript_path はメインセッションのトランスクリプトであり、agent_transcript_path はネストされた subagents/ フォルダに保存されているサブエージェント自身のトランスクリプトです。last_assistant_message フィールドにはサブエージェントの最終応答のテキスト内容が含まれるため、フックはトランスクリプトファイルを解析せずにアクセスできます。 すべての SubagentStop イベントが、Claude が生成したサブエージェントに由来するわけではありません。Claude Code は、プロンプトの提案や /btw による横道の質問など、一部の独自機能のために内部エージェントも実行しており、それらが完了したときにも SubagentStop が発火します。これらのイベントでは、agent_type は --agent や agent 設定で設定されたものなど、セッション自体が実行されているエージェント名になり、セッションがエージェントなしで実行されている場合は空文字列になります。 エージェントタイプを指定する matcher は、空の agent_type には一致しません。matcher が省略されているフック、"" または "*" のフック、あるいは空文字列に一致する正規表現のフックは、agent_type が空のイベントでも実行されます。 Claude Code v2.1.271 以降では、SubagentHandback ツールを使用して実行されるサブエージェントは、停止する前にそのツールを通じてレポートを配信します。その場合、last_assistant_message フィールドには、配信されたレポートではなく、サブエージェントの締めくくりのテキスト(存在する場合)が含まれます。レポートはその呼び出しの message 入力であり、SubagentHandback に一致する PreToolUse または PostToolUse フックは、これを tool_input.message として受け取ります。 SubagentStop フックは、Stop の入力で説明している background_tasks と session_crons 配列も受け取ります。どちらの配列も、サブエージェントではなく親セッションのスコープです。
SubagentStop フックは、Stop フックと同じ決定制御の形式を使用します。これには、サブエージェントの実行を継続させるエラー以外のフィードバックとして、hookEventName を "SubagentStop" に設定した hookSpecificOutput.additionalContext も含まれます。reason とともに decision: "block" を返すと、サブエージェントの実行が継続され、reason が次の指示としてサブエージェントに配信されます。終了コード 2 で終了してブロックするフックも、同じ方法で stderr メッセージを配信します。サブエージェントが戻った後に親セッションにコンテキストを注入するには、代わりに Agent ツールに対する PostToolUse フックを使用してください。

TaskCreated

TaskCreate ツールでタスクが作成されるときに実行されます。命名規則の適用、タスクの説明の必須化、特定のタスクの作成防止に使用します。Task ツールがないセッションでは、このイベントは発火しません。 TaskCreated フックは matcher をサポートせず、すべての発生時に発火します。

TaskCreated の入力

共通入力フィールドに加えて、TaskCreated フックは task_id、task_subject、およびオプションで task_description、teammate_name、team_name を受け取ります。

TaskCreated の決定制御

TaskCreated フックは、終了コード 2 または JSON の決定によって作成をブロックできます。いずれの場合も、Claude Code はタスクを削除し、メッセージをツールのエラーとして Claude に返します。Claude Code はこのイベントからの continue: false を無視し、Claude は作業を続けます。
  • 終了コード 2:Claude Code は stderr のテキストをメッセージとして返します。
  • JSON {"decision": "block", "reason": "..."}:Claude Code は reason をメッセージとして返します。
次の例は、件名が必須の形式に従っていないタスクをブロックします。

TaskCompleted

タスクが完了としてマークされるときに実行されます。これは 2 つの状況で発火します。いずれかのエージェントが TaskUpdate ツールを通じてタスクを明示的に完了としてマークしたとき、またはエージェントチームのチームメイトが進行中のタスクを抱えたままターンを終了したときです。タスクを閉じる前に、テストや lint チェックの合格といった完了基準を適用するために使用します。 TaskCompleted フックは matcher をサポートせず、すべての発生時に発火します。

TaskCompleted の入力

共通入力フィールドに加えて、TaskCompleted フックは task_id、task_subject、およびオプションで task_description、teammate_name、team_name を受け取ります。

TaskCompleted の決定制御

TaskCompleted フックは、タスクの完了を制御する 2 つの方法をサポートしています。
  • 終了コード 2:タスクは完了としてマークされず、stderr メッセージがフィードバックとしてモデルに返されます。
  • JSON {"continue": false, "stopReason": "..."}:チームメイトがターンを終了したことでイベントが発生した場合、Stop フックの動作と同様に、チームメイトを完全に停止します。stopReason はユーザーに表示されます。TaskUpdate ツールによってイベントが発生した場合、Claude Code は continue: false を無視しますが、終了コード 2 では引き続き完了をブロックできます。
次の例はテストを実行し、失敗した場合はタスクの完了をブロックします。

Stop

メインの Claude Code エージェントが応答を完了したときに実行されます。 ユーザーの中断によって停止した場合は実行されません。API エラーの場合は、 代わりに StopFailure が発火します。
/goal コマンドは、セッションスコープのプロンプトベースの Stop フックの組み込みショートカットです。フックの設定を書かずに、ある条件に向けて Claude に作業を続けさせたい場合に使用してください。

Stop の入力

共通入力フィールドに加えて、Stop フックは stop_hook_active、last_assistant_message、background_tasks、session_crons を受け取ります。stop_hook_active フィールドは、Claude Code が Stop フックの結果としてすでに続行している場合に true になります。決して解決しない条件でブロックし続けることを避けるため、この値を確認するか、トランスクリプトを処理してください。 Claude Code は連続 8 回の継続上限を適用します。Stop フックが 8 回連続でターンを継続させた後、Claude Code は次のブロックを上書きしてターンを終了します。連続継続の回数は、Claude がツールを呼び出すたびにリセットされます。上限を引き上げるには、CLAUDE_CODE_STOP_HOOK_BLOCK_CAP を設定してください。 last_assistant_message フィールドには Claude の最終応答のテキスト内容が含まれるため、フックはトランスクリプトファイルを解析せずにアクセスできます。読み上げフックや通知フックなど、完了したばかりのターンに対して動作するフックでは、transcript_path を読み取るのではなく、このフィールドを使用してください。すべてのバージョンで、Stop の時点でトランスクリプトファイルに最終メッセージが含まれているとは限らないためです。 background_tasks と session_crons 配列を使うと、フックは「セッションが完了した」状態と「バックグラウンドの作業によって再開されるのを待って一時停止している」状態を区別できます。どちらの配列も、タスクレジストリにアクセスできる場合に存在し、実行中またはスケジュール済みのものがない場合は空になります。 background_tasks の各エントリは 1 つの実行中のタスクを表し、次のフィールドを使用します。 session_crons の各エントリは、CronCreate、ScheduleWakeup、/loop に由来する、セッションスコープのスケジュール済みの再開を 1 つ表します。 次の例は、実行中のシェルタスク 1 つと繰り返しの cron 1 つを含む Stop の入力を示しています。

Stop の決定制御

Stop と SubagentStop フックは、Claude が続行するかどうかを制御できます。すべてのフックで利用できる JSON 出力フィールドに加えて、フックスクリプトは次のイベント固有のフィールドを返すことができます。 終了コード 2 で終了してブロックするフックは、reason と同じ方法で処理されます。Claude は stderr メッセージを、続行すべき理由の説明として受け取ります。
フックが設計どおりに動作していて、「終了前にテストスイートを実行する」などのガイダンスを Claude に与える場合は、additionalContext を使用します。これは、decision: "block" と同じループ保護(stop_hook_active 入力と連続 8 回の継続上限)を通じて会話を継続させますが、トランスクリプトでは Stop hook feedback とラベル付けされ、フックエラーの通知は表示されません。

StopFailure

API エラーによってターンが終了したときに、Stop の代わりに実行されます。Claude Code は、terminalSequence を除き、フックの出力と終了コードを無視します。レート制限、認証の問題、その他の API エラーによって Claude が応答を完了できない場合に、失敗のログ記録、アラートの送信、復旧アクションの実行に使用します。

StopFailure の入力

共通入力フィールドに加えて、StopFailure フックは error、オプションの error_details、オプションの last_assistant_message を受け取ります。error フィールドはエラーの種類を示し、matcher のフィルタリングに使用されます。
StopFailure フックには決定制御がありません。通知とログ記録の目的でのみ実行されます。

TeammateIdle

エージェントチームのチームメイトがターンを終了した後、アイドル状態になろうとしているときに実行されます。lint チェックの合格を必須にしたり、出力ファイルが存在することを確認したりするなど、チームメイトが作業を停止する前に品質ゲートを適用するために使用します。 TeammateIdle フックは matcher をサポートせず、すべての発生時に発火します。

TeammateIdle の入力

共通入力フィールドに加えて、TeammateIdle フックは teammate_name と team_name を受け取ります。

TeammateIdle の決定制御

TeammateIdle フックは、チームメイトの動作を制御する 2 つの方法をサポートしています。
  • 終了コード 2:チームメイトは stderr メッセージをフィードバックとして受け取り、アイドル状態にならずに作業を続けます。
  • JSON {"continue": false, "stopReason": "..."}:Stop フックの動作と同様に、チームメイトを完全に停止します。stopReason はユーザーに表示されます。
次の例は、チームメイトがアイドル状態になるのを許可する前に、ビルドアーティファクトが存在することを確認します。

ConfigChange

セッション中に設定ファイルが変更されたときに実行されます。設定変更の監査、セキュリティポリシーの適用、設定ファイルへの不正な変更のブロックに使用します。 Claude Code は、設定ファイル、管理ポリシーファイル、またはスキルファイルが変更されたときに ConfigChange フックを実行します。管理ポリシーについては、managed-settings.json または managed-settings.d/ 内のファイルが変更された場合にのみ実行します。サーバー管理設定や、macOS の管理された環境設定、Windows レジストリのポリシーへの変更は、フックを実行せずに適用されます。wslInheritsWindowsSettings を使用した WSL では、変更された Windows 側の管理設定ファイルも、ポリシーのポーリング時にフックを実行せずに適用されます。 matcher は設定のソースでフィルタリングします。 次の例は、セキュリティ監査のためにすべての設定変更をログに記録します。

ConfigChange の入力

共通入力フィールドに加えて、ConfigChange フックは source と、オプションで file_path を受け取ります。source フィールドはどの種類の設定が変更されたかを示し、file_path は変更された特定のファイルへのパスを提供します。

ConfigChange の決定制御

ConfigChange フックは、設定変更が反映されるのをブロックできます。変更を阻止するには、終了コード 2 または JSON の decision を使用します。ブロックされた場合、新しい設定は実行中のセッションに適用されません。
policy_settings の変更はブロックできません。マシン上の管理設定ファイルが変更されたときには policy_settings ソースに対してもフックが発火するため、それらの編集をログに記録するために使用できますが、ブロックの決定は無視されます。これにより、エンタープライズで管理された設定が常に反映されることが保証されます。サーバー管理設定が届いたときや更新されたときには、Claude Code は ConfigChange フックを実行しません。 Claude Code は ConfigChange フックの JSON 出力のうちブロックの決定に基づいて動作し、systemMessage と continue は破棄します。reason でブロックした場合も、終了コード 2 の stderr でブロックした場合も、ブロックされた変更についてユーザーや Claude にメッセージが表示されることはありません。Claude Code はデバッグログに 1 行を書き込むだけです。

CwdChanged

メインの会話内のシェルコマンドが作業ディレクトリを変更したとき、たとえば Claude が cd コマンドを実行したときに実行されます。環境変数の再読み込み、プロジェクト固有のツールチェーンの有効化、セットアップスクリプトの自動実行など、ディレクトリの変更に反応するために使用します。ディレクトリごとの環境を管理する direnv のようなツールでは、FileChanged と組み合わせて使用します。 CwdChanged フックは CLAUDE_ENV_FILE にアクセスできます。そのファイルに書き込まれた変数は、次の CwdChanged イベントで Claude Code によってクリアされるまで、後続の Bash コマンドに引き継がれます。 CwdChanged は matcher をサポートせず、すべての発生時に発火します。

CwdChanged の入力

共通入力フィールドに加えて、CwdChanged フックは old_cwd と new_cwd を受け取ります。

CwdChanged の出力

すべてのフックで利用できる JSON 出力フィールドに加えて、CwdChanged フックは watchPaths を返して、FileChanged が監視するファイルパスを動的に設定できます。 CwdChanged フックには決定制御がありません。ディレクトリの変更をブロックすることはできません。 Claude Code は、これらのフックの JSON 出力から watchPaths と systemMessage を読み取り、continue は破棄します。対話型セッションでは、systemMessage を短いターミナル通知として表示します。このメッセージは SDK のメッセージストリームには届きません。

DirectoryAdded

セッションの途中で /add-dir コマンドを使用して作業ディレクトリを追加した後、または SDK クライアントが register_repo_root 制御リクエストでディレクトリを追加した後に実行されます。新しく追加されたリポジトリの依存関係をインストールするなど、リポジトリの準備に使用します。 Claude Code は、次の場合にはこのイベントを発火しません。
  • --add-dir 起動フラグでディレクトリを渡した場合。これらのディレクトリは SessionStart で対応します
  • /permissions の Workspace タブでディレクトリを追加した場合
  • すでに作業ディレクトリであるディレクトリ、または作業ディレクトリ内のディレクトリを追加した場合
Claude Code はサンドボックスと権限の状態を更新した後に DirectoryAdded を発火するため、フックの実行時には、サンドボックス化されたツールからすでに新しいディレクトリが見える状態になっています。フックのコマンド自体はサンドボックス外で実行されます。 Claude Code はフックを待ちません。追加はすぐに完了し、フックはデフォルトの 600 秒のタイムアウトでバックグラウンドで実行されます。 matcher は、ディレクトリがどのように追加されたかでフィルタリングします。

DirectoryAdded の入力

共通入力フィールドに加えて、DirectoryAdded フックは directory と source を受け取ります。
DirectoryAdded フックには決定制御がありません。フックの実行時には追加がすでに完了しているため、追加をブロックすることはできません。Claude Code はこれらのフックの JSON 出力から continue フィールドを破棄し、残りはソースに応じて異なる方法で表示します。
  • slash_command:Claude Code はフックの systemMessage をユーザーに表示するのではなく、次の会話ターンでコンテキストとして Claude に配信します。失敗したフックの数がトランスクリプトに表示されます。失敗の完全な出力はデバッグログに記録されます
  • register_repo_root:Claude Code は systemMessage の出力と失敗の出力をデバッグログにのみ書き込みます

FileChanged

監視対象のファイルがディスク上で変更されたときに実行されます。Claude Code はツール呼び出しを調べるのではなく、ファイルシステムウォッチャーで変更を検出するため、ファイルを何が変更したかに関係なくフックを実行します。Edit や Write のツール呼び出し、Claude が Bash で実行するスクリプト、あるいは Claude Code とはまったく無関係のプロセスのいずれでも同様です。一般的な用途は、プロジェクトの設定ファイルが変更されたときに環境変数を再読み込みすることです。 このイベントの matcher には 2 つの役割があります。
  • 監視リストを構築する: 値は | で分割され、各セグメントが作業ディレクトリ内のリテラルなファイル名として登録されます。そのため ".envrc|.env" はちょうどこの 2 つのファイルを監視します。ここでは正規表現パターンは役に立ちません。^\.env のような値は、文字どおり ^\.env という名前のファイルを監視します。
  • 実行するフックを絞り込む: 監視対象のファイルが変更されると、同じ値が標準の matcher ルールに従い、変更されたファイルのベース名に対して照合され、実行するフックグループが絞り込まれます。
次の例は、Bash コマンドや外部スクリプトによる書き換えも含め、data.csv が変更されるたびにその改行コードを正規化します。
このフックは、stdin で受け取る JSON 入力の file_path フィールドから、変更されたファイルの絶対パスを読み取ります。grep によるガードは perl が削除するものと同じもの、つまり行末の CR を検査するため、正規化後の実行ではファイルに触れずに終了します。これより緩いガードにすると無限ループになります。perl -i は何も置換しない場合でもファイルを書き換え、Claude Code は書き換えのたびにフックを再実行するためです。このスクリプトを /path/to/normalize-line-endings.sh に保存し、実行可能にしてください。
フックが動作することを確認するには、Bash コマンドで data.csv に CRLF の行を追記するよう Claude に依頼します。Claude Code がフックを実行し、ファイルの改行コードは LF になります。 事前に名前を指定できないファイルを監視するには、フックから watchPaths を返して監視リストを動的に更新します。Claude Code は、監視するファイルを何かが指定したときにのみウォッチャーを起動します。そのため、少なくとも 1 つのファイルを指定する matcher を持つ FileChanged グループか、watchPaths を返す SessionStart フックまたは CwdChanged フックで、リストに初期値を与えてください。監視対象のファイルが変更されたときには引き続き matcher によって実行するフックグループが絞り込まれるため、動的なパスを処理するグループでは matcher を省略してください。省略した matcher は監視対象のすべてのファイルに一致し、監視リストには何も追加しません。"*" の matcher もすべてのファイルに一致しますが、Claude Code はほかの値と同様にこれを監視リストに登録し、* という名前のリテラルなファイルとして扱います。 FileChanged フックは CLAUDE_ENV_FILE にアクセスできます。このファイルに書き込まれた変数は、次の CwdChanged イベントで Claude Code がクリアするまで、以降の Bash コマンドに引き継がれます。

FileChanged の入力

共通の入力フィールドに加えて、FileChanged フックは file_path と event を受け取ります。

FileChanged の出力

すべてのフックで使用できる JSON 出力フィールドに加えて、FileChanged フックは watchPaths を返して、監視するファイルパスを動的に更新できます。 FileChanged フックには判定の制御がありません。ファイルの変更が発生するのをブロックすることはできません。 Claude Code は JSON 出力から watchPaths と systemMessage を読み取り、continue は破棄します。対話セッションでは、systemMessage を短いターミナル通知として表示します。このメッセージは SDK のメッセージストリームには届きません。

WorktreeCreate

次のようなケースで Claude Code が worktree を作成するときに実行されます。 Claude が EnterWorktree を呼び出すのではなく、Bash ツールを通じて git worktree add を実行した場合、WorktreeCreate フックは実行されません。そのコマンドを検査またはブロックするには、Bash matcher を持つ PreToolUse フックを追加してください。 デフォルトでは、Claude Code は git worktree を使って分離された作業コピーを作成します。WorktreeCreate フックを設定すると、このデフォルトの git の動作が置き換えられ、SVN、Perforce、Mercurial などの別のバージョン管理システムを使用できるようになります。 フックはデフォルトの動作を完全に置き換えるため、.worktreeinclude は処理されません。.env のようなローカルの設定ファイルを新しい worktree にコピーする必要がある場合は、フックスクリプトの中で行ってください。 フックは、作成した worktree ディレクトリへのパスを返す必要があります。Claude Code はこのパスを、分離されたセッションの作業ディレクトリとして使用します。各フックタイプがパスを返す方法については、WorktreeCreate の出力を参照してください。 Claude Code はフックの成功と返されたパスに基づいて動作し、systemMessage と continue は破棄します。 次の例は SVN の作業コピーを作成し、Claude Code が使用するパスを出力します。リポジトリの URL は自分のものに置き換えてください。
このフックは stdin の JSON 入力から worktree の name を読み取り、新しいディレクトリに新規のコピーをチェックアウトして、そのディレクトリのパスを出力します。最後の行の echo が、Claude Code が worktree のパスとして読み取るものです。パスの妨げにならないよう、それ以外の出力はすべて stderr にリダイレクトしてください。

WorktreeCreate の入力

共通の入力フィールドに加えて、WorktreeCreate フックは name フィールドを受け取ります。これは新しい worktree のスラッグ識別子で、ユーザーが指定したものか自動生成されたもの(例: bold-oak-a3f2)です。

WorktreeCreate の出力

WorktreeCreate フックは、標準の許可/ブロックの判定モデルを使用しません。代わりに、フックの成功または失敗によって結果が決まります。フックは、作成した worktree ディレクトリへのパスを返す必要があります。
  • コマンドフック(type: "command"): パスを stdout の最後の空でない行として出力します。Claude Code はその行を読み取る前に ANSI エスケープコードを取り除くため、echo より前に出力されたシェルの起動バナーは無視されます。フックのそれ以外の出力は stderr にリダイレクトしてください。
  • HTTP フック(type: "http"): レスポンス本文で { "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } } を返します。
フックが失敗した場合やパスを出力しなかった場合、worktree の作成はエラーで失敗します。 Claude Code は相対パスをフックが実行されたディレクトリを基準に解決し、その中の . や .. のセグメントを折りたたみます。結果のパスが Claude Code が移動できるディレクトリでない場合、セッションはそのパスを示すエラーを出力し、終了コード 1 で終了します。 Claude Code は、. や .. のセグメントを含む絶対パス、およびリポジトリのルートより下でシンボリックリンクを経由するパスを拒否します。リポジトリにコミットされたシンボリックリンクによって、worktree がリポジトリの外にリダイレクトされる可能性があるためです。エラーには拒否された構成要素が示されます。リポジトリ内のシンボリックリンクを経由しない、正規化されたパスを返してください。v2.1.216 より前は、worktree の作成はこのチェックを行わずにフックのパスに従っていました。

WorktreeRemove

WorktreeCreate フックが作成した worktree を Claude Code がクリーンアップするときに実行されます。このイベントは次の場合に発生します。
  • 対話的な worktree セッションを終了し、Claude Code に確認されたときに worktree の削除を選択した
  • 名前を付けていない対話的な worktree セッションを終了し、Claude Code が変更済みまたは未追跡のファイルを見つけなかったため、確認なしで worktree を削除した
  • worktree で実行されているバックグラウンドセッションを削除した
  • セッション中に worktree を終了して削除するよう Claude に依頼し、Claude が ExitWorktree ツールでそれを削除した
  • claude remote-control が worktree モードで開始したセッションがクラッシュせずに終了し、Claude Code がその worktree に変更済みまたは未追跡のファイルも新しいコミットも見つけなかった
  • worktree モードで開始したセッションがまだ実行中の状態で claude remote-control を停止し、Claude Code がそれらの worktree に変更済みまたは未追跡のファイルも新しいコミットも見つけなかった
サブエージェントやワークフローのエージェントが終了したとき、Claude Code は WorktreeCreate フックがそのエージェントのために作成した worktree を保持し、WorktreeRemove フックは実行しません。作業が完了したら、それらの worktree は自分で削除してください。 ExitWorktree の呼び出しや claude remote-control のクリーンアップでは、Claude Code はフックの実行前に確認を求めません。ExitWorktree は、呼び出しで discard_changes: true が渡されない限り、フックで作成された worktree の削除を拒否します。そのため、この経路ではフックが最後のチェックになります。 Claude Code は git を使って変更済みまたは未追跡のファイルを探すため、git のチェックアウトではない worktree やその中にない worktree では、ディレクトリにコミットされていない作業があっても何も見つけません。WorktreeRemove フックでは、何かを削除する前にそのような作業がないか確認してください。 git ベースの worktree では、Claude Code は git worktree remove でクリーンアップを自動的に処理します。WorktreeCreate フックを設定した場合は、WorktreeRemove フックと組み合わせてクリーンアップを制御してください。
  • WorktreeRemove フックがない場合: 終了時または ExitWorktree による削除では Claude Code は git にフォールバックし、claude remote-control がクリーンアップする場合は worktree を保持します。
    • worktree セッションを終了した場合、または Claude が ExitWorktree を呼び出した場合: Claude Code は WorktreeCreate フックが返したパスを git worktree remove --force と同じように削除するため、git が認識している worktree は削除されます。git が認識していない worktree(たとえば、フックが git 以外のバージョン管理システムで作成したもの)はディスク上に残ります。
    • claude remote-control がセッションの worktree をクリーンアップする場合: worktree はディスク上に残り、claude remote-control を実行しているターミナルに worktree removal failed, kept: <path> と表示されます。
    • バックグラウンドセッションを削除した場合: セッションの削除で削除されるものを参照してください。
  • フックが 0 で終了した場合: worktree は削除済みとみなされます。Claude Code はフックからそれ以外に何も読み取らないため、フックが確実にディレクトリを削除するようにしてください。
  • フックが 0 以外で終了した場合: その後も worktree_path のディレクトリが存在していれば削除は失敗し、worktree は git へのフォールバックなしにディスク上に残ります。0 以外で終了する前にディレクトリを削除したフックは、削除済みとみなされます。失敗の報告方法については、WorktreeRemove の入力を参照してください。
Claude Code は WorktreeCreate フックが返したパスしか把握していないため、フックで作成された worktree に属するブランチを削除することはありません。WorktreeCreate フックがブランチを作成する場合は、WorktreeRemove フックでそれを削除してください。 Claude Code は、systemMessage や continue などの WorktreeRemove フックの JSON 出力フィールドを破棄します。 バックグラウンドセッションの削除では、Claude Code はフックを実行する前に保存されている worktree のパスを検証し、シンボリックリンクであるパスや、リポジトリのルートより下でシンボリックリンクを経由するパスを拒否します。この経路では、まだファイルが含まれている worktree に対してフックが実行されるのは、エージェントビューで削除を確定した場合のみです。そのような worktree の場合、claude rm は代わりにセッションと worktree を保持します。v2.1.216 より前は、これらのチェックなしに保存されたパスに対してフックが実行されていました。 Claude Code は、WorktreeCreate が返したパスをフックの入力の worktree_path として渡します。次の例はそのパスを読み取り、ディレクトリを削除します。

WorktreeRemove の入力

共通の入力フィールドに加えて、WorktreeRemove フックは worktree_path フィールドを受け取ります。これは削除される worktree の絶対パスです。
結果は WorktreeRemove フックの終了コードによって決まります。フックが 0 以外で終了し、その後も worktree_path のディレクトリが存在している場合、削除は失敗します。
  • worktree はディスク上に残り、フックのコマンドと stderr はデバッグログに記録されます。
  • バックグラウンドセッションを削除しようとしていた場合は、セッションも残ります。エージェントビューの拒否メッセージには、exited 1 のようにフックがどのように終了したかが示され、stderr の冒頭が引用され、セッションを再度削除した場合にディレクトリが強制的に削除されるかどうかが示されます。
  • claude remote-control がセッションの worktree をクリーンアップしていた場合は、それを実行しているターミナルに worktree removal failed, kept: <path> と表示されます。

PreCompact

Claude Code がコンテキスト圧縮の操作を実行する直前に実行されます。 matcher の値は、圧縮が手動でトリガーされたか自動でトリガーされたかを示します。 圧縮をブロックするには、終了コード 2 で終了します。手動の /compact の場合、stderr のメッセージがユーザーに表示されます。"decision": "block" を含む JSON を返してブロックすることもできます。 自動圧縮をブロックした場合の効果は、それが発生したタイミングによって異なります。コンテキストの上限に達する前に先回りして圧縮がトリガーされた場合、Claude Code は圧縮をスキップし、会話は圧縮されないまま続行されます。API からすでに返されたコンテキスト上限エラーから回復するために圧縮がトリガーされた場合は、元のエラーが表面化し、現在のリクエストは失敗します。 Claude Code は、PreCompact フックの systemMessage フィールドと continue フィールドを破棄します。

PreCompact の入力

共通の入力フィールドに加えて、PreCompact フックは trigger と custom_instructions を受け取ります。manual の場合、custom_instructions にはユーザーが /compact に渡した内容が含まれ、何も渡さなかった場合は null になります。auto の場合、custom_instructions は null です。

PostCompact

Claude Code がコンテキスト圧縮の操作を完了した後に実行されます。このイベントを使って、圧縮後の新しい状態に対応できます。たとえば、生成された要約をログに記録したり、外部の状態を更新したりできます。Claude Code は、PostCompact フックの systemMessage フィールドと continue フィールドを破棄します。 PreCompact と同じ matcher の値が適用されます。

PostCompact の入力

共通の入力フィールドに加えて、PostCompact フックは trigger と compact_summary を受け取ります。compact_summary フィールドには、圧縮操作によって生成された会話の要約が含まれます。
PostCompact フックには判定の制御がありません。圧縮の結果に影響を与えることはできませんが、後続のタスクを実行できます。

PreModelSwitch

ユーザーまたはクライアントが要求したモデルの切り替えを Claude Code が適用する前に実行されます。切り替えをブロックしたり、確認を求めたり、切り替えにかかるコストを事前に表示したりするために使用します。 PreModelSwitch には Claude Code v2.1.251 以降が必要です。Claude Code は次のリクエストに対してこれを実行します。
  • /model <name> および /model のピッカー
  • Option+P または Alt+P のモデルピッカー
  • /config の Model 設定
  • fast mode をオンにしたことでセッションのモデルが変わる場合
  • Agent SDK のホストまたは Remote Control からの set_model リクエスト、または apply_flag_settings リクエストでのモデル変更
Claude Code は、モデルの自動フォールバックやセッション再開時のモデルの復元など、自身で行う切り替えに対しては PreModelSwitch フックを実行しません。これらの変更は PostModelSwitch にのみ届きます。 Claude Code は、[1m] サフィックスを無視して、セッションの切り替え先モデルの正規名と matcher を比較します。opus のようなエイリアス、日付付きのモデル ID、Amazon Bedrock のモデル ID のようなプロバイダー固有の ID はすべて、解決先の 1 つの正規名に一致します。そのため、claude-opus-5 は Opus 5 のあらゆる表記をカバーします。 たとえば LLM ゲートウェイだけが知っているカスタムモデル ID のように、Claude Code が切り替え先の正規名を特定できない場合は、matcher に関係なくすべての PreModelSwitch フックを実行します。したがって、ブロックを行うフックは matcher だけに頼らず、入力の to_model を確認する必要があります。 matcher は、完全な名前、claude-opus-4-6|claude-opus-5 のような | 区切りのリスト、または .*opus.* のような正規表現で記述します。次の例では完全な名前の matcher を使用し、さらにフックの入力の to_model も確認しています。これにより、終了コード 2 で終了して Opus 4.6 への切り替えを拒否し、それ以外の切り替え先は通過させます。
このコマンドは jq で to_model を確認します。
フックが動作することを確認するには、別のモデルで実行中のセッションから /model claude-opus-4-6 を実行します。Claude Code は現在のモデルを維持し、PreModelSwitch フックが切り替えをブロックしたことを、指定したメッセージを理由として報告します。

PreModelSwitch の入力

共通の入力フィールドに加えて、PreModelSwitch フックは次の表のフィールドを受け取ります。最後の 5 つは、会話を新しいモデルに再送信するのにかかるコストを表しており、フックは切り替えの前にその数値を表示できます。 次の例は、Sonnet 5 で実行中のセッションで /model opus を実行した場合の入力を示しています。

PreModelSwitch の判定の制御

PreModelSwitch フックは、切り替えをキャンセルしたり、ユーザーに確認を求めたり、そのまま続行させたりできます。終了コード 2 またはトップレベルの decision: "block" で切り替えがキャンセルされます。 より細かく制御するには、PreToolUse と同様に、hookSpecificOutput オブジェクトで permissionDecision と permissionDecisionReason を返します。PreModelSwitch は "allow"、"deny"、"ask" を受け付けます。"defer"、updatedInput、additionalContext は受け付けません。次の表で両方のフィールドについて説明します。 "ask" のプロンプトを表示できるのは、対話セッションの /model のみです。-p フラグを使った非対話モード、/config、set_model リクエストを含むその他すべてのサーフェスでは、Claude Code は "ask" を拒否として扱います。 次の例は、context_tokens のトークン数を引用してユーザーに確認を求めます。
複数の PreModelSwitch フックが異なる判定を返した場合、優先順位は deny > ask > allow です。 Claude Code は判定に関係なく、フックが返した systemMessage をユーザーに表示します。そのため、コストを報告するフックは {"systemMessage": "..."} を返して 0 で終了できます。

PreModelSwitch のタイムアウトとその他の終了コード

タイムアウトまでに応答しない PreModelSwitch フックは、切り替えをブロックします。このイベントのデフォルトのタイムアウトは 30 秒です。 有効な JSON 出力なしで 0 または 2 以外の終了コードを返した場合はブロックしないエラーとなり、切り替えは続行されます。ただし、失敗時に切り替えをブロックするフックは例外です。

PostModelSwitch

セッションのモデルが変わった後に実行されます。すべての CLAUDE.md を編集することなく、モデル固有のガイダンスを Claude に与えるために使用します。たとえば、特定のモデルに適用される組織全体の指示などです。 PostModelSwitch には Claude Code v2.1.251 以降が必要です。モデルはすでに変わっているため、ブロックすることはできません。Claude Code は、次のいずれかの変更の後に PostModelSwitch フックを実行します。
  • ユーザーまたはクライアントが要求した切り替え
  • セッションのモデルを変更するモデルの自動フォールバック
  • opusplan のような設定による plan モードへの移行または plan モードからの離脱
  • セッション再開時に Claude Code がモデルを復元した場合
フォールバックモデルチェーンのモデルがターンを処理する場合、Claude Code は PostModelSwitch フックを実行しません。その置き換えは 1 ターンだけのもので、セッションのモデルは変わらないためです。 matcher は PreModelSwitch と同じルールに従います。Claude Code は、セッションの切り替え先モデルの正規名と matcher を比較します。 次の例は、セッションのモデルがいずれかの Opus モデルに変わるたびにガイダンスを追加します。
フックが動作することを確認するには、別のモデルで実行中のセッションから Opus モデルに切り替え(たとえば Sonnet のセッションから /model opus を実行し)、現在のモデルについてどのようなガイダンスがあるか Claude に尋ねます。

PostModelSwitch の入力

PostModelSwitch フックは PreModelSwitch と同じフィールドを受け取ります。ただし、hook_event_name は "PostModelSwitch" に設定され、source の値が 2 つ追加されます。自動フォールバックや Claude Code が自身で行ったその他の変更の場合は "auto"、セッション再開時に復元されたモデルの場合は "resume" です。 source が "auto" の場合、requested_model は null です。source が "resume" の場合は、Claude Code が復元した保存済みのモデル設定になります。

PostModelSwitch の判定の制御

Claude Code は、終了コード 0 の場合のフックのプレーンテキストの stdout、または JSON 出力の additionalContext を受け取り、切り替え後の次のリクエストで Claude に届けます。すべてのフックで使用できる JSON 出力フィールドに加えて、次を返すことができます。 次のプロンプトを送信してから 5 秒以内にフックが完了しない場合、Claude Code はその出力なしでリクエストを送信し、代わりにその次のリクエストに出力を添付します。次のリクエストまでにモデルが複数回変わった場合、Claude Code は最後の切り替え先モデルに対する出力のみを届けます。

SessionEnd

Claude Code のセッションが終了したときに実行されます。クリーンアップタスク、セッション統計のログ記録、 セッション状態の保存に役立ちます。終了理由で絞り込むための matcher をサポートしています。 フックの入力の reason フィールドは、セッションが終了した理由を示します。

SessionEnd の入力

共通の入力フィールドに加えて、SessionEnd フックはセッションが終了した理由を示す reason フィールドを受け取ります。すべての値については、上記の理由の表を参照してください。
SessionEnd フックには判定の制御がありません。セッションの終了をブロックすることはできませんが、クリーンアップタスクを実行できます。Claude Code は、systemMessage などの JSON 出力フィールドを破棄します。 SessionEnd フックのデフォルトのタイムアウトは 1.5 秒です。これは、終了したとき、/clear を実行したとき、または対話的な /resume でセッションを切り替えたときに適用されます。フックにより多くの時間を与えるには、次の 2 つの方法があります。
  • フックごとの timeout: そのフックの設定で timeout を設定します。全体の予算は、設定ファイル内のフックごとの timeout の最大値に合わせて、最大 60 秒まで自動的に引き上げられます。この方法で予算を引き上げた場合でも、独自の timeout を持たないフックはデフォルトのままです。プラグインが提供するフックに設定されたタイムアウトは、予算を引き上げません。
  • CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS: この環境変数をミリ秒単位で設定すると、予算を明示的に上書きできます。設定した値は、独自の timeout を持たない各フックのタイムアウトにもなります。
次の例は予算を 5 秒に設定します。
v2.1.268 より前は、CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS は全体の予算だけを引き上げ、独自の timeout を持たないフックは引き続き 1.5 秒後にキャンセルされていました。

Elicitation

MCP サーバーがタスクの途中でユーザー入力を要求したときに実行されます。デフォルトでは、Claude Code はユーザーが応答するための対話的なダイアログを表示します。フックはこのリクエストをインターセプトしてプログラムで応答し、ダイアログを完全にスキップできます。 設定エントリとスクリプトを含む完全なフックについては、スクリプトからフォームリクエストに回答するを参照してください。 matcher フィールドは MCP サーバー名に対して照合されます。

Elicitation の入力

共通の入力フィールドに加えて、Elicitation フックは mcp_server_name、message、およびオプションの mode、url、elicitation_id、requested_schema フィールドを受け取ります。 最も一般的なケースであるフォームモードの elicitation の場合:
ブラウザベースの認証に使用される URL モードの elicitation の場合:

Elicitation の出力

Elicitation フックは、ユーザーの代わりにリクエストに回答したり、辞退またはキャンセルしたり、ダイアログに任せたりできます。回答、辞退、キャンセルを行うには、0 で終了し、action を含む hookSpecificOutput オブジェクトを出力します。サーバーは回答を受け取り、ダイアログは表示されません。この表の各行は、1 つの結果について何を返すか、MCP サーバーが何を受け取るかを示しています。 次の出力は、Elicitation の入力で示したフォームモードのリクエストに回答します。content のキーは、そのリクエストの requested_schema のプロパティ名です。
次の出力はリクエストを辞退します。
ダイアログでは、Decline を選択すると decline が送信され、Esc を押すと cancel が送信されます。サーバーに見せたいほうを返してください。 URL モードのリクエストでは、accept を返すフックはダイアログをスキップするため、URL は開かれません。 Claude Code は、どの action を返した場合でも、Elicitation フックの JSON 出力の reason、systemMessage、continue を破棄します。

elicitation を辞退するその他の方法

フックは次の方法でも辞退できます。サーバーは "action": "decline" の場合と同じ decline を受け取ります。
  • 終了コード 2 で終了する: Claude Code は同じフックが出力した hookSpecificOutput を無視します
  • トップレベルの "decision": "block" を出力する: ブロックは同じ出力内の action を上書きします
複数のフックが同じリクエストに一致した場合、いずれかのフックによる辞退は、ほかのフックの accept や cancel を上書きします。 次のスクリプトは、URL モードのリクエストを辞退し、フォームのリクエストはダイアログに任せます。
Claude Code は stderr も reason も表示しないため、ユーザーもサーバーもフックが辞退した理由を知ることはできません。 Claude Code は、v2.1.105 から v2.1.284 で修正されるまで、Elicitation フックと ElicitationResult フックのトップレベルの decision を無視していました。

スクリプトからフォームリクエストに回答する

この例では、繰り返し尋ねられる 1 つの質問にユーザーの代わりに回答します。issue-tracker という名前の MCP サーバーがフォームでプロジェクトキーを尋ね、フックが DOCS を入力します。スクリプトは、project_key がフォームの唯一のフィールドである場合に受け入れます。それ以外のリクエストでは何も出力しないため、ダイアログが表示されます。
設定ファイルで、サーバー名を matcher としてこのイベントのコマンドフックを登録します。
このスクリプトをプロジェクト内の .claude/hooks/answer-project-key.sh に保存し、chmod +x で実行可能にします。
フックが動作することを確認するには、claude --debug で Claude Code を起動し、サーバーがプロジェクトキーを尋ねるようなタスクを Claude に与えます。ダイアログは表示されず、デバッグログに Elicitation resolved by hook: {"action":"accept","content":{"project_key":"DOCS"}} で終わる行が記録されます。

ElicitationResult

ユーザーが MCP の elicitation に応答した後に実行されます。フックは、応答が MCP サーバーに送り返される前に、それを監視、変更、またはブロックできます。 Elicitation フックがリクエストに回答した場合、Claude Code は ElicitationResult フックを実行せずにその回答をサーバーに送信します。 matcher フィールドは MCP サーバー名に対して照合されます。

ElicitationResult の入力

共通の入力フィールドに加えて、ElicitationResult フックは mcp_server_name、action、およびオプションの mode、elicitation_id、content フィールドを受け取ります。

ElicitationResult の出力

ElicitationResult フックは、ユーザーの応答をそのまま通したり、その値を変更したり、ブロックしたりできます。応答を変更またはブロックするには、0 で終了し、action を含む hookSpecificOutput オブジェクトを出力します。この表の各行は、1 つの結果について何を返すか、MCP サーバーが何を受け取るかを示しています。 次の出力は ElicitationResult の入力で示した応答を変更し、ユーザーが alice と送信したところをサーバーが alice@example.com として受け取るようにします。
指定した content はユーザーの content オブジェクト全体を置き換えるため、変更しないフィールドも含めてください。Claude Code は action のない hookSpecificOutput を無視するため、action も一緒に返してください。 ElicitationResult フックはユーザーが辞退またはキャンセルした場合にも実行され、フックの action がユーザーのものを置き換えます。accept を返す前に入力の action が accept であることを確認してください。そうしないと、フックが辞退されたリクエストを受け入れられたものに変えてしまいます。次のスクリプトは、ユーザーが受け入れた場合に同じ変更を行い、ほかのフィールドは保持し、それ以外の場合は何も出力しません。
次の出力は応答をブロックします。
終了コード 2 とトップレベルの "decision": "block" でも応答をブロックできます。フックがこれらを組み合わせた場合にどれが有効になるか、ユーザーに何が表示されるか、どのバージョンが decision を無視していたかについては、elicitation を辞退するその他の方法で説明しています。 Claude Code は、どの action を返した場合でも、ElicitationResult フックの JSON 出力の reason、systemMessage、continue を破棄します。

プロンプト ベースのフック

コマンド、HTTP、MCP ツール フックに加えて、Claude Code はプロンプト ベースのフック(type: "prompt")をサポートしており、LLM を使用してアクションを許可またはブロックするかどうかを評価し、エージェント フック(type: "agent")はツール アクセスを持つ agentic ベリファイアーを生成します。すべてのイベントがすべてのフック タイプをサポートしているわけではありません。 5 つのフック タイプ(command、http、mcp_tool、prompt、agent)すべてをサポートするイベント:
  • PermissionDenied
  • PostToolBatch
  • PostToolUse
  • PostToolUseFailure
  • PreToolUse
  • Stop
  • SubagentStop
  • TaskCompleted
  • TaskCreated
  • TeammateIdle
  • UserPromptExpansion
  • UserPromptSubmit
PermissionRequest は command、http、mcp_tool、prompt フックをサポートしますが、agent フックはサポートしません。このイベントにエージェント フックを設定した場合、Claude Code はそれをスキップし、権限フローは変更されずに進行します。フックから許可または拒否するには、コマンド フックまたは HTTP フックから決定オブジェクトを返します。 command、http、mcp_tool フックをサポートするが、prompt または agent をサポートしないイベント:
  • ConfigChange
  • CwdChanged
  • DirectoryAdded
  • Elicitation
  • ElicitationResult
  • FileChanged
  • InstructionsLoaded
  • MessageDisplay
  • Notification
  • PostCompact
  • PostModelSwitch
  • PreCompact
  • PreModelSwitch
  • SessionEnd
  • StopFailure
  • SubagentStart
  • WorktreeCreate
  • WorktreeRemove
SessionStart と Setup は command と mcp_tool フックをサポートしており、それらの mcp_tool フックがいつ実行されるかについては MCP ツール フックのフィールドで説明しています。これらは http、prompt、agent フックをサポートしていません。

プロンプト ベースのフックの仕組み

プロンプト ベースのフックは Bash コマンドを実行する代わりに:
  1. フック入力とプロンプトを Claude モデル(デフォルトでは Claude Code がバックグラウンド機能に使用するモデル)に送信
  2. LLM は決定を含む構造化 JSON で応答
  3. Claude Code は決定を自動的に処理

プロンプト フック設定

type を "prompt" に設定し、command の代わりに prompt 文字列を提供します。$ARGUMENTS プレースホルダーを使用して、フックの JSON 入力データをプロンプト テキストに注入します。 プロンプト フックまたはエージェント フックでは、prompt を「.env ファイルを読み取る Bash コマンドをすべてブロックする」のようにブロックまたは許可する対象に関するルールとして記述することも、「すべてのユニット テストが成功する」のように満たされるべき条件として記述することもできます。 この Stop フックは、Claude が終了する前にすべてのタスクが完了しているかどうかを評価するよう LLM に求めます:

レスポンス スキーマ

LLM は以下を含む JSON で応答する必要があります:
ok: false で何が起こるかはイベントによって異なります:
  • Stop と SubagentStop:理由は Claude の次の指示としてフィードバックされ、ターンが続行されます。ただし、応答で impossible: true も設定されている場合は、Claude Code が停止を許可し、ターンが終了します
  • PreToolUse:ツール呼び出しが拒否されます。デフォルトではターンが終了し、拒否理由は警告行としてチャットに表示されます。代わりに理由をツール エラーとして Claude に返し、Claude が調整して続行できるようにするには、continueOnBlock: true を設定します。これはコマンド フックの permissionDecision: "deny" と同等です
  • PostToolUse:デフォルトではターンが終了し、理由は警告行としてチャットに表示されます。continueOnBlock: true を設定して、理由を Claude にフィードバックし、ターンを続行する代わりに使用します
  • PostToolBatch、UserPromptSubmit、UserPromptExpansion:ターンが終了し、理由は警告行として表示されます。これらのイベントは continue に関係なく decision: "block" でターンを終了します
  • PostToolUseFailure、TaskCreated:理由は continueOnBlock に関係なくツール エラーとして Claude に返され、ターンが続行されます
  • TaskCompleted:ターン中にタスクが完了としてマークされたために発火した場合、理由は continueOnBlock に関係なくツール エラーとして Claude に返され、ターンが続行されます。チームメイトが停止したために発火した場合は、TeammateIdle と同様に動作し、デフォルトでチームメイトを停止します
  • TeammateIdle:デフォルトではチームメイトが停止し、理由は警告行として表示されます。continueOnBlock: true を設定して、理由をチームメイトにフィードバックし、代わりに作業を続行させます
  • PermissionRequest:ok: false は効果がありません。フックから承認を拒否するには、コマンド フックを使用して hookSpecificOutput.decision.behavior: "deny" を返します
  • PermissionDenied:ok: false は効果がありません。拒否は既に発生しているためです。このイベントが読み取る唯一の出力は hookSpecificOutput.retry です。プロンプト フックとエージェント フックはこれを設定できません。これらはこのイベントで実行されますが、その出力は破棄されます。retry を返すには、コマンド フックを使用してください
任意のイベントでより細かい制御が必要な場合は、決定制御で説明されているイベント ごとのフィールドを使用して、コマンド フックを使用してください。

停止する前に複数の条件をチェック

この Stop フックは詳細なプロンプトを使用して、Claude が停止することを許可する前に 3 つの条件をチェックします。SubagentStop フックは同じ形式を使用して、サブエージェントが停止すべきかどうかを評価します。条件がまだ満たされていないためにモデルが "ok": false を返した場合、Claude は提供された理由を次の指示として受け取り、作業を続行します:

エージェント ベースのフック

エージェント フックは実験的です。動作と設定は将来のリリースで変更される可能性があります。本番ワークフローの場合は、コマンド フックを優先してください。
エージェント ベースのフック(type: "agent")はプロンプト ベースのフックのようですが、マルチターン ツール アクセスを備えています。単一の LLM 呼び出しの代わりに、エージェント フックはサブエージェントを生成し、ファイルを読み取り、コードを検索し、コードベースを検査して条件を検証できます。エージェント フックは、PermissionRequest を除き、プロンプト ベースのフックと同じイベントをサポートしています。

エージェント フックの仕組み

エージェント フックが発火するとき:
  1. Claude Code はプロンプトとフックの JSON 入力を持つサブエージェントを生成します
  2. サブエージェントは Read、Grep、Glob などのツールを使用して調査できます
  3. 最大 50 ターン後、サブエージェントは構造化 { "ok": true/false } 決定を返します
  4. Claude Code は ok が true の場合にアクションを許可します。ok が false の場合、Claude Code はレスポンス スキーマに記載されているとおり、そのイベントで continueOnBlock: true を指定したプロンプト フックと同じ方法でブロックを処理します
エージェント フックは、フック入力データのみを評価するのではなく、実際のファイルを検査したりテスト出力を検査したりする必要がある場合に便利です。

エージェント フック設定

type を "agent" に設定し、prompt 文字列を提供します。フック入力 JSON のプレースホルダーとして $ARGUMENTS を使用します。設定フィールドはプロンプト フックと同じですが、エージェント フックはデフォルト タイムアウトが 60 秒と長く、continueOnBlock フィールドがありません。 レスポンス スキーマは、許可する場合は { "ok": true }、ブロックする場合は { "ok": false, "reason": "..." } です。ok: false の場合、Claude Code はエージェント フックを、同じイベントにおけるcontinueOnBlock: true を指定したプロンプト フックと同じ方法で処理します。エージェント フックには continueOnBlock フィールドがなく、プロンプト フックの impossible フィールドもサポートしていません。 この Stop フックは、Claude が終了することを許可する前にすべてのユニット テストが合格することを検証します:

バックグラウンドでフックを実行

デフォルトでは、フックは完了するまで Claude の実行をブロックします。デプロイ、テスト スイート、外部 API 呼び出しなどの長時間実行タスクの場合、"async": true を設定してフックをバックグラウンドで実行し、Claude が作業を続行できるようにします。非同期フックはブロックまたは Claude の動作を制御できません。decision、permissionDecision、continue などのレスポンス フィールドは、制御しようとしたアクションがすでに完了しているため、効果がありません。

非同期フックを設定

コマンド フックの設定に "async": true を追加して、Claude をブロックせずにバックグラウンドで実行します。このフィールドは type: "command" フックでのみ利用可能です。 このフックは、すべての Write ツール呼び出しの後にテスト スクリプトを実行します。run-tests.sh の実行中も、Claude はすぐに作業を続行します。スクリプトが完了すると、その出力は次の会話ターンで配信されます。
非同期フックがバックグラウンドで実行され始めると、Claude Code はそのフックに timeout を適用しません。asyncRewake で実行するフックには、Claude Code は引き続き timeout を適用します。 Claude Code が非同期フックの結果を配信するのは、セッションの実行中のみです。
  • -p フラグを使用した非対話モードでは、Claude Code は終了処理時にまだ実行中の非同期フックをすべて強制終了し、結果 cancelled で確定します
  • フックの処理を claude -p セッションより長く存続させる必要がある場合は、フックから完全にデタッチされたプロセスを起動します

非同期フックの実行方法

非同期フックが発火すると、Claude Code はフック プロセスを開始し、完了を待たずにすぐに続行します。フックは同期フックと同じ JSON 入力を stdin 経由で受け取ります。 バックグラウンド プロセスが終了した後、Claude Code はフックの JSON レスポンスに含まれる additionalContext フィールドと systemMessage フィールドを次の会話ターンで Claude に配信します。同期フックの systemMessage とは異なり、どちらのフィールドもユーザーには表示されません。 JSON レスポンスは、stdout に単独で出力するか、それ自体だけの 1 行として出力します。
  • stdout に単独で出力: レスポンスが stdout 上の唯一のテキストである場合、整形された jq 出力のように複数行にまたがってもかまいません。複数行にまたがるには Claude Code v2.1.295 以降が必要です。
  • それ自体だけの 1 行として出力: jq -c を使用するなどしてレスポンスが単独で 1 行に収まる場合、非同期フックは stdout に他のテキストを出力できます。
Claude Code はその JSON レスポンスを同期フックと同じ出力スキーマに対して検証し、systemMessage が文字列でない場合など、値の型が間違っているフィールドは配信せずにドロップします。--debug で実行すると、ドロップされた各フィールドの名前を示す警告が表示されます。 非同期フック完了通知はデフォルトで抑制されます。これらを表示するには、Ctrl+O で詳細モードを有効にするか、--verbose で Claude Code を開始します。

ファイル変更後にテストを実行

このフックは Claude がファイルを書き込むたびにバックグラウンドでテスト スイートを開始し、テストが完了したら結果を Claude に報告します。このスクリプトをプロジェクトの .claude/hooks/run-tests-async.sh に保存し、chmod +x で実行可能にします。
次に、プロジェクト ルートの .claude/settings.json にこの設定を追加します。async: true フラグにより、Claude はテストの実行中に作業を続行できます。

制限事項

非同期フックは同期フックと比べていくつかの制約があります。
  • フック出力は次の会話ターンで配信されます。セッションがアイドル状態の場合、レスポンスは次のユーザー操作まで待機します。例外: asyncRewake フックが終了コード 2 で終了すると、セッションがアイドル状態でも Claude を直ちに起動します。
  • 各実行は個別のバックグラウンド プロセスを作成します。

セキュリティに関する考慮事項

免責事項

コマンド フックはユーザー アカウントの完全な権限でシェル コマンドを実行します。ユーザー アカウントがアクセスできるファイルを変更、削除、またはアクセスできます。フック コマンドを設定に追加する前に、すべてのフック コマンドを確認してテストしてください。

ワークスペースの信頼

Claude Code は、設定ファイルのフックを実行する前にワークスペースの信頼を確認します。何が信頼済みとみなされるかは、セッションの種類によって異なります。
  • インタラクティブ セッション: ユーザーがそのフォルダー、またはそのフォルダーにまで信頼が及ぶ親ディレクトリについてワークスペースの信頼ダイアログを承認するまで、Claude Code はユーザー自身の ~/.claude/settings.json を含むすべての設定ファイルのフックを保留します
  • -p または SDK セッション: Claude Code はダイアログを表示せず、フォルダーを信頼済みとして扱います。そのため、リポジトリの .claude/settings.json にコミットされたフックは、一度も信頼したことのないフォルダーでも実行されます
自分が作成していないリポジトリに対して claude -p をスクリプトで実行する前に、そのリポジトリの .claude/ 設定ファイルを確認するか、--bare で開始するか、--settings '{"disableAllHooks": true}' を使用してその実行ではフックをオフにしてください。プロジェクト サブエージェントのフロントマター フックには、設定ファイルのフックよりも厳しいルールが適用されます。フォルダーを信頼する前に実行されるものでは、リポジトリのコンテンツの種類ごとにセッションの種類別の動作を示しています。

セキュリティ ベストプラクティス

フックを書くときは、これらのプラクティスに留意してください。
  • 入力を検証およびサニタイズ: 入力データを盲目的に信頼しないでください
  • 常にシェル変数を引用: $VAR ではなく "$VAR" を使用
  • パス トラバーサルをブロック: ファイル パスで .. をチェック
  • 絶対パスを使用: スクリプトの完全なパスを指定します。exec 形式では、${CLAUDE_PROJECT_DIR} を使用し、パスは引用符で囲む必要がありません。シェル形式では、ダブル クォートで囲みます
  • 機密ファイルをスキップ: .env、.git/、キーなどを避ける

Windows PowerShell ツール

Windows では、コマンド フックで "shell": "powershell" を設定することで、個別のフックを PowerShell で実行できます。Claude Code は pwsh.exe(PowerShell 7 以降の実行可能ファイル)を自動検出し、Windows PowerShell 5.1 の powershell.exe にフォールバックします。
PowerShell シェル形式のコマンドからプロジェクト ルートを参照するには、${CLAUDE_PROJECT_DIR} または $env:CLAUDE_PROJECT_DIR を記述します。Claude Code は settings.json、プラグイン、またはスキルで定義されているかどうかに関係なく、PowerShell シェル形式のコマンド内の ${CLAUDE_PROJECT_DIR}、${CLAUDE_PLUGIN_ROOT}、および ${CLAUDE_PLUGIN_DATA} プレースホルダーを PowerShell の ${env:NAME} 形式に書き換えます。PowerShell は解析後にエクスポートされた環境から値を解決するため、プレースホルダーはダブルクォート文字列内では機能しますが、PowerShell が変数を展開しないシングルクォート文字列内では機能しません。 PowerShell フックで裸の $CLAUDE_PROJECT_DIR スペルを記述しないでください。PowerShell はそれを未定義のローカル変数として解析し、$null に解決します。これにより、スクリプト パスがプロジェクト ルート プレフィックスなしで残されます。Claude Code はその形式を書き換えません。代わりに、デバッグ ログ に警告を記録します。 以下の例は、$env: 形式でプロジェクト スクリプトを実行する settings.json フックを示しています。

フックをデバッグ

フック実行の詳細はデバッグ ログ ファイルに書き込まれます。claude --debug-file <path> で既知の場所にログを書き込むか、claude --debug を実行してログを ~/.claude/debug/<session-id>.txt で読み取ります。--debug フラグはターミナルに出力しません。 たとえば、Write に対する PostToolUse フックで、コマンドが hook-ran を出力する場合、次のようなエントリが生成されます。
遅いフックを見つけるには、ログで所要時間で終わる Hooks: 行を検索します。Claude Code v2.1.296 以降では、ツール イベント、UserPromptSubmit、SessionStart、Stop、およびその他のいくつかのイベントに対する各コマンド フックは、何を出力したかにかかわらず、終了時にこの行を 1 つ残します。この行には、イベント名とフックがマッチしたツール名またはその他の値をコロンでつないだもの、続いて角括弧で囲まれたフックのコマンド、フックの提供元のプラグイン(ある場合)、実行の終了状態、および所要時間が示されます。例: Hooks: PostToolUse:Write [.claude/hooks/log-write.sh] finished with status 0 (31ms)。実行は timed out after <N>ms、cancelled、moved to the background、または failed to start で終了する場合もあります。Notification、SessionEnd、PreCompact などの一部のイベントでは、コマンド フックは代わりに所要時間のない completed with status 行を残します。 より詳細なフック マッチング詳細については、CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose を設定して、フック matcher 数とクエリ マッチングなどの追加ログ行を確認します。 フックが発火しない、Stop フックが実行をブロックし続ける、または設定エラーなどの一般的な問題のトラブルシューティングについては、ガイドの制限事項とトラブルシューティングを参照してください。/context、/doctor、および設定の優先順位をカバーするより広範な診断チュートリアルについては、設定をデバッグを参照してください。