Claude Codeを使い始めると、最初は「指示を出せばコードを書いてくれる」だけでも十分便利です。しかし、運用が長くなるにつれて、毎回同じ確認を頼む、編集後に同じテストを走らせる、危険なコマンドだけ止める、セッション開始時に環境情報を読み込ませる、といった定型作業が増えてきます。そこで役立つのがClaude Code Hooksです。
この記事では、Claude Code Hooksの仕組みを、イベント、Matcher、Handler、Decisionの4要素に分けて解説します。単に設定例を並べるのではなく、どのイベントを選ぶべきか、どこまで自動化してよいか、誤作動をどう防ぐかまで扱います。
結論:Hooksは「Claudeの判断を置き換える機能」ではなく、ライフサイクル上の決まった地点で検証や通知を自動実行する仕組みです。最初はPostToolUseでの軽い検証から始め、PreToolUseによる拒否は対象を狭く設計するのが安全です。
Claude Code Hooksとは
Claude Code Hooksは、Claude Codeの特定のイベントに応じて、ユーザーが定義した処理を自動実行する機能です。公式リファレンスでは、シェルコマンド、HTTPエンドポイント、MCPツール、LLMプロンプト、サブエージェントなどをHook handlerとして利用できます。
重要なのは、Hooksが単なる「実行後スクリプト」ではない点です。セッション開始、ユーザープロンプト送信、ツール実行前、ツール成功後、ツール失敗後、停止、コンテキスト圧縮前後など、Claude Codeのライフサイクル上に多数のイベントがあります。適切なイベントを選ぶことで、同じ処理を毎回プロンプトへ書かずに済みます。
一方、Hooksはユーザーの権限で処理を実行します。設定を広くしすぎると、すべてのツール呼び出しで重い処理が走ったり、不適切な入力をシェルへ渡したりする危険があります。便利さより先に、対象範囲と失敗時の挙動を決めることが大切です。
スラッシュコマンドとの違い
Claude Codeのスラッシュコマンドは、ユーザーが明示的に呼び出す「手動の入口」です。たとえば、レビュー用プロンプトや定型の調査手順を、必要なときだけ展開する用途に向きます。詳しいコマンド一覧は、Claude Codeのスラッシュコマンド一覧で解説しています。
Hooksは、イベントが発生したときに自動で動く仕組みです。毎回忘れずに実行したい検査、通知、ログ記録などに向いています。
| 比較項目 | スラッシュコマンド | Hooks |
|---|---|---|
| 起動方法 | ユーザーが手動実行 | イベントで自動実行 |
| 主な用途 | 定型プロンプト、作業メニュー | 検証、通知、ガード |
| 実行頻度 | 必要なときだけ | 条件に一致するたび |
| 主なリスク | 呼び忘れ | 過剰実行、誤った拒否 |
| 設計の中心 | 何を依頼するか | いつ、何を対象に動くか |
両者は競合するものではありません。「作業を始める操作」はスラッシュコマンド、「作業中に必ず守る検証」はHooks、という組み合わせが分かりやすいです。
Hooksを構成する4つの要素

