Claude Codeのhooks早見表
Claude Codeのhookのイベントは33個で、16個はexit 2で止められます。イベントとexit codeを表で引けます。
- hooksは、Claude Codeの決まった時点で自動で動くコマンド、HTTPエンドポイント、MCPツール、プロンプト、サブエージェントです。公式ドキュメントにはイベントが33個あります。
- exit 0は成功、exit 2は止められるイベントでは処理を止めます。それ以外の終了コードで正しいJSONも出さない場合は止めないエラーで、onFailureをblockにしたときだけ止まります。
- ツールの呼び出しを実行の前に止めるなら、PreToolUseでexit 2にするか、permissionDecisionでdenyを返します。
hooks は、Claude Code の決まった時点で自動で動く、利用者が書いたシェルのコマンド、HTTP のエンドポイント、MCP のツール、LLM のプロンプト、サブエージェントです。ターミナル、IDE の拡張、デスクトップアプリ、クラウドのセッションのどこでも、同じイベントで動きます。このページは早見表です。全イベントの表、exit code と JSON の表、最小の例、hook ごとに動かして確かめた記事への案内を載せています。どれも2026年10月24日に公式のリファレンスと照らし合わせ、Claude Code 2.1.310 で確かめました。
全イベントの一覧
公式ドキュメントに載っているイベントは33個です。「exit 2」の列は、そのイベントの hook が終了コード 2 で終わったときに起きること、「matcher」の列は matcher が何と比べられるかです。「なし」は matcher に対応せず、毎回動くイベントです。
| イベント | 動くとき | exit 2 | matcher |
|---|---|---|---|
SessionStart | セッションの開始・再開 | 人に stderr を見せるだけ | 始まり方(startup、resume、clear、compact、fork) |
Setup | --init-only、または -p 付きの --init / --maintenance のときだけ | 無視される | init、maintenance |
InstructionsLoaded | CLAUDE.md や .claude/rules/*.md が読み込まれたとき | 無視される | 読み込みの理由 |
UserPromptSubmit | プロンプトを送ったとき、Claude が処理する前 | プロンプトを止める | なし |
UserPromptExpansion | 打ったコマンドがプロンプトに展開されるとき | 展開を止める | コマンド名 |
MessageDisplay | アシスタントのメッセージが画面に流れるとき | 元の文が表示される | なし |
PreToolUse | ツールの呼び出しを組み立てたあと、実行の前 | 呼び出しを止める | ツール名 |
PermissionRequest | 権限の確認を出す直前 | 効かない。decision で拒否する | ツール名 |
PostToolUse | ツールが成功した直後 | Claude に stderr を見せる。ツールはもう動いている | ツール名 |
PostToolUseFailure | 実行を始めたツールが失敗したとき | Claude に stderr を見せる | ツール名 |
PostToolBatch | まとめて呼んだツールがすべて終わったとき | 次のモデル呼び出しの前でループを止める | なし |
PermissionDenied | auto mode が呼び出しを拒否したとき | 無視される | ツール名 |
Notification | 通知を送るとき | 無視される | 通知の種類 |
SubagentStart | サブエージェントを起動・再開したとき | 人に stderr を見せるだけ | エージェントの種類 |
SubagentStop | サブエージェントが応答を終えたとき | サブエージェントを止めずに続けさせる | エージェントの種類 |
TaskCreated | TaskCreate でタスクを作るとき | 作成を取り消す | なし |
TaskCompleted | タスクを完了にするとき | 完了にさせない | なし |
Stop | メインのエージェントが応答を終えたとき | Claude を止めずに続けさせる | なし |
StopFailure | API のエラーでターンが終わったとき | terminalSequence 以外は無視される | エラーの種類 |
TeammateIdle | エージェントチームのメンバーが待機に入る直前 | 待機させずに続けさせる | なし |
ConfigChange | セッション中に設定ファイルが変わったとき | 変更を反映させない(policy_settings を除く) | 設定の出どころ |
CwdChanged | シェルのコマンドで作業ディレクトリが変わったとき | 人に stderr を見せるだけ | なし |
DirectoryAdded | /add-dir でディレクトリを足したとき | stderr はデバッグログへ | 足し方 |
FileChanged | 監視しているファイルが変わったとき | 人に stderr を見せるだけ | 監視するファイル名 |
WorktreeCreate | worktree を作るとき | 0 以外の終了コードで作成が失敗する | なし |
WorktreeRemove | hook が作った worktree を消すとき | 0 以外の終了コードで削除が失敗する | なし |
PreCompact | 要約(compact)の前 | 要約を止める | manual、auto |
PostCompact | 要約の後 | 人に stderr を見せるだけ | manual、auto |
PreModelSwitch | モデルの切り替えを反映する前 | 切り替えを止める | 切り替え先のモデル名 |
PostModelSwitch | モデルが切り替わった後 | 人に stderr を見せるだけ | 切り替え先のモデル名 |
SessionEnd | セッションが終わるとき | 人に stderr を見せるだけ | 終わった理由 |
Elicitation | MCP サーバーが入力を求めたとき | 求めを断り、画面は出ない | MCP サーバー名 |
ElicitationResult | MCP の入力に人が答えた後 | 答えを止める | MCP サーバー名 |
出典:https://code.claude.com/docs/en/hooks 、2026-10-24確認
exit 2 で止められるのは、PreToolUse、UserPromptSubmit、UserPromptExpansion、Stop、SubagentStop、TeammateIdle、TaskCreated、TaskCompleted、ConfigChange、PostToolBatch、PreCompact、PreModelSwitch、Elicitation、ElicitationResult、WorktreeCreate、WorktreeRemove の16個です。WorktreeCreate と WorktreeRemove は 0 以外の終了コードで失敗し、WorktreeRemove はその後もディレクトリが残っているときだけ失敗します。
exit code と JSON の早見表
| hook の終わり方 | 結果 |
|---|---|
exit 0 | 成功。stdout の JSON があれば反映される。UserPromptSubmit、UserPromptExpansion、SessionStart、PostModelSwitch では、普通の文も Claude の文脈に足される |
exit 2 | 止められるイベントでは、止める種類のエラー。stderr が理由になる。JSON も読まれるが、"allow" でも止まる |
| それ以外(1 を含む) | 普通の文か何も出さない場合は止めないエラーで、処理は進み、hook error の通知が出る。検証を通る JSON を出した場合は、終了コードは無視され JSON の中身で決まる。方針を守らせる hook には exit 2 が勧められている |
| 起動できない、タイムアウト、JSON が読めない | 既定では止めないエラー。ただし PreModelSwitch では、タイムアウトで取り消された hook はモデルの切り替えを止める |
command か HTTP の hook に "onFailure": "block" | 失敗したとき(exit 1 も含む)も、そのイベントで exit 2 と同じことが起きる。exit 2 が効かない PermissionRequest では、権限の要求を拒否する。Claude Code v2.1.295 以降。Stop、SubagentStop、TaskCompleted、TeammateIdle と非同期の hook には効かない |
よく使う JSON のフィールドです。
| フィールド | 使うイベント | 効果 |
|---|---|---|
hookSpecificOutput.permissionDecision | PreToolUse | allow・deny・ask・defer。複数の hook では deny > defer > ask > allow の順に強い。defer は -p の実行でだけ効く |
hookSpecificOutput.permissionDecisionReason | PreToolUse | ask では確認の画面に、deny では Claude に見せる |
hookSpecificOutput.updatedInput | PreToolUse | ツールの入力をまるごと差し替える |
一番外の decision: "block" と reason | PostToolUse、Stop、UserPromptSubmit など | PostToolUse ではツールの結果の横に理由を足し、Stop では Claude を続けさせる |
hookSpecificOutput.additionalContext | いくつかのイベント | Claude の文脈に文を足す |
systemMessage | 多くのイベント(捨てるイベントもある) | 人にメッセージを見せる |
出典:https://code.claude.com/docs/en/hooks 、2026-10-24確認
置き場所と最小の例
| 置き場所 | 範囲 |
|---|---|
~/.claude/settings.json | 自分のすべてのプロジェクト |
.claude/settings.json | 1つのプロジェクト。Git に入れて共有できる |
.claude/settings.local.json | 1つのプロジェクト。自分だけ |
| managed policy settings | 組織全体 |
plugin の hooks/hooks.json | plugin が有効な間 |
| skill やサブエージェントの frontmatter | skill を呼んだあと、またはサブエージェントが動いている間 |
hook の設定は、これらの階層で上書きされず足し合わされます(出典:https://code.claude.com/docs/en/hooks 、2026-10-24確認)。
一番小さい PreToolUse の hook は、1つのコマンドを止めるものです。ダミーのプロジェクトで npm publish を止める例です。
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash",
"hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/no-publish.sh" } ] }
]
}
}
#!/usr/bin/env bash
# .claude/hooks/no-publish.sh (PreToolUse, matcher: Bash)
cmd=$(jq -r '.tool_input.command // ""')
case "$cmd" in
*"npm publish"*) echo "Blocked: publishing is done by a human." >&2; exit 2 ;;
esac
exit 0
2026年10月24日に、ダミーの JSON を流して確かめました。{"tool_name":"Bash","tool_input":{"command":"npm publish"}} では Blocked: publishing is done by a human. と出て exit 2、npm test では exit 0 でした。設定ファイルは jq と claude doctor を通りました。実際のセッションの中で発火するところは見ていません(未実行)。
hooks の記事を読む順番
考え方から入り、例を写し、動かないときの確かめ方を知り、最後に設計を考える順に並べました。
- Claude Code hooks実践:hook が散文のルールより効く理由と、終了コードの意味を実測で確かめた入門
- PreToolUse hookの例集:
rm -rf /や秘密ファイル、強制 push を止める、貼って使える6本 - PostToolUseで整形とテストを自動化:編集のたびに整形とテストを回す hook
- UserPromptSubmitの使い方:文脈を足す hook と、API キーを含むプロンプトを止める hook
- Stop hookで完了を確かめる:テストが通るまで止めない hook と、ループの防ぎ方
- hooksが動かないときの確認:発火しない・止まらない原因を再現して並べたチェックリスト
- AIの「完了しました」を信じない仕組み:完了報告を hook と git の実数で確かめる
- AIエージェントの権限設計:拒否ルールと hook の評価の順番
- permissions設定の早見表:hook と組み合わせる allow・ask・deny の書き方
まとめ
- Claude Code の hook のイベントは33個で、そのうち16個は exit 2 で止められる
- exit 0 は成功、exit 2 は止められるイベントで止める。それ以外の終了コードは、正しい JSON で別の判断を返さない限り処理を通す
"onFailure": "block"(v2.1.295 以降)で、落ちた hook やタイムアウトした hook でも止められる。Stop 系と非同期の hook には効かない- ツールを止めるなら PreToolUse、動いたあとに知らせるなら PostToolUse、終わる前に確かめるなら Stop
- ユーザー、プロジェクト、ローカル、組織、plugin の hook は、上書きされず足し合わされる
よくある質問
- Claude Code の PreToolUse とは?
- Claude がツールの呼び出しを組み立てたあと、実行する前に動く hook です。呼び出しを許可・拒否・確認・保留にでき、exit 2 で止めることもできます。
- フックでコマンドを止めるには?
- matcher を Bash にした PreToolUse の hook を登録し、スクリプトで tool_input.command を調べて、理由を stderr に書いて exit 2 で終わります。Claude には stderr が理由として渡ります。
- exit 2 は何を意味する?
- 止める種類のエラーです。PreToolUse、UserPromptSubmit、Stop のように止められるイベントでは、Claude Code が処理を止めます。PostToolUse のように止められないイベントでは、stderr を見せるだけです。
- exit 1 でツールの呼び出しは止まる?
- それだけでは止まりません。exit 1 で普通の文か何も出さない場合は止めないエラーで、ツールはそのまま動きます。検証を通る JSON を出した場合は JSON の中身で決まり、deny なら止まります。onFailure: block を付けると(v2.1.295 以降)exit 1 も失敗として止まります。公式は、方針を守らせる hook には exit 2 を勧めています。
- フックが動かないときは?
- 設定ファイルの置き場所、JSON の書式、イベント名のつづり、matcher の大文字と小文字、スクリプトの実行権限をよく確かめます。確かめ方はチェックリストの記事にまとめています。