Claude Code Hooks とは|全イベント一覧と設定・自動化活用法

Claude Code Hooks とは|全イベント一覧と設定・自動化活用法

Claude Code の Hooks は、セッションのライフサイクル上の特定タイミングで自動実行されるユーザー定義コマンドです。ファイル編集後に自動フォーマット、危険なコマンドの即時ブロック、作業完了時のデスクトップ通知——これらをモデルの「判断」に頼らず、決定論的に 実現できる仕組みです。本記事では Anthropic 公式ドキュメント(Hooks リファレンスフックで自動化するガイド)をもとに、全イベント一覧から設定方法、実践ユースケースまでを解説します。

結論powered by Claude
Claude Code の Hooks は、セッションのライフサイクル上の特定タイミングで自動実行されるユーザー定義コマンドです。ファイル編集後の自動フォーマット、危険なコマンドの即時ブロック、タスク完了時の通知など、モデルの判断に依存せず決定論的に動作する点が最大の特徴です。

Hooks には PreToolUsePostToolUseSessionStartStop など 30 種類近くのイベントが用意されており、ハンドラーも commandhttppromptagent など 5 タイプから選択できます。マッチャーを使えば特定のツールや引数パターンにだけ絞り込んで発火させることも可能です。

設定は ~/.claude/settings.json(全プロジェクト共通)か .claude/settings.json(プロジェクト固有)に JSON で記述します。本記事では Anthropic 公式ドキュメントをもとに、全イベント一覧から設定方法、実践ユースケースまでを解説します。

目次 (13)

Hooks が解決する問題

Claude Code は指示どおりにコードを書いたりコマンドを実行したりしますが、「編集のたびに必ず Prettier を走らせる」「.env への書き込みは例外なく拒否する」といった ルールの強制 はモデルの裁量に依存します。モデルが「今回は不要」と判断すれば実行されません。

Hooks はこの問題を解消します。特定のイベントが発火するたびにシェルコマンドや HTTP エンドポイントを呼び出し、LLM の判断を介さず決定論的にアクションを実行します。Anthropic 公式も「Hooks は特定のアクションが常に発生することを保証する」と明言しています。

全イベント一覧

Hooks は発火タイミングによってカテゴリーに分かれます。代表的なものを以下に示します。

イベント 発火タイミング 主な用途
SessionStart セッション開始・再開時 環境セットアップ、コンテキスト注入
UserPromptSubmit プロンプト送信時 プロンプト検証、追加コンテキスト付与
PreToolUse ツール実行 ツール呼び出しのブロック・承認
PostToolUse ツール実行 Lint/フォーマット、ログ記録
PermissionRequest 許可ダイアログ表示時 自動承認・自動拒否
Stop Claude の応答完了時 タスク完了チェック、通知
Notification Claude が入力待ち状態になったとき デスクトップ通知
SessionEnd セッション終了時 クリーンアップ処理
ConfigChange 設定ファイルが変更されたとき 監査ログ
CwdChanged 作業ディレクトリが変わったとき direnv 統合
FileChanged 監視ファイルが変更されたとき 環境リロード
PreCompact / PostCompact コンテキスト圧縮の前後 コンテキスト再注入

公式の完全一覧には SubagentStartTaskCreatedWorktreeCreate など 30 種類近くのイベントが定義されています。

ハンドラーの 5 タイプ

Hook の実行方式は 5 種類から選べます。

  1. command(最も一般的): シェルコマンドを実行。stdin に JSON が渡される
  2. http: 指定 URL に POST。クラウド関数や社内サービスに委譲できる
  3. mcp_tool: 接続済みの MCP サーバーのツールを呼び出す
  4. prompt: LLM(デフォルトは Haiku)に判断させる。ルールに収まらない条件判断に向く
  5. agent: ファイル読み取りや検索ツールつきのサブ実行環境を起動。複雑な検証に使う

commandhttp は決定論的、promptagent は LLM を介した判断ベースです。

設定ファイルと適用スコープ

Hooks は JSON で記述し、スコープに応じたファイルに配置します。

ファイルパス スコープ リポジトリへのコミット
~/.claude/settings.json 全プロジェクト共通 不可(マシンローカル)
.claude/settings.json 単一プロジェクト 可能
.claude/settings.local.json 単一プロジェクト 不可(gitignored)

基本構造は以下の 3 層です。

{
  "hooks": {
    "PostToolUse": [         // ① イベント名
      {
        "matcher": "Edit|Write",   // ② マッチャー
        "hooks": [           // ③ ハンドラー
          {
            "type": "command",
            "command": "..."
          }
        ]
      }
    ]
  }
}

設定後は CLI で /hooks と入力すると登録済み Hook の一覧を確認できます。