Hooksの設定は、次の4要素に分けると理解しやすくなります。
1. Event
Eventは、処理を起動するタイミングです。代表例は次のとおりです。
- SessionStart:セッション開始または再開時
- UserPromptSubmit:プロンプト送信後、Claudeが処理する前
- PreToolUse:ツール呼び出しの実行前
- PermissionRequest:権限判断が必要になった時
- PostToolUse:ツール呼び出し成功後
- PostToolUseFailure:ツール呼び出し失敗後
- Stop:Claudeが応答を終える時
- PreCompact/PostCompact:コンテキスト圧縮の前後
- SessionEnd:セッション終了時
ファイル変更のたびにテストするならPostToolUse、危険なコマンドを実行前に止めるならPreToolUse、環境情報を追加するならSessionStartが候補です。
2. Matcher
Matcherは、イベントの中から対象を絞り込むフィルターです。たとえばPreToolUseのすべてではなく、Bashツールだけを対象にできます。
対象を絞らない設定は、処理回数が増えるだけでなく、関係のないツールまで拒否する原因になります。最初は具体的なツール名から始め、必要性を確認してから範囲を広げます。
3. Handler
Handlerは、実際に動かす処理です。コマンドHookでは、Claude Codeがイベント情報をJSONとして標準入力へ渡します。Handlerはその入力を読み、検査、ログ記録、テスト実行などを行います。
標準入力の値は、そのままシェルコマンドへ連結してはいけません。JSONとして読み、必要なフィールドだけを取得し、許可した形式か検証してから使います。
4. Decision
イベントによっては、Handlerの結果で処理を許可または拒否できます。PreToolUseでは危険な呼び出しをdenyできますが、無言の成功を「常に許可」とみなす設計は避けます。Hookが判断を返さない場合は、Claude Codeの通常の権限フローへ戻すのが基本です。
設定ファイルを置く場所
HooksはClaude Codeのsettingsファイルに設定します。配置場所で適用範囲が変わります。
- ~/.claude/settings.json:その端末上のすべてのプロジェクト
- .claude/settings.json:プロジェクトで共有する設定
- .claude/settings.local.json:プロジェクト固有だがローカルだけの設定
- 管理者ポリシー:組織で強制する設定
個人だけのパスや通知コマンドを共有設定へ入れると、他の開発者の環境で失敗します。チーム共通の品質検査はプロジェクト設定、個人用通知はローカル設定、強制すべきセキュリティルールは管理ポリシー、という分け方が実用的です。
設定変更前には、既存のsettingsをコピーして戻せる状態にします。また、リポジトリ共有する設定に秘密情報、ホームディレクトリの絶対パス、個人専用トークンを含めないでください。
最小構成:ファイル編集後に検証を走らせる
最初のHooksとして扱いやすいのは、ツール成功後に軽い検証を実行する構成です。次は考え方を示す最小例です。実際のツール名やmatcherは、利用中のClaude Code公式リファレンスで確認してください。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-after-edit.sh"
}
]
}
]
}
}
Handler側では、まず軽量な確認だけを行います。
#!/usr/bin/env bash
set -euo pipefail
cd "$CLAUDE_PROJECT_DIR"
git diff --check
この例は、コードの正しさ全体を証明するものではありません。しかし、空白エラーなどを編集直後に見つけられます。毎回フルテストを走らせると遅くなるため、Hookでは軽量検査を実行し、まとまったテストは作業完了時に実行する分担が向いています。
PreToolUseで危険な操作を止める
PreToolUseは、ツール実行前に入力を確認できる強力なイベントです。削除、外部送信、公開、購入など、実行前に人間判断が必要な操作をガードできます。
ただし、「特定の文字列が含まれたら全部拒否する」だけの単純なルールは、引用、説明、テストコードまで誤検知することがあります。ツール名、サブコマンド、対象パス、操作種別を分けて判定してください。
安全な設計は次の順番です。
- Matcherで対象ツールを限定する
- JSON入力から必要な値だけ読む
- 許可リストまたは構造化条件で判定する
- 拒否理由を短く具体的に返す
- 判断できない入力は安全停止する
- 正常系だけでなく誤検知をテストする
公式例では、PreToolUseのdecisionを使い、危険なシェルコマンドを拒否できます。実運用では、文字列の部分一致だけでなく、パスを正規化してから対象範囲を照合することが重要です。
終了コードとJSON出力
コマンドHookでは、終了コードと標準出力がClaude Codeへの結果になります。イベントごとに扱いが異なるため、すべてを同じ動作だと思わないでください。
一般的には、終了コード0はHook処理の成功、終了コード2はブロック判断に使われる場面があります。他の終了コードは非ブロッキングエラーとして扱われる場合があります。ただし、正確な挙動はイベント別の公式表を確認する必要があります。
構造化されたdecisionや追加コンテキストを返す場合は、仕様どおりのJSONを標準出力へ出します。デバッグ文を同じ標準出力へ混ぜるとJSONが壊れるため、診断ログは標準エラーへ出すか、別のログファイルへ分けます。
入力を安全に扱う
Hook入力はClaude Codeから渡されますが、その中にはユーザープロンプト、ファイルパス、ツール引数など、外部由来の値が含まれる可能性があります。「Claude Codeが渡したから安全」とは限りません。
特に避けたいのは次の実装です。
COMMAND=$(jq -r '.tool_input.command')
eval "$COMMAND"
evalは入力をもう一度シェルとして解釈します。検査用Hookが、逆に任意コマンド実行の入口になります。値を実行するのではなく、解析対象として扱ってください。
パスを扱う場合は、相対パス、シンボリックリンク、親ディレクトリ参照を考慮します。プロジェクト内だけを対象にするなら、正規化後のパスがプロジェクトルート配下か確認します。ログへ入力全体を残す場合も、APIキーや個人情報が混ざらないようにマスキングが必要です。
安全な運用を3層に分ける




