Claude Code特集2026年5月更新

Claude Code Hooks 使い方|PreToolUse/PostToolUse/Stop/SubagentStop 完全ガイド

公開日: 2026/04/22
更新日: 2026/05/20
Claude Code Hooks 使い方|PreToolUse/PostToolUse/Stop/SubagentStop 完全ガイド

この記事のポイント

Claude Code Hooks の全イベント・5ハンドラータイプを完全解説。PreToolUse/PostToolUse/Stop/SubagentStop の設定例、exit 2の罠、stop_hook_active対策など実務で即使えるレシピを網羅。

Claude Code Hooks は、rm -rf のような破壊的コマンドの事前ブロック、編集後の型チェック自動実行、作業ログの自動記録などをLLMの判断に依存せず設定ファイルだけで保証できる仕組みです。公式リファレンス(v2.1.141+ 系、2026年5月時点)では27以上のイベントと5タイプのハンドラーが確認されています。

この記事でわかること:

  • Claude Code Hooks の全体像と5つのハンドラータイプの使い分け
  • 主要4イベント(PreToolUse / PostToolUse / Stop / SubagentStop)の仕様・設定例・制御出力の違い
  • 全ライフサイクルイベント一覧(27以上)と発火タイミング
  • exit 1 では止まらない・無限ループに陥るなど、よくある落とし穴と回避策
  • Hooks / Permissions / CLAUDE.md の責任分界と使い分け基準
  • バージョン別の機能追加履歴(v2.0.28〜v2.1.141+)
  • 企業導入時のセキュリティ統制(管理者ポリシー・hook 無効化)

対象読者は、Claude Code を導入済みで「自動化とガードレールをもう一段階深めたい」中級〜上級の開発者、およびチームに Claude Code を展開する前にガバナンスを整えたい技術リーダーです。

Claude Code Hooks とは|30秒で全体像を掴む

Claude Code Hooks は、Claude Code の内部イベントに対してフックスクリプトを登録し、決定論的なガードレールと自動化を実現する仕組みです。Anthropic の公式ドキュメント(hooks-guide)では、「LLM が自分でそう判断するのに依存するのではなく、特定のアクションが常に発生することを保証する」ための機能と説明されています。

Hooks が解く課題は3つあります。

  1. 安全性: 破壊的コマンド(rm -rfgit push --force、本番DBへの書き込みなど)をLLMの判断に委ねず、設定ファイル側で確実にブロックしたい
  2. 品質: ファイル編集後に Prettier・ESLint・型チェック・テストを必ず走らせたい
  3. 運用: セッション開始時にプロジェクトコンテキストを自動注入したり、作業ログを自動記録したい

これらを Claude Code の settings.json に記述するだけで、セッション再起動や独自ツール不要で即運用できます。

できることの代表例

カテゴリ

代表ユースケース

事前ブロック

rm -rf /git push --force.env 編集、本番環境への接続

自動品質担保

Prettier / ESLint / TypeScript型チェック / pytest / go test の自動実行

コンテキスト注入

現在時刻・git status・ブランチ名・最近のissueを毎ターン自動追加

監査・ロギング

全ツール呼び出しを外部サーバーにPOST、セッションコスト記録

停止ゲート

テスト未通過なら Claude を停止させない、未コミット時に警告

サブエージェント検証

Taskツール完了後の成果物検証・リソースクリーンアップ

Hooks の提供状況(2026年5月時点)

  • 提供元: Anthropic(Claude Code に標準同梱、追加料金不要)
  • 対応環境: macOS / Linux / Windows(Claude Code が動く全環境)
  • 現行バージョン: v2.1.141+(2026年5月時点。日々更新されるため claude --version で確認)
  • 確認コマンド: Claude Code 内で /hooks を実行すると設定済み hooks を一覧できる(読み取り専用ブラウザ)
Claude Code 公式製品ページのスクリーンショット

出典: Anthropic 公式サイト

関連記事: Claude Code とは|料金・使い方・特徴を徹底解説 / Claude Code 使い方 完全ガイド

設定ファイルの配置場所とスコープ

Hooks は複数のスコープで多層的に設定できます。優先順位は厳密に決まっており、管理者ポリシー > プロジェクト > ユーザー > プラグイン/スキルの順で評価され、上位設定は下位設定を上書き・制限できます。

配置場所

スコープ

Git共有

用途

管理ポリシー設定

組織全体

管理者配布

エンタープライズ統制

.claude/settings.json

単一プロジェクト

チーム共通のガードレール

.claude/settings.local.json

単一プロジェクト

不可(gitignore)

個人の実験的 hook

~/.claude/settings.json

ユーザー全体

不可

個人の全プロジェクト共通 hook

プラグイン hooks/hooks.json

プラグイン有効時

プラグインにバンドル

再利用可能なhook集

スキル / エージェント frontmatter

コンポーネント有効時

コンポーネント内

特定スキル限定 hook

運用のコツ: チームで共有したい最低限のガードレール(rm -rf 防御、.env 保護など)は .claude/settings.json にコミットし、個人ごとの実験用 hook は .claude/settings.local.json に置くのが基本パターンです。

設定ファイルの基本構造|3階層ネストを理解する

Hooks 設定は3階層のネスト構造で記述します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh",
            "timeout": 600,
            "if": "Edit(*.env)"
          }
        ]
      }
    ]
  }
}

