「hooksを書いたのに、動いた形跡がない」。Claude Codeの設定でつまずく話として、これはよく聞きます。

原因の多くは、書き方ではなくイベントの選び方にあります。似た名前のイベントが並んでいて、発火する場所も、止められるかどうかも違う。そこを確かめないまま書くと、効かせたつもりのhooksができ上がります。

この記事は、公式ドキュメントに載っている全30種類のイベントを一覧にして、そこから「やりたいこと」で引ける形に整理します。個別の実装コードは別記事へ送り、一覧と選び方に絞ります。hooksが自動化4層のどこに位置するかは『AIエージェントの自動化は4層|着手する順番と稼働の数え方』で扱いました。

本記事の検証環境:claude-opus-5 / Claude Code v2.1.x / macOS 15 / 2026-07-29検証。

こんなふうに調べていませんか

  • hooksを設定したのに、動いた形跡がない
  • イベント名が似ていて、どれに何を書けばいいのか決められない
  • 危ない操作だけを実行前に止めたいが、入口がいくつもあって選べない

この記事を読み終えたときに手に入るもの

  • 30種類のイベントを、発火タイミングとブロック可否の2軸で選び分けられるようになります
  • やりたいことから、使うイベントを逆引きできるようになります
  • matcherとタイムアウトでつまずく場所を、書く前に避けられるようになります

結論30秒でわかる、この記事の結論

  • hooksは、AIエージェントの動きに割り込む場所をあらかじめ決めておく仕組みです。
  • 選ぶ軸は2つです。いつ発火するかと、実行や継続を止められるかどうか。
  • 30種類を全部は使いません。取り消せない操作に近いところから、順に入れます。
30種類のhooksを、2つの軸で選び分けます名前で覚えず、発火する場所と止め方で引きます30種類のhooksを、2つの軸で選び分けます軸1いつ発火するか起動から終了までの通り道のどこか軸2止められるか拾うだけの場所と、引き返せる場所がある順番戻せない操作から観測用のイベントは、あとから足せる鈴木さん名前で覚えず、発火する場所と止め方で引きます
30種類のhooksを、2つの軸で選び分けます — 名前で覚えず、発火する場所と止め方で引きます

進行役は3人です。若葉さん(Web担当2年目)が用語のそもそもを聞き、高梨課長が自分の手で動かす側の疑問を出し、鈴木さん(本誌監修)が答えます。

01Claude Code hooksの一覧を、AIエージェントを動かす前に見ておくのはなぜですか?

若葉さん
若葉さんの発言

そもそもhooksって、何をするものなんでしょうか。設定ファイルに書く、というところまでは分かったんですが。

鈴木さん
鈴木さんの発言

セッションの中で起きた出来事に反応して、1回だけ動く小さなスクリプトです。火災報知器に近いと思ってください。ふだんは何もしていなくて、煙を感知したときだけ鳴ります。

若葉さん
若葉さんの発言

ずっと動いているわけではないんですね。

鈴木さん
鈴木さんの発言

はい。対応する出来事が起きるまで、1行も動きません。だから「動かない」と感じたときは、書き方より先に、選んだ出来事のほうを疑うと早いです。

先に結論を3つ置きます。

1つめ。hooksは常駐しません。対応するイベントが起きるまで、スクリプトは1行も動きません。時刻を起点に動かしたい処理は、別の層が担当します。

2つめ。本記事では30種類を5つのグループへ整理します。この分類は本記事の独自編集です。 公式ドキュメントはイベントを「セッションに1回」「ターンに1回」「ツール呼び出しごと」という3つの発火頻度でしか説明していません。読み分けやすさのために、こちらで束ね直しています。

3つめ。選ぶ基準は2つです。いつ発火するかと、実行や継続をブロックできるか。この2軸を外すと、発火しないhooksか、止められないhooksができます。

危険なコマンドの遮断そのものは『Claude CodeのPreToolUseで危険コマンドを遮断する4つの判定』にコードつきでまとめています。

この章のまとめ

hooksは、AIエージェントの動きに割り込む場所の名前です。名前で覚えるのではなく、発火する場所と、止められるかどうかで選びます。

02Claude Code hooksの一覧は、AIエージェントの1セッションのどこで発火するんですか?

公式ドキュメントの「Hook lifecycle」表を数えると、hooksイベントは30種類です(2026-07-29に公式ドキュメントを取得して実数を確認)。