マッチャーで発火対象を絞り込む

matcher フィールドを使うと、全呼び出しではなく特定のツールやイベントだけに Hook を絞れます。

  • "" → 空文字列を指定すると全てのイベントにマッチします(フィルタなし)
  • "Bash" → Bash ツール呼び出しのみ
  • "Edit|Write" → Edit または Write のみ(パイプで OR 結合)
  • "mcp__github__.*" → GitHub MCP サーバーの全ツール(正規表現)
  • "compact" → SessionStart の中でコンパクト再開時のみ

また if フィールドを使うと、ツール名に加えて引数の中身でもフィルタリングできます(Claude Code v2.1.85 以降)。

{
  "if": "Bash(git *)",
  "command": "..."
}

これにより git コマンドのときだけ Hook プロセスが起動し、無関係な Bash 呼び出しで無駄にプロセスが生成されるのを防げます。

実践ユースケース

作業完了時にデスクトップ通知を受け取る

Claude が入力待ちになったとき、ターミナルを監視しなくても通知を受け取れます。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
          }
        ]
      }
    ]
  }
}

matcher に空文字列を指定すると全てのイベントにマッチします。フィルタリングが不要な場合は "" を使います。

macOS は osascript -e 'display notification "..."'、Windows(PowerShell)は MessageBox API を使います。

編集後に Prettier を自動実行する

PostToolUseEdit|Write マッチャーを設定し、編集されたファイルパスを jq で取り出して Prettier に渡します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

Claude が何ファイル編集しても、手動で Prettier を走らせる手間がゼロになります。

機密ファイルへの書き込みをブロックする

.envpackage-lock.json など保護対象のファイルへの編集を、exit 2 で即時拒否します。

#!/bin/bash
# .claude/hooks/protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
    exit 2
  fi
done
exit 0
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

exit 2 で返すと Claude はブロック理由を受け取り、別のアプローチを試みます。

圧縮後にコンテキストを再注入する

コンテキスト圧縮後に重要な規約を Claude に再度伝えられます。

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Reminder: Bun を使う、コミット前に bun test を実行する'"
          }
        ]
      }
    ]
  }
}

stdout に書いたテキストが Claude のコンテキストに追加されます。

direnv で環境変数を自動リロードする

ディレクトリ移動時に direnv で環境変数をリロードし、Bash ツールに即時反映させます。

{
  "hooks": {
    "CwdChanged": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ]
  }
}

CLAUDE_ENV_FILE に書いた内容は、以降の Bash コマンド実行時のプリアンブルとして自動適用されます。

終了コードと JSON 出力

Hook の動作はシェルの終了コードで制御します。

終了コード 動作
0 異議なし。通常の許可フローが継続
2 アクションをブロック。stderr の内容が Claude へのフィードバックになる
その他 非ブロッキングエラー。実行は継続するがトランスクリプトに警告が表示される

exit 2 とエラーメッセージ出力の代わりに、JSON を stdout に書いて exit 0 で返す構造化出力も使えます。

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "grep より rg(ripgrep)を使ってください"
  }
}

permissionDecision"allow" / "deny" / "ask" から選択します。"allow" はインタラクティブな許可プロンプトをスキップしますが、設定ファイルの deny ルールはオーバーライドできません。

デバッグと注意点

Hook が動かないときの確認ポイントをまとめます。

  1. /hooks コマンドで Hook がイベントの下に表示されているか確認する
  2. スクリプトに実行権限があるか確認する(chmod +x)
  3. claude --debug-file /tmp/claude.log でデバッグログを出力し、マッチ状況・終了コード・stderr を確認する
  4. シェルプロファイル(~/.bashrc 等)に無条件の echo が含まれていると stdout が汚染され JSON 解析エラーが発生する。インタラクティブシェル時のみ実行するよう if [[ $- == *i* ]]; then でガードする
  5. Stop Hook が 8 回連続でブロックするとオーバーライドされる。無限ループを防ぐには Hook 入力の stop_hook_active を確認して早期 exit 0 する

Hook は強力な自動化ツールですが、PreToolUse"allow" を返しても管理ポリシーの deny ルールはバイパスできない点に注意が必要です。反対に "deny"bypassPermissions モードでもブロックを実現でき、ポリシー強制に使えます。

詳細な入力/出力スキーマや非同期 Hook については、Anthropic 公式の Hooks リファレンスHooks ガイド を参照してください。

参考になったら ♡
Clauder Navi 編集部
@clauder_navi

Anthropic の Claude / Claude Code を中心に、日本のエンジニア向けに最新動向と実務 を毎日発信。 運営方針 は メディアについて をご覧ください。