各階層の役割

  1. イベント名PreToolUse など): ライフサイクル上のどのタイミングで発火するか
  2. matcher: どのツール・条件にマッチしたときに実行するか
  3. hooks: 実際に実行するハンドラー(command / http / mcp_tool / prompt / agent の5タイプ)

matcher 構文の評価ルール

matcher は文字列の中身によって評価方式が変わります。

パターン

評価方式

"*"""、省略

全マッチ(毎回発火)

すべてのツール

英数字・_| のみ

完全一致 or パイプ区切り

Bash / Edit|Write

それ以外の文字を含む

JavaScript 正規表現として評価

^Notebook / mcp__.*__write.*

if フィールド(v2.1.85 以降)でツール引数レベルのフィルタ

Claude Code v2.1.85 以降では、if フィールドで許可ルール構文を使ったツール引数レベルの条件指定ができます。matcher でツール名を絞った上で、さらに引数でも絞り込めるため、不要な hook 発火を大幅に減らせます。

{ "if": "Bash(git push --force*)" }
{ "if": "Edit(*.ts)" }
{ "if": "Bash(rm *)" }

ポイント:

  • matcher でツール名を絞り、if で引数を絞るのが推奨パターン
  • 複合コマンド(npm test && git push)はサブコマンドごとに評価される
  • if が機能するのはツール系イベント(PreToolUse / PostToolUse / PostToolUseFailure / PermissionRequest / PermissionDenied)のみ
  • matcher を通過したフックグループの中で、個別フックレベルでさらに絞り込める

5つのハンドラータイプの使い分け

Hook が実行する処理は5つのタイプから選べます。用途と確実性のトレードオフで使い分けるのが基本です。

タイプ

主な用途

LLM利用

デフォルトタイムアウト

備考

"type": "command"

シェルコマンド実行(最も基本)

なし

600秒(UserPromptSubmit: 30秒)

stdin で JSON 受信、stdout/stderr/終了コードで応答

"type": "http"

外部URLへPOST

なし

600秒(UserPromptSubmit: 30秒)

監査サーバー連携。allowedEnvVars でヘッダー補間

"type": "mcp_tool"

MCPサーバーのツール呼び出し

なし

600秒

既存MCPインフラとの連携向け

"type": "prompt"

単一ターンLLM判定

あり

30秒

デフォルト Haiku で {"ok": true/false} を返させる

"type": "agent" ⚠️実験的

サブエージェントによる調査付き判定

あり

60秒(最大50ターン)

公式が実験的と明記。本番前に挙動検証必須

最初は command から始めるのが安全です。 prompt / agent は LLM 呼び出しコストが発生し、かつレスポンスに揺らぎが出るため、確実性が求められるガードレールには向きません。agent タイプは公式が実験的と明記し仕様変更の可能性があるため、本番運用前に挙動を十分確認してください。

mcp_tool タイプは、既にプロジェクトで MCP サーバーを使っている場合に有効です。たとえば GitHub MCP サーバーの create_issue を hook から呼び出して、エラー発生時に自動で issue を作成するといった連携が可能です。

関連記事: Claude Code MCPの使い方

Exit Code と制御出力|最頻出ミス領域

Hook の挙動を決める最重要ポイントが終了コード(Exit Code)です。ここを誤解していると「設定した気になっていたのに何も守られていなかった」状態が起きます。

Exit Code の動作

Exit Code

動作

0

成功。stdout が JSON なら制御出力として解釈。UserPromptSubmit / SessionStart では stdout がそのままコンテキストに追加される

1

非ブロッキングエラー。stderr はトランスクリプトに表示されるのみで、アクションは続行される

2

ブロッキングエラー。アクションがブロックされ、stderr が Claude へフィードバックとして渡される

その他

非ブロッキング。<hook name> hook error として通知のみ

⚠️ 最大の落とし穴: exit 1 では止まらない

セキュリティゲートを作ったつもりで exit 1 を使ってしまうと、警告は表示されるが実行自体はブロックされません。ポリシー強制目的では必ず exit 2 を使ってください。

# ❌ 悪い例: 警告は出るが rm -rf は実行される
if echo "$COMMAND" | grep -q "rm -rf"; then
  echo "危険なコマンドです" >&2
  exit 1   # ← これでは止まらない
fi

# ✅ 正しい例: 実行がブロックされ、Claude にフィードバックが返る
if echo "$COMMAND" | grep -q "rm -rf"; then
  echo "rm -rf は禁止されています" >&2
  exit 2   # ← これで確実にブロック
fi

Unix の慣例では exit 1 が「失敗」ですが、Claude Code ではブロックにならない点が混乱を招きます。この挙動は多くの記事でも誤解されている最頻出バグです。

構造化 JSON 出力(exit 0 時)

より柔軟な制御をしたい場合は、stdout に JSON を返します。

{
  "continue": true,
  "stopReason": "...",
  "suppressOutput": false,
  "systemMessage": "...",
  "decision": "block",
  "reason": "...",
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "...",
    "updatedInput": { "field": "value" },
    "additionalContext": "...",
    "retry": true
  }
}