一覧に入る前に、1回のセッションがどう進むかを眺めておきます。起動して、指示を受け取り、道具を使い、答え終えて、閉じる。この通り道のどこかで、それぞれのイベントが待っています。並び順が頭に入ると、表は暗記せずに引けるようになります。

1回のセッションの、どこで発火するか起動から終了まで、通り道に沿って並んでいます1回のセッションの、どこで発火するか起動から終了まで、通り道に沿って並んでいます1起動するSetup・SessionStart2指示を受け取るUserPromptSubmit ほか3道具を使うPreToolUse・PostToolUse4答え終えるStop・StopFailure5閉じるSessionEnd鈴木さんサブエージェントは、この通り道の横で並走します
1回のセッションの、どこで発火するか — 起動から終了まで、通り道に沿って並んでいます

以下が全30種類です。グループ名は本記事の独自編集で、公式ドキュメントの分類ではありません。

グループイベント名発火タイミングブロック可否
セッションの生死・環境Setup--init-only起動時、または-p --init/--maintenance時に1回不可(context注入のみ)
セッションの生死・環境SessionStartセッション開始・--resume/--continue/clear後・compaction後・fork後不可(additionalContextinitialUserMessagewatchPathssessionTitlereloadSkillsの5フィールドのみ返せる)
セッションの生死・環境SessionEndセッション終了時不可(後始末専用・1.5秒の共有予算)
セッションの生死・環境PreCompactコンテキスト圧縮の直前可(decision: blockで圧縮を止める)
セッションの生死・環境PostCompactコンテキスト圧縮の完了後不可(ログ用途)
セッションの生死・環境ConfigChange設定ファイル変更を検知した時可(policy_settings以外は変更を止められる)
セッションの生死・環境CwdChanged作業ディレクトリが変わった時(cd実行等)不可(環境連携の副作用専用)
セッションの生死・環境InstructionsLoadedCLAUDE.mdや.claude/rules/*.mdが読み込まれた時不可(ログ用途)
セッションの生死・環境FileChanged監視対象ファイルがディスク上で変化した時不可(副作用専用)
セッションの生死・環境WorktreeCreateworktreeが作成される時実質可(0以外の終了コードで作成が失敗する)
セッションの生死・環境WorktreeRemoveworktreeが削除される時不可(後始末専用)
プロンプト処理・応答終了UserPromptSubmitユーザーがプロンプトを送信し、処理される直前可(decision: blockで送信自体を消せる)
プロンプト処理・応答終了UserPromptExpansionコマンドやスキルがプロンプトへ展開される時可(decision: blockで展開を止める)
プロンプト処理・応答終了StopClaudeが応答を終える時可(decision: blockで終了させず継続させる)
プロンプト処理・応答終了StopFailureAPI側エラーでターンが終わった時不可(ログ・後始末専用)
ツール実行PreToolUseツール呼び出しの直前可(permissionDecision: allow/deny/ask/defer)
ツール実行PermissionRequestツール呼び出しに許可判定が要る時可(decision.behavior: allow/deny)
ツール実行PermissionDenied自動モードの分類器が拒否した直後不可(retry指示のみ・exit codeとstderrは無視)
ツール実行PostToolUseツール呼び出しが成功した後可(decision: blockまたはupdatedToolOutputで結果を書き換え)
ツール実行PostToolUseFailureツール呼び出しが失敗した後可(decision: blockで後続を止める)
ツール実行PostToolBatch並列ツール呼び出しが全解決後、次のモデル呼び出し前可(decision: blockでループを止める)
サブエージェント・タスクSubagentStartサブエージェントが生成された時不可(context注入のみ)
サブエージェント・タスクSubagentStopサブエージェントが完了した時可(decision: blockで完了させず継続させる)
サブエージェント・タスクTaskCreatedタスクが作成された時可(continue: falseまたはexit code 2で作成を巻き戻す)
サブエージェント・タスクTaskCompletedタスクが完了扱いになった時可(continue: falseまたはexit code 2で完了を止める)
サブエージェント・タスクTeammateIdleエージェントチームの一員がアイドルになる直前可(アイドル化・継続そのものも止められる)
通知・MCP連携NotificationClaude Codeが通知を送る時不可(副作用専用)
通知・MCP連携MessageDisplayアシスタントのメッセージ文が画面表示されている間不可(画面表示のみdisplayContentで差し替え可)
通知・MCP連携ElicitationMCPサーバーが入力を要求した時可(action: accept/decline/cancel)
通知・MCP連携ElicitationResultユーザー応答をMCPサーバーへ返す直前可(action: accept/decline/cancelで応答を差し替え)

表は上から読むものではありません。困っている場面を先に決めて、そこから引きます。

0330種類のhooksのうち、AIエージェントの動きを止められるのはどれですか?

30種類のうち、ブロック可否が「可」なのは17種類、「不可」は13種類です(2026-07-29実測)。「不可」の多くは、文脈を足すためか、記録と副作用のための設計です。止まらない場所に止める処理を書いても、そこは通り抜けます。

止められるイベントと、止められないイベント同じ一覧を、ブロック可否の側から見ます止められるイベントと、止められないイベント同じ一覧を、ブロック可否の側から見ます止められる(17種類)実行の直前で引き返せる完了を認めず、もう1周させられる変更を差し戻せる取り消せない操作の手前に置く止められない(13種類)文脈を足すだけ表示だけを差し替える記録して次へ渡す気づける状態をつくるために置く
止められるイベントと、止められないイベント — 同じ一覧を、ブロック可否の側から見ます

「可」と書いてあっても、返し方はイベントごとに違います。decision: block を返すもの、permissionDecision を返すもの、終了コードで表すもの。この違いは、次の章から順に見ていきます。

この章のまとめ

一覧は暗記するものではなく、引くものです。「この場面はどのイベントか」を引き、そのイベントが止められるかを確かめる。この2手で足ります。

04AIエージェントの手を実行の直前で止めるのは、どのhooksですか?

高梨課長
高梨課長の発言

危ない操作だけを実行前に止めたいんですが、それらしい名前が並んでいて選べません。

鈴木さん
鈴木さんの発言

判断軸は2つです。呼び出しの前か後か。そして、誰の判断を経由するか。この2つで並べ直すと、6種類はすんなり分かれます。

高梨課長
高梨課長の発言

まず前と後で割る、ということですね。

鈴木さん
鈴木さんの発言

はい。前が3つ、後ろが3つです。前の3つは、まだ何も起きていないので引き返せます。

ツール実行グループの6種類は、名前が似ていて混同しやすい領域です。ここでは、前側の3つを見ます。

PreToolUse はツール呼び出しの直前に発火し、permissionDecisionallowdenyaskdefer のいずれかで返します。deferclaude -p を呼び出す外部アプリ向けの値で、ツール呼び出しを保留したままセッションを終了させます。対話セッションでは警告が記録され、フックの結果は無視されます(出典: Claude Code公式ドキュメント)。

4つの値のうち、実行を止めるのは deny です。defer だけは用途が特殊で、外部アプリからClaude Codeを呼ぶ構成のときにだけ意味を持ちます。

05許可を求められた場面だけAIエージェントに応答させるhooksはどれですか?

PermissionRequest は、PreToolUseとは別の入口です。許可判定が要る局面で発火し、hookSpecificOutput.decision.behaviorallowdeny を返します。

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "deny",
      "updatedInput": {}
    }
  }
}

PermissionDenied は、自動モードの分類器が拒否した直後に発火します。ここだけ作法が違い、exit codestderr は無視されます。意味を持つのは retry フィールドだけです(出典: Claude Code公式ドキュメント)。

呼び出しの前と後で、入口が分かれます前に3つ、後ろに3つ。役割が重なりません呼び出しの前と後で、入口が分かれます前に3つ、後ろに3つ。役割が重なりません1呼ぶ前に判定するPreToolUse・PermissionRequest2道具が動くhookが入るのは前後だけ3成功か失敗かで分かれるPostToolUse/PostToolUseFailure4並列がすべて終わるPostToolBatch
呼び出しの前と後で、入口が分かれます — 前に3つ、後ろに3つ。役割が重なりません

06生成AIの出力や応答の終わりには、どのhooksが効くんですか?

後ろ側の3種は、成功・失敗・並列で分かれます。

成功したときは PostToolUse、失敗したときは PostToolUseFailure、並列で呼ばれた道具がすべて解決したあと・次のモデル呼び出しの前は PostToolBatch です。

PostToolUseは updatedToolOutput で結果そのものを書き換えられます。機密情報のマスキングや、長い出力の要約に向く場所です。AIエージェントが読む前に手を入れられる、という点が効きます。

PostToolUseFailureとPostToolBatchは、どちらも decision: block で後続を止められます。失敗をなかったことにして進ませない、ループをそこで打ち切る、といった使い方になります。

道具の実行ではなく、応答そのものの終わりを受け止めるのが Stop です。decision: block を返すと、終わらせずにもう1周させられます。API側のエラーでターンが終わったときは StopFailure が発火しますが、こちらは記録と後始末の専用です。同じグループの UserPromptSubmitUserPromptExpansion は入口側にあり、送信そのものや、コマンド・スキルの展開を止められます。

07起動のたびに同じ前提をAI社員へ読ませるのは、どのhooksですか?

高梨課長
高梨課長の発言

うちのルールを毎回いちばん最初に読ませたいんですが、これも実行前に止める話になりますか。

鈴木さん
鈴木さんの発言

いえ、止める話ではなく、渡す話です。SessionStartは読ませる専用で、起動そのものを止める力は持っていません。だから設計の中身は「何を渡すか」だけになります。

セッションの生死・環境グループの11種類は、2つの層に分かれます。開始と終了の層と、セッション中に外側で起きた変化を検知する層です。まず前者から見ます。

SessionStartsource フィールドで発火元を区別できます。startupresumeclearcompactfork の5パターンです。新規起動のときだけ読ませる、圧縮の後だけ読み直す、といった書き分けがここでできます。

返せるフィールドは5つです。

  • additionalContext:文脈を注入する
  • initialUserMessage:最初のプロンプトを設定する
  • watchPaths:監視対象ファイルを指定する
  • sessionTitle:セッション名を設定する
  • reloadSkills:スキルを再読み込みする
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "必読ルールの要約テキスト",
    "reloadSkills": true
  }
}

同じ層には、--init-only 起動時などに1回だけ動く Setup、終了時の SessionEnd、圧縮の直前と完了後の PreCompactPostCompact、worktreeの作成と削除に対応する WorktreeCreateWorktreeRemove が並びます。このうち止められるのはPreCompactで、WorktreeCreateは0以外の終了コードを返すと作成そのものが失敗します。

08セッションの外側で起きた変化は、AIエージェントのhooksでどこまで拾えますか?

もう一方の層が、環境の変化を検知する4種です。

ConfigChange は、設定ファイルの変更を検知したときに発火します。この層で唯一止められるイベントで、decision: block で変更を差し戻せます(policy_settings は対象外です)。

CwdChanged は作業ディレクトリが変わったとき、InstructionsLoaded はCLAUDE.mdや .claude/rules/*.md が読み込まれたとき、FileChanged は監視対象ファイルがディスク上で変化したときに発火します。この3つは止められません。環境の同期や、記録を残すための場所です。

止められないことは、弱点ではありません。「気づける状態をつくる」ための層だと考えると、置き場所が決まります。設定が書き換わったことにも、参照ファイルが差し替わったことにも誰も気づけない、という運用のほうが危ういからです。

この章のまとめ

外側の変化は、原則として拾うだけです。止められるのはConfigChangeだけで、そこも policy_settings は対象から外れています。

09サブエージェントに任せた作業の終わりは、どのhooksで受け止めるんですか?

役割を分けて動かすときに効くのが、サブエージェント・タスクの5種です。

SubagentStart は、サブエージェントが生成されたときに発火します。文脈を注入するだけで、生成そのものは止められません。SubagentStop は完了したときに発火し、decision: block で完了させずに継続させられます。

タスク側は少し違います。TaskCreated はタスクが作成されたとき、TaskCompleted は完了扱いになったときに発火し、どちらも continue: falseexit code 2 で巻き戻せます。TeammateIdle は、エージェントチームの一員がアイドルになる直前です。ここはアイドル化そのものも止められます。

止められるのは、入口か出口かサブエージェント側とタスク側で違います止められるのは、入口か出口かサブエージェント側とタスク側で違いますサブエージェント生成された時は、文脈を足すだけ完了した時は、継続させられる入口では止まらないタスク作成された時に、巻き戻せる完了扱いを、止められる入口も出口も引き返せる
止められるのは、入口か出口か — サブエージェント側とタスク側で違います

役割を分けて動かすときは、この5種のどこで受け止めるかを先に決めておくと、あとから足す処理の置き場所に迷わなくなります。

10通知やMCPからの問いかけは、AIエージェントのどのhooksで受けるんですか?

残る4種が、通知とMCP連携です。Notification は通知を送るときの副作用専用、MessageDisplay は画面表示中に displayContent で表示だけを差し替えられます。Elicitation はMCPサーバーが入力を要求したとき、ElicitationResult はユーザー応答をMCPサーバーへ返す直前に発火し、どちらも actionacceptdeclinecancel を返します。

MCP連携の2種は、外部サーバーからの問いかけに自動で答えさせられる、という点で性格が違います。何をこちらの確認なしに受け入れるかは、ここで決まります。

11やりたいことから引くと、AIエージェントに仕込むhooksはどれになりますか?

イベント名から入ると迷います。「何をしたいか」から引ける表にします。

やりたいこと使うイベント判定の返し方
危険な操作を実行前に止めたいPreToolUsepermissionDecision: "deny"
起動時に必読ルールを注入したいSessionStartadditionalContext
実行結果を書き換えたい(マスキング等)PostToolUseupdatedToolOutput
応答を終える前にもう1周させたいStopdecision: "block"
設定ファイルの変更を検知して止めたいConfigChangedecision: "block"(policy_settings除く)
.envのようなファイルの変化だけ監視したいFileChangedmatcherにファイル名を列挙(副作用専用)
サブエージェント完了時に集計処理を挟みたいSubagentStopdecision: "block"またはadditionalContext
MCPからの入力要求に自動で応答したいElicitationaction: "accept"/"decline"/"cancel"

迷ったときは、上から順に3つの問いを自分に投げてください。取り消せない操作か。止めたいのか。それとも観測だけでよいのか。この順で答えると、たいていは1つに絞れます。

12チームでAIエージェントの止め方をそろえるには、hooksをどこに書くんですか?

高梨課長
高梨課長の発言

手元では動くようになりました。これをチームの全員に同じように効かせるには、どこに書けばいいんでしょうか。

鈴木さん
鈴木さんの発言

置き場所が6つあります。共有したいものはプロジェクトの設定へ、自分だけの一時的な上書きは手元へ。分け方はそれだけです。

hooksを書ける場所は6箇所あります(出典: Claude Code公式ドキュメント)。

置き場所有効範囲共有可否
~/.claude/settings.json全プロジェクト不可(個人設定)
.claude/settings.json単一プロジェクト可(Gitでコミット)
.claude/settings.local.json単一プロジェクト不可(gitignore対象)
Managed policy settings組織全体可(管理者のみ変更)
プラグインのhooks/hooks.jsonプラグイン有効時可(同梱配布)
スキル・エージェントのfrontmatter動作中のみ可(ファイル内に記述)

チームで共有するhooksは .claude/settings.json に書いてGitで配り、個人の一時的な上書きは .claude/settings.local.json へ置きます。permissions のallow・ask・denyとhooksの配分は『Claude Codeの権限設定|AIエージェントに任せる範囲と3列の配分』で扱っています。

13同じhooksを2か所に書くと、AIエージェントでは何回動くんですか?

高梨課長
高梨課長の発言

同じhookを共有側と手元の両方に書いてしまったら、2回動くんでしょうか。

鈴木さん
鈴木さんの発言

そこは条件つきです。コマンドと引数が完全に一致していれば1回にまとまります。少しでも違えば、両方とも動きます。

同じhookを2か所に書いたら、どうなるか一致の度合いで、動く回数が変わります同じhookを2か所に書いたら、どうなるか一致の度合いで、動く回数が変わりますコマンドも引数も完全に一致重複が排除される1回だけ動く上書きしたつもりが、そのとおりになる少しでも違う排除されないすべて並列で動く二重に動いていることに気づきにくい
同じhookを2か所に書いたら、どうなるか — 一致の度合いで、動く回数が変わります

同じイベントに複数の置き場所から登録した場合、コマンドと引数が完全に一致するものは重複が排除され、1回だけ動きます。それ以外は、すべて並列で実行されます。「手元の設定で上書きしたつもりが、両方動いていた」という取り違えは、ここで起きます。

組織全体へ配るManaged policy settingsは、管理者だけが変更できます。allowManagedHooksOnly を有効にすると、Managed以外のhookは動かなくなります。配る側と使う側で前提が変わるので、有効にするかどうかは先に決めておく話になります。

14matcherを書き間違えると、AIエージェントのどこにhooksが効かなくなるんですか?

matcherは、そのhookをどのツール名・どのファイル名に効かせるかを書く欄です。ここの評価ルールが、事故のいちばん多い場所になります

書き方は3パターンあります(出典: Claude Code公式ドキュメント)。

  • *・空文字・省略:全件一致
  • 英数字・_-・空白・,| だけの文字列:完全一致かリスト指定
  • それ以外の文字を含む:正規表現として評価

例で言うと、Bash は完全一致、Edit|Write はリスト、mcp__memory__.* は正規表現です。

matcherは、表札の書き方に似ています書いた文字の種類で、読まれ方が変わりますmatcherは、表札の書き方に似ています書いた文字の種類で、読まれ方が変わります表札でいうとmatcherでいうと名前だけを書く英数字だけなら完全一致同居人を縦棒で並べるリスト指定として読まれる「◯◯を含む家」と書く記号が混ざると正規表現念のため※を足す全件一致ではなく正規表現になるFileChangedとStopFailureだけ、完全一致になる文字が狭くなります。
matcherは、表札の書き方に似ています — 書いた文字の種類で、読まれ方が変わります

ハイフンが完全一致の側に入ったのは v2.1.195 以降です。それより前は code-reviewer も正規表現として扱われ、senior-code-reviewer にも当たっていました。同じ設定ファイルが、バージョン違いの環境では別の当たり方をする、ということです。

FileChangedとStopFailureは例外です。完全一致になるのは英数字・_| だけで、ハイフン・空白・カンマを含めると、他のイベントより先に正規表現として評価されます。

15hooksから外部へつなぐとき、AIエージェントはどれくらい待つんですか?

hookの実行方式(type)は5種類です(出典: Claude Code公式ドキュメント)。

  • command:シェルコマンドを実行する
  • http:URLへPOSTする
  • mcp_tool:MCPツールを呼ぶ
  • prompt:モデルにYes/Noを判定させる
  • agent:検証用のサブエージェントを動かす

デフォルトタイムアウトは方式ごとに違います。commandhttpmcp_tool が600秒、prompt が30秒、agent が60秒です。判定をモデルに任せる promptagent は、外部へPOSTするより短く設定されています。

イベント側にも短い既定値があります。UserPromptSubmitは30秒、MessageDisplayは10秒、SessionEndは1.5秒です。

外部へ問い合わせる処理をhooksに置くときは、この既定値を先に確かめておくと、打ち切られてから気づく事態を避けられます。

16hooksが受け取る情報は、AIエージェントのどのイベントでも同じですか?

入力側の共通フィールドは、全イベントで同じですsession_idtranscript_pathcwdhook_event_namepermission_mode。サブエージェントの中では agent_idagent_type も加わります。

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/current/working/directory",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse"
}

出力側の共通フィールドは continuestopReasonsuppressOutputsystemMessage です。イベント固有の判定は hookSpecificOutput の中に書きます。共通部分が同じなので、1本書ければ他のイベントへも移しやすくなります。

17AI導入の順番として、hooksはどのイベントから設定するんですか?

高梨課長
高梨課長の発言

30種類あると分かったのはいいんですが、どこから手を付ければいいでしょうか。全部は無理です。

鈴木さん
鈴木さんの発言

全部やらなくて大丈夫です。取り消せない操作に近いところから入れてください。観測用のものは、後からでも間に合います。

高梨課長
高梨課長の発言

順番を決める基準がほしいです。

鈴木さん
鈴木さんの発言

「戻せない操作か」と「止められるイベントか」。この2つで並べると、最初に入れる1本が決まります。

30種類を全部使う必要はありません。取り消せない操作に近いイベント(PreToolUse・SessionStart等)から優先して登録し、観測用途は後回しにする。この優先順位づけが、実務では機能します。

どのイベントから入れるかを、2軸で決めます戻せるかと、止められるかで区画が決まりますどのイベントから入れるかを、2軸で決めます戻せるかと、止められるかで区画が決まります最初に入れるPreToolUse。戻せない操作をdenyにする先に渡しておくSessionStart。止まらないが優先度は高いあとから足すStopやPostToolUse。やり直しがきく観測として後回しInstructionsLoadedなど記録の層上:戻せない操作に近い / 下:あとから戻せる左:止められるイベント / 右:止められないイベント
どのイベントから入れるかを、2軸で決めます — 戻せるかと、止められるかで区画が決まります

最後に、PermissionDeniedの落とし穴を1つ。PreToolUseと同じ感覚で exit code 2 を返しても、ここでは無視されます。読まれるのは retry フィールドだけです。matcherと type の挙動は、イベントをまたいで統一されていません。類推で実装せず、公式ドキュメントを都度確認するのが要になります。

着手前の確認は、次の項目で足ります。

  • 実行前に止めたい操作を、PreToolUseのdeny対象として洗い出したか
  • 使うイベントを「発火タイミング」と「ブロックできるか」の2軸で選んだか
  • matcherに * など、正規表現化する文字を意図せず混ぜていないか
  • settings.jsonのどの置き場所(User/Project/Local/Managed等)に書くか決めたか
  • 短いデフォルトタイムアウト(UserPromptSubmit 30秒・MessageDisplay 10秒・SessionEnd 1.5秒)を把握したか
  • /hooks コマンドで登録内容を確認したか
  • PreToolUseの詳しい実装は専用記事へ委ね、ここでは判断基準だけを使ったか

18よくある質問

Claude Code hooksは常駐しているプロセスですか

いいえ。対応するイベントが起きたときだけ新しいプロセスとして起動し、判定を返すと終了します。裏で待ち続けているわけではありません。逆に言うと、時刻を起点に動かしたい処理はhooksでは書けません。毎朝決まった時間に何かをさせたい場合は、定期実行の層が担当します。この役割分担は『AIエージェントの自動化は4層|着手する順番と稼働の数え方』で整理しています。

PreToolUseとPermissionRequestは何が違いますか

PreToolUseは、ツール呼び出しの直前に発火します。返せる判定は permissionDecision で、allowdenyaskdefer です。PermissionRequestは、許可判定が要る局面だけで発火する別の入口で、返せるのは decision.behaviorallowdeny に絞られます。呼び出しそのものに広く効かせたいならPreToolUse、許可を求められた場面だけに応答したいならPermissionRequest、という選び分けになります。

hooksのイベント一覧はどこで確認できますか

Claude Codeで /hooks と入力すると、登録済みのイベントとmatcherを読み取り専用で一覧できます(出典: Claude Code公式ドキュメント)。ここで見えるのは、いま読み込まれている内容です。設定ファイルに書いた内容と食い違うことがあるので、書いたあとに一度は目で確かめてください。イベントそのものの一覧は、本記事の表を手元に置いておくと引きやすくなります。

hooksがdeferを返すと何が起きますか

claude -p の非対話実行では、そのツールは実行されず、stop_reasontool_deferred でセッションが終了します。呼び出し元のアプリは deferred_tool_use を読み、自前のUIで入力を集めてから claude -p --resume で再開します。対話セッションでは警告が記録され、フックの結果は無視されます(出典: Claude Code公式ドキュメント)。外部アプリからClaude Codeを呼ぶ構成でなければ、当面は使わない値です。

hooksをどのイベントから設定し始めるべきですか

取り消せない操作に近いイベントからです。まずPreToolUseで、戻せない操作をdenyにする。ここが最も優先度の高い1本になります。次に、起動のたびに読ませたい前提があればSessionStartを足します。記録や通知のような観測用途は、そのあとで構いません。順番を逆にすると、動いている実感は得られても、いちばん危ない場所が空いたままになります。

19まとめ|今日やる3つのこと

選ぶ軸は、いつ発火するかと、止められるかどうかの2つでした。イベント名を覚えるのではなく、一覧を引く。その順で進めてください。

今日この順で手をつけます

  1. 止めたい操作を1つ書き出す

    対象が決まらないと、選ぶイベントも決まりません

  2. そのイベントが止められるかを一覧で確かめる

    止まらない場所に書いても、通り抜けます

  3. /hooks で登録内容を目で見る

    書いたことと、読み込まれたことは別です

AI検索では、こう聞かれています

  • Claude Codeのhooksって、どんなイベントがあるんですか?

    「Claude Code hooksの一覧は、AIエージェントの1セッションのどこで発火するんですか?」の章に全30種類の表があります

  • AIエージェントを実行の直前で止めるには、どのhooksを使うんですか?

    「AIエージェントの手を実行の直前で止めるのは、どのhooksですか?」の章で説明しています

  • hooksはどのイベントから設定し始めればいいんですか?

    「AI導入の順番として、hooksはどのイベントから設定するんですか?」の章で扱っています

  • 書いたhooksが動かないのは、どこを間違えているんですか?

    「matcherを書き間違えると、AIエージェントのどこにhooksが効かなくなるんですか?」の章に原因の型があります

次に読むなら、この記事です