フックは、Claude Codeのライフサイクルの特定のタイミングで実行される、ユーザー定義のシェルコマンドです。Claudeが実行するかどうかをLLMの判断に委ねるのではなく、「ある操作を必ず行う」ことを決定論的に保証できます。プロジェクトのルールを強制したり、繰り返し作業を自動化したり、既存のツールとClaude Codeを連携させたりするのに使います。この記事では、フックの設定方法・実例・入出力の仕組み・マッチャーによる絞り込みを、公式ガイドに基づいて解説します。
フックとは
フックは、Claude Codeの動作を決定論的に制御する仕組みです。Claudeが「そうしよう」と選ぶかどうかに頼るのではなく、決めたタイミングで特定の処理が確実に起きるようにします。次のような用途に向いています。
- プロジェクトルールの強制 - 保護ファイルの編集をブロックする、危険なコマンドを止めるなど
- 繰り返し作業の自動化 - 編集後のフォーマット、変更のログ記録など
- 既存ツールとの連携 - 通知の送信や、外部サービスへのイベント送信など
決定論的なルールではなく判断が必要な場面では、Claudeモデルに条件を評価させる「プロンプトベースのフック」や「エージェントベースのフック」も使えます。フックはスキル・サブエージェント・プラグインと並ぶ、Claude Codeの拡張手段のひとつです。
最初のフックを設定する
フックを作るには、設定ファイルにhooksブロックを追加します。ここでは、Claudeが入力を待っているときにデスクトップ通知を出すフックを例に、3ステップで設定します。
- 設定にフックを追加する -
~/.claude/settings.jsonを開き、Notificationフックを追加します。 - 設定を確認する -
/hooksと入力するとフックブラウザが開きます。Notificationを選び、追加したフックが一覧に出ることを確認します。 - フックを試す -
EscでCLIに戻り、権限が必要な操作をClaudeに依頼して、ターミナルから離れます。デスクトップ通知が届けば成功です。
次はmacOS向けのNotificationフックの例です(LinuxやWindowsではそれぞれnotify-sendやPowerShellのコマンドに置き換えます)。
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
すでにhooksキーがある場合は、既存のイベントキーの兄弟としてNotificationを追加します(オブジェクト全体を置き換えないこと)。各イベント名は、ひとつのhooksオブジェクトの中のキーになります。フックはCLIで内容を説明すればClaudeに書いてもらうこともできます。
/hooksメニューは読み取り専用
フックの追加・変更・削除は、設定JSONを直接編集するか、Claudeに変更を依頼して行います。/hooksメニューは設定内容の閲覧のためのものです。
自動化できること
フックは、Claude Codeのライフサイクルの要所でコードを実行できます。編集後のファイルフォーマット、実行前のコマンドのブロック、入力待ちの通知、セッション開始時のコンテキスト注入などが可能です。代表的な例を紹介します。
編集後の自動フォーマット
PostToolUseをEdit|Writeマッチャーで使い、Claudeが編集したファイルにPrettierを自動適用します
保護ファイルの編集をブロック
PreToolUseでスクリプトを呼び、.envや.git/などへの編集を終了コード2で拒否します
圧縮後のコンテキスト再注入
SessionStartをcompactマッチャーで使い、圧縮で失われがちな規約を再度注入します
たとえば編集後の自動フォーマットは、PostToolUseイベントにEdit|Writeマッチャーを付け、編集されたファイルパスをjqで取り出してPrettierに渡します。プロジェクト直下の.claude/settings.jsonに追加します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
このほか、設定変更を監査ログに記録するConfigChange、権限プロンプトを自動承認するPermissionRequestなど、多くのイベントが用意されています。各例は、設定ファイルに貼り付けてすぐ使える形になっています。
フックの仕組み
フックのイベントは、Claude Codeの特定のライフサイクル時点で発火します。イベントが発火すると、マッチしたフックは並行して実行され、同一のフックコマンドは自動的に重複排除されます。主なイベントには次のものがあります。
SessionStart/SessionEnd- セッションの開始・再開時、終了時UserPromptSubmit- プロンプト送信時(Claudeが処理する前)PreToolUse/PostToolUse- ツール実行の前(ブロック可能)・成功後Notification- Claude Codeが通知を送るときStop/SubagentStop- Claudeやサブエージェントが応答を終えたときPreCompact/PostCompact- コンテキスト圧縮の前後
各フックには実行方式を決めるtypeがあります。多くは"type": "command"(シェルコマンド)ですが、URLへPOSTするhttp、単発のLLM評価を行うprompt、ツールを使って多段検証するagentなども選べます。
入力と出力
フックはstdin・stdout・stderr・終了コードでClaude Codeとやり取りします。イベントが発火すると、イベント固有のデータがJSONとしてstdinに渡されます。たとえばPreToolUseフックがBashコマンドを受け取ると、次のようなJSONが渡されます。
{
"session_id": "abc123",
"cwd": "/Users/sarah/myproject",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
}
}
スクリプトは終了コードで次の動作を指示します。
- 終了コード0 - 異議なし。操作は通常どおり進む(
PreToolUseでは承認ではなく、通常の権限フローが適用される) - 終了コード2 - 操作をブロック。stderrに書いた理由がClaudeにフィードバックされ、Claudeは方針を調整できる
- それ以外の終了コード - 操作は進むが、トランスクリプトにフックエラーの通知が表示される
より細かく制御したいときは、終了コード0にしてstdoutにJSONオブジェクトを出力します。たとえばPreToolUseでpermissionDecisionを"deny"にすると、ツール呼び出しをキャンセルし、理由をClaudeに伝えられます。ただし"allow"を返しても、設定側のdenyルールを上書きすることはできません。フックは制限を強められますが、権限ルール以上に緩めることはできません。
マッチャーで絞り込む
マッチャーを付けないと、フックはそのイベントが起きるたびに発火します。マッチャーを使うと発火条件を絞れます。たとえばフォーマッタを「ファイル編集後だけ」動かしたいなら、PostToolUseにEdit|Writeマッチャーを付けます。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "prettier --write ..." }
]
}
]
}
}
マッチャーが何を対象にするかはイベントごとに異なります。
PreToolUse/PostToolUseなど - ツール名(例:Bash、Edit|Write、mcp__.*)SessionStart- セッションの開始理由(startup/resume/clear/compact)Notification- 通知の種類(permission_prompt、idle_promptなど)PreCompact/PostCompact- 圧縮の契機(manual/auto)
MCPツールはmcp__<server>__<tool>という命名になるため、mcp__github__.*のような正規表現マッチャーで、特定サーバーのツールをまとめて対象にできます。マッチャーは大文字・小文字を区別する点に注意してください。UserPromptSubmitやStopなど一部のイベントはマッチャーに対応せず、常に発火します。
設定場所とベストプラクティス
フックをどこに書くかで、そのフックの適用範囲が決まります。
ユーザー単位・プロジェクト単位
~/.claude/settings.json- 自分の全プロジェクトに適用(共有はされない).claude/settings.json- 単一プロジェクト。リポジトリにコミットして共有できる.claude/settings.local.json- 単一プロジェクト。共有しない(gitignore対象)
組織・拡張単位
- 管理ポリシー設定 - 組織全体に適用(管理者が制御)
- プラグインの
hooks/hooks.json- プラグイン有効時に適用 - スキル/エージェントのフロントマター - その要素がアクティブな間だけ適用
設定を無効化したいときは、設定ファイルに"disableAllHooks": trueを指定します。設定ファイルを直接編集すると、通常はファイルウォッチャーが変更を自動で拾います。PreToolUseフックは権限モードのチェックより前に発火するため、"deny"を返すフックはbypassPermissionsモードでもツールをブロックできます。逆に"allow"を返しても設定側のdenyルールは上書きできません。
権限プロンプトの自動承認は、マッチャーをできるだけ狭くしてください。マッチャーを空にしたり.*にしたりすると、ファイル書き込みやシェルコマンドを含むすべてのプロンプトを自動承認してしまいます。フックが発火しないときは/hooksでイベントとマッチャーを確認し、JSONの妥当性(末尾カンマやコメントの混入がないか)もチェックします。
フックはstdout・stderr・終了コードのみでやり取りし、スラッシュコマンドやツール呼び出しを直接トリガーすることはできません。決定論的なルールにはコマンドフックを、判断が必要な場面にはプロンプトフックやエージェントフックを、と使い分けるのがコツです。まずはよく繰り返す1つの作業を選び、小さなフックから始めて反復的に改善していくとよいでしょう。