注意点:

  • コンテキスト系フィールド(additionalContext など)は 10,000文字上限
  • PreToolUse の許可判定は hookSpecificOutput.permissionDecision を使う(トップレベル decision ではない)
  • exit 2 と JSON 制御を混在させない(Claude Code は exit 2 時に JSON を無視する)
  • 複数 hook の決定は最も制限的なものが採用される(deny > defer > ask > allow

全イベント一覧|ライフサイクル上で何が発火するか(27以上)

Claude Code は現時点(v2.1.141+)で27以上のイベントでhookを発火できます。以下に確認できた全イベントを一覧で示します。

イベント名

発火タイミング

ブロック可否

代表用途

PreToolUse

ツール実行直前

破壊的コマンド防止

PostToolUse

ツール成功直後

フィードバック可

型チェック・Lint

PostToolUseFailure

ツール失敗直後

コンテキスト注入可

失敗ログ・代替提案

PostToolBatch

並列ツール呼び出しが全て完了後

バッチ処理後の一括検証

UserPromptSubmit

ユーザー入力送信直後

✅(破棄)

時刻・git status 注入

UserPromptExpansion

スラッシュコマンド展開時

コマンド展開検証

Stop

Claude 応答終了時

✅(継続強制)

完了ゲート

StopFailure

APIエラーでターン終了時

エラー監視・自動リカバリー

SubagentStop

サブエージェント終了時

✅(継続強制)

成果物検証

SubagentStart

サブエージェント起動時

ロギング(観測専用)

SessionStart

セッション開始・再開時

コンテキスト注入

プロジェクト情報注入

SessionEnd

セッション終了時

一時ファイル削除

Setup

--init-only / -p --init 起動時

初期化処理

Notification

許可プロンプト表示・アイドル時

デスクトップ通知

PermissionRequest

許可ダイアログ表示時

自動承認・自動拒否

PermissionDenied

Autoモードで分類器が拒否時

retry指示可

再試行促進

PreCompact

コンテキスト圧縮前

圧縮前ルール記録

PostCompact

コンテキスト圧縮後

ルール再注入

FileChanged

監視対象ファイル変更時

direnv連携

CwdChanged

作業ディレクトリ変更時

環境切替

ConfigChange

設定ファイル変更時

リロード通知・監査ログ

InstructionsLoaded

CLAUDE.md / .claude/rules/*.md 読込時

ルール検証

WorktreeCreate

git worktree 作成時

ワークスペース管理

WorktreeRemove

git worktree 削除時

ワークスペース管理

TaskCreated

TaskCreate でタスク作成時

タスク監査

TaskCompleted

タスク完了マーク時

タスク監査

TeammateIdle

Agent Teamのチームメイトがアイドル時

チーム協調

Elicitation

MCPサーバーがユーザー入力を要求するとき

MCP統合

ElicitationResult

ユーザーがMCP elicitation に回答後

MCP統合

環境変数の永続化注意: $CLAUDE_ENV_FILE への書き込みが環境変数として次のターンに永続化されるのは、SessionStartSetupCwdChangedFileChanged の4イベントのみです。他のイベントでの環境変数注入は次ターンに引き継がれません。

PreToolUse|ツール実行前に挟むガードレール(最重要)

ターミナルのセキュリティガード:PreToolUseフックによる破壊的コマンドのブロック

PreToolUse は Hooks の中で最も重要なイベントです。Claude がツール呼び出しのパラメータを生成した直後、実際のツール実行の直前に発火します。ここでブロックすれば、破壊的な操作を確実に止められます。

いつ発火するか

  • Claude がツール呼び出し(Bash / Edit / Write / Read / Agent / WebFetch / MCPツールなど)を決定した後
  • 実際のツール実行の直前(ツールはまだ動いていない)

matcher の対象

ツール名で絞り込みます。

  • 組み込みツール: Bash / Edit / Write / Read / Glob / Grep / Agent / WebFetch / WebSearch / AskUserQuestion / ExitPlanMode など
  • MCP ツール: mcp__<server>__<tool> 形式(例: mcp__github__create_issue

入力スキーマ

stdin から以下の JSON が渡されます。

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/current/directory",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "npm test" },
  "tool_use_id": "toolu_01ABC123..."
}

制御出力(2通り)

方式A: 終了コード 2 で stderr にメッセージ

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$COMMAND" | grep -qE '(rm -rf|git push --force|drop table)'; then
  echo "破壊的コマンドのためブロックしました: $COMMAND" >&2
  exit 2
fi
exit 0

方式B: JSON で permissionDecision を返す

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "本番環境への接続は事前承認が必要です"
  }
}

permissionDecision の値は以下の4種類です。

  • allow: 許可して即実行
  • deny: ブロック(bypassPermissions モードや --dangerously-skip-permissions でも効く)
  • ask: ユーザーに確認
  • defer: 外部UIに判断を委ねる(v2.1.89以降、SDK利用時向け)

代表ユースケース

  1. 破壊的 Bash コマンドのブロックrm -rfgit push --forceDROP TABLE など
  2. 機密ファイルの保護.envcredentials.json*.pem の編集・読み取り防止
  3. ツール入力の書き換えupdatedInput で命令の一部を自動修正
  4. MCP 書き込みの検証mcp__.*__write.* にマッチさせて書き込み系 MCP ツールだけを検証

設定例: rm -rf と git push --force を全プロジェクトでブロック

~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard-bash.sh",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

.claude/hooks/guard-bash.sh:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# 危険パターン
if echo "$COMMAND" | grep -qE '(^|[; &|])rm -rf( |$)'; then
  echo "rm -rf は禁止されています。--dry-run で確認してください。" >&2
  exit 2
fi
if echo "$COMMAND" | grep -qE 'git push.*--force'; then
  echo "force push は禁止です。--force-with-lease か PR を使ってください。" >&2
  exit 2
fi
exit 0

⚠️ 補足: 許可モードとの優先関係

PreToolUse hook は任意の許可モード判定より前に発火します。つまり、ユーザーが bypassPermissions モードや --dangerously-skip-permissions を使っても、hook が deny を返せば必ずブロックされます。これによりユーザーがモード変更で回避できないポリシーを適用できます。

ただし逆は真ではなく、hook で allow を返しても設定の deny ルールはバイパスできません。hook は制限を厳しくはできても、緩和はできない設計です。

PostToolUse|実行後の品質ゲート

PostToolUseフックでコード品質チェック・型チェック・Lintを自動実行するイメージ

PostToolUse はツール呼び出しが成功した直後に発火します。ファイル編集後に Prettier / ESLint / 型チェックを自動実行するなど、品質ゲートの中核を担うイベントです。

発火タイミングと入力

  • ツール呼び出しが成功したとき(失敗時は PostToolUseFailure が発火)
  • stdin には tool_input に加えて tool_response が含まれる
{
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": { "file_path": "/path/to/file.ts", "content": "..." },
  "tool_response": { "filePath": "/path/to/file.ts", "success": true }
}

制御出力とその限界

⚠️ 重要な制約: PostToolUse はツールがすでに実行された後に発火するため、アクション自体は取り消せません。できるのは「結果を Claude にフィードバックし、次のアクションに活かす」ことだけです。

  • トップレベル decision: "block" + reason を返すと Claude にフィードバックが戻る
  • Claude はそれを読んで自主的に修正を試みる

代表ユースケース

  1. TypeScript 型チェック*.ts / *.tsx 編集後に tsc --noEmit を実行し、エラーがあれば Claude に戻す
  2. ESLint 自動修正eslint --fix を走らせ、残ったエラーを Claude にフィードバック
  3. Prettier 自動整形 — 編集ファイルを即フォーマット
  4. テスト自動実行 — 小規模プロジェクトならファイル編集後に pytest / vitest を走らせる
  5. 変更差分のログ化 — 監査用に git diff を記録
  6. コミット後の差分確認git commit 後に git log -1 を Claude に見せる

設定例: TypeScript 編集後の型チェック

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tsc-check.sh",
            "timeout": 60,
            "if": "Edit(*.ts)|Edit(*.tsx)|Write(*.ts)|Write(*.tsx)"
          }
        ]
      }
    ]
  }
}

.claude/hooks/tsc-check.sh:

#!/bin/bash
cd "$CLAUDE_PROJECT_DIR"
OUTPUT=$(npx tsc --noEmit 2>&1)
if [ $? -ne 0 ]; then
  jq -n --arg reason "$OUTPUT" '{
    decision: "block",
    reason: ("型エラーがあります。修正してください:\n" + $reason)
  }'
  exit 0
fi
exit 0

運用のコツ:

  • matcherif でファイル種別を必ず絞る(全ツールで型チェックを走らせると毎回2〜3秒以上かかる)
  • 実行時間の目安は1 hook あたり500ms以下。大規模プロジェクトでは差分ファイルだけ検査する工夫が必要
  • 重い処理は timeout を明示し、失敗時の挙動(open / closed)を決めておく

Stop|Claude の応答終了時に割り込む

Stopフックによるワークフロー自動化・タスク完了ゲートのイメージ

Stop イベントはClaude が応答を終えたタイミングで発火します。タスク未完了なら Claude を継続させる、作業ログを最終記録する、といった「最後の仕上げ」に使います。

発火タイミングの注意

  • Claude が応答を終了したときに毎回発火する(タスク完了時だけではない)
  • ユーザーが割り込みで停止させた場合は発火しない(APIエラーは StopFailure へ)

制御出力

  • 終了コード2 または JSON で decision: "block" を返すと、Claude は停止せず作業を継続する
  • stderr の内容が「継続すべき理由」として Claude に渡る

⚠️ 最重要の注意点: 無限ループ防止と8回上限

Stop hook で何も考えずに block を返すと、以下の無限ループに陥ります。

Claude 応答終了 → Stop hook 発火 → block → Claude 継続
→ また応答終了 → Stop hook 発火 → block → …(延々)

Claude Code では、Stop フックが8回連続でブロックすると Claude Code が強制終了します。これを防ぐため、Stop hook では必ず stop_hook_active フィールドをチェックしてください。

#!/bin/bash
INPUT=$(cat)

# ❗ 無限ループ対策: 2回目以降は素直に停止を許可
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0
fi

# ここに本来のロジック(例: テスト未通過なら止めない)
cd "$CLAUDE_PROJECT_DIR"
if ! npm test --silent > /dev/null 2>&1; then
  echo "テストが通るまで継続してください" >&2
  exit 2
fi
exit 0

stop_hook_active は「この Stop hook によって既に一度 Claude が継続させられた」ことを示すフラグです。2回目以降は exit 0 で素直に停止させるのが鉄則です。

代表ユースケース

  1. タスク完了ゲート — テスト未通過なら Claude を止めない
  2. 作業ログ最終記録 — セッションの最終サマリーを外部DBに保存
  3. 未コミット変更の警告git status で変更残りを検知してフィードバック

SubagentStop|サブエージェント終了時のフック

SubagentStop はサブエージェント(Task / Agent ツールで起動したエージェント)が終了したときに発火します。Stop とは別のイベントで、親セッションではなくサブエージェントのライフサイクルに紐付きます。

matcher

エージェントタイプ名でマッチします。

  • 組み込み: Bash / Explore / Plan / general-purpose など
  • カスタムエージェント: .claude/agents/ 配下で定義した独自エージェント名

制御出力

  • Stop と同様、exit 2 または decision: "block" でサブエージェントを継続させられる
  • stop_hook_active 対策も同じく必要

代表ユースケース

  1. サブエージェント成果物の検証Explore エージェントが調査結果を出した後、JSON スキーマに合致するか検証
  2. リソースクリーンアップ — エージェント用の一時ワークスペースを削除
  3. 完了ログ — サブエージェントの実行時間・トークン使用量を記録
  4. カスタムエージェントの QAreview-agent 完了後に生成物の必須項目チェック
  5. 並列エージェントの完了カウント — 複数サブエージェントが同時動作する場合、全完了を検知してから次の処理へ進む

設定例: Explore エージェントの結果を検証

{
  "hooks": {
    "SubagentStop": [
      {
        "matcher": "Explore",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-explore-output.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

関連記事: Claude Code Agent Teamsの使い方

Notification|デスクトップ通知・外部サービス連携

Notification はClaude が通知を送信するとき(入力待ち・権限確認待ち・完了など)に発火します。ブロックはできませんが、OS通知やSlack連携を自動化するのに最適なイベントです。

matcher の値

matcher値

発火タイミング

permission_prompt

ツール承認待ちでClaude が入力を待っているとき

idle_prompt

作業完了・次のプロンプト待ち

auth_success

認証完了時

elicitation_dialog

MCP elicitationダイアログ表示時

elicitation_complete

MCP elicitation完了時

elicitation_response

MCP elicitationへの応答後

設定例: macOS 通知・Slack Webhook 連携

{
  "hooks": {
    "Notification": [
      {
        "matcher": "idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude が完了しました\" with title \"Claude Code\"'"
          }
        ]
      },
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "http",
            "url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
            "headers": { "Content-Type": "application/json" },
            "body": "{\"text\": \"Claude Code: ツール承認が必要です\"}"
          }
        ]
      }
    ]
  }
}

注意点:

  • Notification はブロック不可exit 2 は stderr 表示のみで Claude Code の動作は継続する
  • 通知スクリプトは非同期的に動く想定で書く(長時間処理を入れると次の操作が遅れる)
  • permission_prompt は非インタラクティブモード(-p)では発火しないことがある

補足イベント|知っておくと差がつく4つ

UserPromptSubmit|ユーザー入力直後

ユーザーがプロンプトを送信した瞬間に発火します。Claude が処理を始める前にコンテキストを注入したり、入力内容を検証できます。

代表用途:

  • 現在時刻・git status・ブランチ名を毎ターン自動注入
  • 機密情報を含むプロンプトの自動ブロック
  • sessionTitle でセッションの自動命名
#!/bin/bash
BRANCH=$(git branch --show-current 2>/dev/null || echo "no-git")
STATUS=$(git status --short 2>/dev/null)
jq -n --arg branch "$BRANCH" --arg status "$STATUS" '{
  hookSpecificOutput: {
    hookEventName: "UserPromptSubmit",
    additionalContext: ("現在ブランチ: " + $branch + "\n変更: " + $status)
  }
}'

SessionStart|セッション開始・再開時

matcher で細かく発火条件を絞れます。

  • startup: 新規セッション
  • resume: --resume / --continue / /resume
  • clear: /clear
  • compact: コンテキスト圧縮後

代表用途: プロジェクトコンテキストの自動注入、CLAUDE_ENV_FILE 経由の環境変数永続化、direnv 連携、圧縮後のルール再注入。

PostToolUseFailure|ツール失敗時

ツール実行が失敗したときに発火し、erroris_interrupt を受け取ります。失敗ログの収集、代替アプローチの提案を additionalContext で注入、外部アラート連携などに使います。

SessionEnd|セッション終了時

終了のきっかけ(clear / resume / logout / prompt_input_exit など)を matcher で判定できます。一時ファイル削除、セッションコスト記録、監査ログへのアーカイブに使います。制御出力は持たずクリーンアップ専用です。

Hooks / Permissions / CLAUDE.md の責任分界

「何をHooksで実装し、何をPermissionsで設定し、何をCLAUDE.mdに書くか」は混乱しやすいポイントです。3つの仕組みは性格が異なります。

手段

性格

向いている用途

向いていない用途

Permissions

静的・宣言的

基本的な許可/拒否ルール。ツール名やパスで単純に制御したい場合

複雑な条件分岐・後処理・外部API連携

CLAUDE.md

ガイダンス的(Claude が読む)

好ましい行動の指示・プロジェクト規約・コーディング規約

「必ず発生する」ことを保証したい処理

Hooks

決定論的・イベント駆動

Permissionsで対応できない複雑なロジック・自動化・ログ・外部連携

単純な許可/拒否(Permissionsで十分)

ベストプラクティス: 基本的なブロックは Permissions の deny ルール、Permissions で対応できない複雑なロジック・後処理・通知は Hooks で実装するのが推奨パターンです。

注意点: Hooks は制限を厳しくはできるが緩和はできない設計です。permissionDecision: "allow" を返しても、設定ファイルの deny ルールはバイパスできません。

関連記事: Claude Code Skills 活用ガイド

バージョン別機能追加履歴

Claude Code Hooks は継続的に機能が拡張されています。以下は確認できた主要なバージョン別の変更履歴です。

バージョン

時期(概算)

主な変更

初期実装

2025年7月

PreToolUse / PostToolUse / Stop / SessionStart / SessionEnd の基本セット

v2.0.28

2025年10月

SubagentStart / SubagentStop 追加、PermissionRequest フック追加

v2.1.0

2026年1月

Hooks をスコープ化(スキル・エージェント・コマンド単位)。大幅強化

v2.1.63

2026年3月前後

HTTP Hooks(外部サーバーへのJSONポスト)追加

v2.1.69

2026年3月前後

InstructionsLoaded フック追加(CLAUDE.md 適用監査)

v2.1.76

2026年3月前後

Elicitation / ElicitationResult フック追加(MCP双方向ダイアログ)

v2.1.78

2026年3月前後

StopFailure フック追加(APIエラー時の自動リカバリー)

v2.1.85

2026年4月前後

if フィールド追加(許可ルール構文でフックの細粒度フィルタリング)

v2.1.141+

2026年5月

27以上のイベントが確認済み。PostToolBatchTaskCreatedTaskCompleted など追加

注意: 正確なリリース日は未公開のため概算です。現行バージョンは claude --version で確認してください。

実務で即使える 10 のレシピ

Hooksを活用した自動化ワークフローのイメージ

1. rm -rf / force push の完全ブロック

最初に入れるべき hook No.1 です。~/.claude/settings.jsonPreToolUse を設定し、以下のスクリプトで危険パターンを exit 2 でブロックします。

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -qE '(^|[; &|])rm -rf( |$)'; then
  echo "rm -rf は禁止されています。--dry-run で確認してください。" >&2
  exit 2
fi
if echo "$COMMAND" | grep -qE 'git push.*--force'; then
  echo "force push は禁止です。--force-with-lease か PR を使ってください。" >&2
  exit 2
fi
exit 0

2. .env / 秘密鍵の読み取り・編集防止

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-secrets.sh",
            "if": "Read(*.env)|Edit(*.env)|Write(*.env)|Read(*.pem)|Read(*credentials*)"
          }
        ]
      }
    ]
  }
}

3. TypeScript 型チェック自動実行

PostToolUsematcher: "Edit|Write" の組み合わせで、if フィールドで *.ts / *.tsx に限定します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tsc-check.sh",
            "timeout": 60,
            "if": "Edit(*.ts)|Edit(*.tsx)|Write(*.ts)|Write(*.tsx)"
          }
        ]
      }
    ]
  }
}

4. ESLint 自動修正

#!/bin/bash
FILE=$(cat | jq -r '.tool_input.file_path')
case "$FILE" in
  *.ts|*.tsx|*.js|*.jsx) npx eslint --fix "$FILE" ;;
esac
exit 0

5. Prettier 自動整形

#!/bin/bash
FILE=$(cat | jq -r '.tool_input.file_path')
npx prettier --write "$FILE" 2>/dev/null
exit 0

6. 現在時刻・git status の自動注入(UserPromptSubmit)

UserPromptSubmit イベントで以下のスクリプトを設定します。プロンプトに「今どこにいるか」の文脈が毎回入るため、Claude の出力精度が体感で改善します。

#!/bin/bash
BRANCH=$(git branch --show-current 2>/dev/null || echo "no-git")
STATUS=$(git status --short 2>/dev/null)
jq -n --arg branch "$BRANCH" --arg status "$STATUS" '{
  hookSpecificOutput: {
    hookEventName: "UserPromptSubmit",
    additionalContext: ("現在ブランチ: " + $branch + "\n変更: " + $status)
  }
}'

7. 作業ログの自動記録(Stop)

#!/bin/bash
INPUT=$(cat)
[ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ] && exit 0
echo "[$(date +%F_%T)] session_id=$(echo "$INPUT" | jq -r '.session_id')" \
  >> "$CLAUDE_PROJECT_DIR/.claude/work-log.jsonl"
exit 0

8. 未コミット変更の警告(Stop)

#!/bin/bash
INPUT=$(cat)
[ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ] && exit 0
cd "$CLAUDE_PROJECT_DIR"
if [ -n "$(git status --porcelain)" ]; then
  echo "未コミット変更があります。コミットするか stash してください。" >&2
  exit 2
fi
exit 0

9. npm install 系コマンドの事前警告(PreToolUse)

依存関係を勝手に追加されないよう、npm install / pnpm add 系に対して ask 判定を返す。

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -qE '^(npm install|pnpm add|yarn add)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "パッケージ追加はレビューが必要です"
    }
  }'
fi
exit 0

10. サブエージェント完了時のリソース解放(SubagentStop)

#!/bin/bash
INPUT=$(cat)
AGENT_NAME=$(echo "$INPUT" | jq -r '.agent_name // empty')
rm -rf "$CLAUDE_PROJECT_DIR/.claude/tmp/${AGENT_NAME}_"*
exit 0

よくある5つの落とし穴と回避策

1. exit 1 でブロックしたつもりになっている

症状: セキュリティゲートを書いたのに破壊的コマンドが実行される。警告だけ出て止まらない。

原因: exit 1 は非ブロッキング扱い。アクションは続行される。

回避策: ポリシー強制目的では必ず exit 2/hooks コマンドで設定済み hook の挙動を確認する。

2. JSON 内で $HOME が展開されないまま放置

症状: hook が呼ばれているはずなのに何も動かない(サイレント失敗)。

原因: settings.json 内の $HOME~ は展開されないケースがある。相対パスも NG。

回避策: "$CLAUDE_PROJECT_DIR" 環境変数を使う、または絶対パスを記述する。/hooks で実パスを検証する。

3. jq 依存を前提にしてしまう

症状: 開発機では動くが CI や他チームメンバーの環境でサイレント失敗する。

原因: jq 未インストール環境での挙動を決めていない。

回避策: スクリプト冒頭で command -v jq をチェックし、未インストール時の動作(安全側は closed = 全ブロック、利便性優先は open = 通過)を明示する。

4. 実行時間が長すぎてフロー全体を遅くする

症状: 50ファイル編集で2.5分以上のオーバーヘッドが発生する。

原因: PostToolUse で全ファイルを対象にした重い型チェックを無条件実行。

回避策:

  • 1 hook あたり 500ms以下を目安にする
  • matcherif で実行条件を狭める(ファイル種別・引数パターンで絞る)
  • 重い処理は差分ファイルだけ検査する
  • 必要なら timeout を明示

5. コンテキスト消費の監視不足

症状: 45分作業したら Claude の応答品質が劇的に低下した。

原因: コンテキストウィンドウが95%に達していることに気付いていない。

回避策: PostToolUse でツール呼び出し数をカウントし、閾値超過時に警告を注入する hook を仕込む。/compact を自動で促す運用にする。

企業導入時のセキュリティ統制

チームや組織に Claude Code を展開する場合、ユーザー任せの hook 設定では統制が効きません。管理者ポリシーを活用します。

企業向けAIツールのセキュリティ統制イメージ

管理者向けの3つの制御

オプション

動作

allowManagedHooksOnly: true

ユーザー/プロジェクト/プラグインの hooks をすべてブロックし、管理者設定だけを有効化

enabledPlugins

特定プラグイン内の hook を強制有効化(allowManagedHooksOnly の例外として)

disableAllHooks: true

階層を尊重しつつ全 hooks を無効化(緊急停止)

HTTP hook の環境変数補間

外部監査サーバーに全ツール呼び出しを POST する場合、HTTP hook のヘッダー値で $VAR / ${VAR} 形式の補間ができますが、allowedEnvVarsに列挙した変数のみ解決され、それ以外は空文字に置換されます。認証トークンの誤流出を防ぐ仕組みです。

{
  "type": "http",
  "url": "https://audit.example.com/hooks",
  "headers": {
    "Authorization": "Bearer ${AUDIT_TOKEN}"
  },
  "allowedEnvVars": ["AUDIT_TOKEN"]
}

セキュリティ上の注意点

  1. プロンプトインジェクション対策: フックが外部入力(ユーザープロンプト、ツール出力)を処理する場合、シェル文字列補間を使わず jq 等で構造化データとして解析する
  2. 認証情報の漏洩防止: CLAUDE_ENV_FILE に機密情報を書き込まない。外部シークレット管理サービスを使用
  3. 権限昇格の防止: permissionDecision: "allow" で不正な操作を許可しない。管理設定の deny ルールは hook の "allow" 返却でもオーバーライドされない

関連記事: Claude Codeのセキュリティと安全な使い方

Hooks 導入ロードマップ|どこから始めるか

いきなり全イベントを設定しようとすると破綻します。以下の順番で段階的に導入するのが安全です。

Step 1: 安全ネット(初日)

  • PreToolUse で rm -rf / git push --force / .env 編集をブロック
  • exit 2 の使い方に慣れる
  • /hooks コマンドで設定反映を確認

Step 2: コンテキスト強化(1週間以内)

  • UserPromptSubmit で git status・ブランチ名・現在時刻を自動注入
  • SessionStart でプロジェクトの README や最近の issue を注入

Step 3: 品質ゲート(2週間以内)

  • PostToolUse で型チェック・Lint・Prettier を自動実行
  • matcherif で対象を絞り、500ms 以下を維持

Step 4: タスク完了制御(必要に応じて)

  • Stop で未コミット・テスト未通過を検知
  • stop_hook_active 対策を必ず入れる

Step 5: チーム展開(組織レベル)

  • .claude/settings.json をコミットしてチーム共通の hook を配布
  • 管理者ポリシーで allowManagedHooksOnly を検討
  • Notification hook で Slack 通知を整備し、長時間実行中の Claude の完了を把握

Claude Code Hooks がおすすめの人・そうでない人

こんな人におすすめ

  • LLM 任せの自動化に不安がある開発者 — 決定論的なガードレールで事故を事前に防ぎたい
  • チームで Claude Code を展開する技術リーダー — メンバー間で一貫した品質・セキュリティ基準を適用したい
  • 既存の Lint / 型チェック / テストを AI 開発フローに組み込みたい人 — PostToolUse でそのまま連携できる
  • 監査ログ要件がある企業 — 全ツール呼び出しを外部サーバーに記録したい
  • OSS / セキュリティ重視プロジェクトのメンテナ.env 誤操作や force push を物理的にブロックしたい

慎重になるべきケース

  • Claude Code 初日・初導入の段階 — まず基本機能を使いこなしてから hook を追加するのが効率的
  • 小さな個人スクリプト用途 — オーバーヘッドの割にメリットが薄い
  • シェルスクリプトに慣れていない人 — JSON 操作や jq 依存の扱いにつまずきやすい
  • agent ハンドラーを確実性が必要な場面で使いたい場合 — 公式が実験的と明記しているため、本番運用前に挙動検証を徹底する

よくある質問(FAQ)

Q1. Hooks の利用に追加料金はかかりますか?

A. Hooks 機能自体は Claude Code に標準同梱で追加料金はかかりません。ただし type: "prompt" / type: "agent" ハンドラーは内部で LLM を呼び出すため、API トークン消費が発生します。type: "command" / type: "http" / type: "mcp_tool" ならトークン消費はありません。

関連記事: Claude Code料金(日本円換算)

Q2. 設定を変更したら再起動が必要ですか?

A. セッション中に設定ファイルを編集すると、ConfigChange イベントが発火し、ファイルウォッチャーが通常は自動で変更を取り込みます。反映されない場合はセッション再起動で強制リロードしてください。

Q3. どのスコープに設定を置くのがベストですか?

A. 目的によります。チームで共有したい最低限のガードレール(rm -rf 防御など)は .claude/settings.json にコミット、個人の実験は .claude/settings.local.json、全プロジェクト共通の個人設定は ~/.claude/settings.json が基本パターンです。

Q4. PermissionRequest hook で自動承認したいのですが、-p 非インタラクティブモードで動きません。

A. 公式仕様として、PermissionRequest hooks は -p 非インタラクティブモードでは発火しません。自動化したい場合は PreToolUse hook で permissionDecision: "allow" を返してください。

Q5. 複数の PreToolUse hook が updatedInput を返したらどうなりますか?

A. 最後に完了したものが勝ちます。並列実行されるため順序は非決定的です。複数 hook で入力を書き換えるのは避け、1つの hook に統合するのが安全です。

Q6. Stop hook で無限ループになりました。どう直せばいいですか?

A. スクリプトの冒頭に以下を追加してください。

INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0
fi

stop_hook_activetrue のとき(hook によって Claude が継続させられた2回目以降)は即 exit 0 で停止を許可します。なお、Stop フックが8回連続ブロックすると Claude Code が強制終了します。

Q7. Hook から / コマンドやツールをトリガーできますか?

A. できません。Hook が Claude に影響を与えられるのは stdout / stderr / 終了コード(HTTP hook はレスポンスボディ)だけです。別のツールを呼びたい場合は additionalContext でその旨を Claude に伝え、Claude 自身にツールを呼ばせる設計にします。

Q8. MCP ツールに対する hook は書けますか?

A. 書けます。matchermcp__<server>__<tool> 形式の正規表現を指定してください。書き込み系 MCP ツールだけを絞るなら mcp__.*__write.* のように書けます。また、type: "mcp_tool" のハンドラーを使えば、hook 自体が既存 MCP ツールを呼び出すことも可能です。

関連記事: Claude Code MCPの使い方

Q9. agent タイプのハンドラーは本番で使えますか?

A. 現時点では、公式ドキュメントが「実験的・変更可能性あり」と明記しています。本番環境への導入前に、十分な検証とフォールバック設計(hook が失敗した場合にブロックするか通過させるかの判断)を行ってください。

Q10. GitHub Actions などの CI 環境でも Hooks は動きますか?

A. 動きます。CI 環境で Claude Code を実行する場合も settings.json を配置すれば hook が発火します。ただし PermissionRequest は非インタラクティブモードでは発火しないため、CI での自動化には PreToolUse を使ってください。

関連記事: Claude Code GitHub Actionsの使い方

まとめ|Hooks は「LLM 任せにしない」ための基盤

Claude Code Hooks は、Claude Code に決定論的なガードレールを敷くための仕組みです。LLM が正しく判断してくれることを祈るのではなく、「この操作は絶対に実行されない」「この場合は必ず型チェックが走る」を設定ファイルで保証できます。

  • 現時点(v2.1.141+)で27以上のイベント・5タイプのハンドラーが利用可能
  • 主要4イベント(PreToolUse / PostToolUse / Stop / SubagentStop)を理解すれば8割の用途はカバーできる
  • ポリシー強制目的では必ず exit 2exit 1 では止まらない)
  • Stop / SubagentStop では stop_hook_active を必ずチェック(無限ループ・強制終了の原因No.1)
  • matcher でツール名、if でツール引数を絞り、1 hook 500ms 以下を目安に
  • Hooks は制限を厳しくできるが緩和はできない設計
  • チーム展開時は .claude/settings.json コミット+管理者ポリシーで統制
  • agent タイプは実験的なため、本番前に挙動を十分検証

まずは「rm -rf ブロック」と「UserPromptSubmit で git status 注入」の2つから始めて、徐々に品質ゲートとログ記録を追加していく段階的導入がおすすめです。

合わせて読みたい関連記事

公式リソース

この記事の著者

AI革命

AI革命

編集部

AI革命株式会社の編集部です。最新のAI技術動向から実践的な導入事例まで、企業のデジタル変革に役立つ情報をお届けしています。豊富な経験と専門知識を活かし、読者の皆様にとって価値のあるコンテンツを制作しています。

AI活用ならAI革命にお任せ。サービスを見てみる
AI Revolution Growth Arrow

AIでビジネスを革新しませんか?

あなたのビジネスにAIがどのような価値をもたらすかをご提案いたします。