Hooksの安全性は、Matcher、Handler、Decisionの3層で考えると整理できます。
Matcher層:実行対象を最小化する
Bash全体ではなく、必要なサブコマンドやツールへ限定します。すべてのファイル変更ではなく、対象拡張子や特定ディレクトリだけに絞る方法もあります。起動回数を減らすことは、速度だけでなく誤作動の減少にもつながります。
Handler層:境界で検証する
JSONの型、必須項目、文字数、パス、許可値を確認します。タイムアウトを設定し、ネットワーク障害やツール未導入時の挙動も決めます。秘密情報を標準出力へ含めません。
Decision層:拒否範囲を限定する
拒否するのは、明確に危険と判定できる操作に限定します。Hookが落ちただけで全作業を永久停止するのか、警告だけにするのかも、イベントの重要度に応じて分けます。
非同期Hookを使う場面
公式リファレンスには、バックグラウンドで実行する非同期Hookもあります。時間のかかる通知、分析、ログ転送をメイン処理から切り離したい場合に有効です。
ただし、非同期処理は実行前の拒否判断には使えません。結果を待たずにClaude Codeが進むためです。危険操作のガードは同期処理、完了通知や低優先度の分析は非同期処理、と分けます。
非同期Hookでは、重複実行、セッション終了後の処理、ログの保存先、失敗の発見方法も設計します。「バックグラウンドだから速い」だけで採用すると、失敗が見えなくなります。
HTTP・MCP・Prompt・Agent Hook
HooksのHandlerはシェルコマンドだけではありません。
HTTP Hookは、イベント情報をPOST bodyとしてエンドポイントへ送ります。便利ですが、外部送信になるため、送信先、認証、タイムアウト、送信データの最小化が必要です。プロンプト本文やツール引数を丸ごと送らない設計が安全です。
MCP tool Hookは、登録済みMCPツールをHandlerとして利用します。ツールの入力Schemaと権限を確認し、Hookから呼び出してよい操作を限定します。
Prompt Hookは、LLMへ条件判断を依頼できます。単純な規則で表しにくい検査に向きますが、確率的な結果、追加コスト、遅延があります。削除や購入のような高リスク操作を、LLM判断だけで自動承認しないでください。
Agent Hookは、より複数ステップの確認に使えます。調査能力は上がりますが、実行時間と費用も増えます。まず決定的なコマンドHookで実装できないか検討するのがよい順番です。
よくある失敗と対処
Hookが動かない
イベント名、設定ファイルの場所、JSON構文、Matcherを確認します。プロジェクト設定を変更した場合、ワークスペース信頼の状態によっては反映されないことがあります。Claude Codeのhooksメニューやデバッグ機能で、読み込まれた設定を確認します。
毎回何度も起動する
Matcherが広すぎる可能性があります。PostToolUseはエージェントループ内でツール成功ごとに発生します。ツール名、対象ファイル、サブコマンドを絞り込みます。
HookでClaude Codeが遅くなる
同期Hookでフルテストや重いネットワーク処理を実行していないか確認します。編集後は静的検査、完了時はフルテスト、通知は非同期というように役割を分けます。
正常な操作まで拒否される
文字列の部分一致だけで拒否すると誤検知します。構造化入力を使い、ツールと対象パスを確認します。拒否理由を記録し、実際の誤検知例をテストケースへ追加します。
JSON出力が読まれない
標準出力にデバッグ文字列が混ざっていないか、イベントに対応したSchemaかを確認します。ログは標準エラーへ分けます。
Windowsで挙動が違う
シェル、パス区切り、実行ポリシーが異なります。PowerShell用Handlerを分け、OSごとのテストを用意します。共有設定へmacOS専用パスを書かないようにします。
導入前チェックリスト
- □ 自動化したい作業と、手動で残す判断を分けた
- □ Eventを公式リファレンスで確認した
- □ Matcherを必要最小限にした
- □ Hook入力の型、値、パスを検証した
- □ evalや未検証の文字列連結を使っていない
- □ タイムアウトと失敗時の挙動を決めた
- □ 秘密情報を標準出力や共有ログへ残していない
- □ 正常系、失敗、誤検知をテストした
- □ 外部送信、費用、削除、公開には人間の確認を残した
- □ 非同期処理の重複と失敗の確認方法を決めた
段階的な導入手順
最初から多数のHooksを追加すると、どの設定が問題か分からなくなります。次の順番がおすすめです。
- PostToolUseでgit diff --checkなどの軽量検査を1つ追加する
- 起動回数と所要時間をログで確認する
- 対象ツールと対象ファイルをMatcherで絞る
- 失敗を通知するが、まずは自動拒否しない
- 誤検知例をテストへ追加する
- 明確な危険操作だけPreToolUseで拒否する
- 通知や低優先度分析を非同期化する
この順番なら、作業を止める前に観測データを得られます。自動拒否は最後に追加するのが安全です。
HooksとAIエージェント運用
HooksはAIエージェントそのものではありません。AIエージェントが複数ステップでツールを選び、目標へ進む仕組みについては、AIエージェントとは?生成AI・RAGとの違いとPythonで動かすAIエージェントの最小構成も参考になります。
AIエージェントへツールを与えるほど、実行前後の検査、ログ、承認境界が重要になります。Hooksは、その運用上の境界をコードで補助する仕組みとして役立ちます。
まとめ
Claude Code Hooksは、Claude Codeのライフサイクルに合わせて定型処理を自動化する機能です。Eventでタイミングを選び、Matcherで対象を絞り、Handlerで入力を検証し、必要な場合だけDecisionを返します。
導入の第一歩は、編集後の軽量検査や通知です。動作回数と誤検知を観測してから、危険操作の拒否へ進みます。Hooksを「何でも自動化する仕組み」ではなく、「忘れたくない検証を小さく確実に実行する仕組み」と捉えると、安全性と開発効率を両立しやすくなります。

コメント