コンテンツにスキップ

Claude Code 完全ガイド

Claude Code Hooks実践:AIエージェント自動化編【2025年最新版】

この記事のポイント

  • Claude Code Hooksは初期の4種から11種のイベントタイプに拡張され、セッション全体のライフサイクルをカバーする仕組みへ進化した
  • Hook実行タイプもcommand(シェル)/ prompt(LLM評価)/ agent(サブエージェント)の3種に拡充され、単純なスクリプト実行からコンテキスト認識型の判断まで対応する
  • PreToolUseのツール入力修正機能Plugin hooksMCP連携、Skills/Subagentsフロントマターでのhook定義など、エコシステム全体との統合が大幅に強化された
  • 2025年7月に報告されたCVE-2025-59536を含むセキュリティ脆弱性が修正されており、設定ファイルの取り扱いには引き続き注意が必要

はじめに

Claude Code Hooks完全ガイドで基本概念を学んだ方向けに、本記事では最新仕様に基づく実践的なHooks実装パターンと、AIエージェント自動化の最新テクニックを解説する。

本記事は2025年1月の初版公開以降に追加された新機能・仕様変更を反映した改訂版である。Claude Codeのバージョンアップに伴い、Hooksの仕様は大幅に拡張されている。

Claude Code Hooksとは

Claude Code Hooksは、AIエージェント実行の特定のライフサイクルポイントで自動的にアクションを実行する仕組みである。プロンプトベースの「お願い」とは異なり、条件が満たされれば確実に実行される決定論的な制御レイヤーとして機能する。

CLAUDE.mdやプロンプトでの指示は「モデルが従う可能性が高い」提案であるのに対し、Hooksは「必ず実行される」ガードレールという点が本質的な違いとなる。

11のHookイベントタイプ

初期の4種から大幅に拡張され、現在は以下の11種のイベントタイプが利用可能である。

イベント発火タイミング主な用途
PreToolUseツール実行前コマンドのバリデーション、危険操作ブロック、入力の自動修正
PermissionRequest権限ダイアログ表示時(v2.0.45+)権限の自動承認・拒否
PostToolUseツール実行後コードフォーマット、品質チェック、ログ記録
Notification通知イベント発生時デスクトップ通知、Slack連携
UserPromptSubmitユーザーがプロンプト送信時プロンプトバリデーション、コンテキスト注入
Stopメインエージェント応答完了時タスク完了判定、自動コミット
SubagentStopサブエージェント完了時サブエージェントの完了検証
SubagentStartサブエージェント起動時サブエージェントの監視、コンテキスト注入
PreCompactコンパクト操作実行前トランスクリプトのバックアップ
SessionStartセッション開始時環境変数の設定、開発コンテキストの読み込み
SessionEndセッション終了時クリーンアップ、ログ集計

→ 全15種のイベント一覧はコマンドリファレンスを参照

3つのHook実行タイプ

従来のシェルコマンド実行に加え、LLMベースの評価とサブエージェントによる検証が追加された。

1. Command Hook(シェルコマンド)

従来型のシェルコマンド実行。stdinでイベントのJSON入力を受け取り、exit codeとstdoutで結果を返す。

{
  "type": "command",
  "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
}

2. Prompt Hook(LLM評価)

軽量なClaudeモデル(Haiku)にプロンプトを送信し、approve/blockの判断をJSON形式で返す。Stop/SubagentStopでの「タスクが本当に完了したか」の判定に効果的である。

{
  "type": "prompt",
  "prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete and no errors remain.",
  "timeout": 30
}

3. Agent Hook(サブエージェント)

Read、Grep、Globなどのツールを使用できるサブエージェントを起動し、条件を検証してから判断を返す。より複雑な検証ロジックが必要な場合に有用である。

実装ガイド:基本設定

設定ファイル

Claude Code Hooksは以下の設定ファイルで構成する。

  • ~/.claude/settings.json — ユーザー設定
  • .claude/settings.json — プロジェクト設定(Git管理対象)
  • .claude/settings.local.json — ローカルプロジェクト設定(Git管理対象外)
  • Enterprise managed policy settings — 管理者設定

設定構造

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

matcherはツール名に対する正規表現パターン(大文字・小文字区別あり)である。Edit|Writeのようにパイプで複数指定、Notebook.*のようにワイルドカードも使える。*や空文字列で全ツールにマッチする。

matcherはPreToolUse、PermissionRequest、PostToolUseで使用される。UserPromptSubmit、Stop、SubagentStop等ではmatcherフィールドを省略する。

/hooks インタラクティブマネージャー

Claude Code内で /hooks と入力すると、対話型のhookマネージャーが起動する。設定ファイルを直接編集することなく、hookの確認・追加・削除が可能である。

hookの一時無効化

設定ファイルに "disableAllHooks": true を追加するか、/hooksメニュー内のトグルで全hookを一時的に無効化できる。なお、管理者ポリシーで設定されたhookはこの設定では無効化できない。

実践的な使用例

例1: 自動コード品質チェック(PostToolUse)

ファイル書き込み後に自動でlint/フォーマットを実行する。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/lint-check.sh"
          }
        ]
      }
    ]
  }
}

.claude/hooks/lint-check.shの実装例:

#!/bin/bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')

if [[ "$file_path" == *.py ]]; then
  ruff check "$file_path" && ruff format "$file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
  npx eslint "$file_path" --fix && npx prettier --write "$file_path"
fi

パフォーマンスに関する注意

PostToolUseでフォーマッタを実行するとファイル変更のたびにコンテキストウィンドウを消費する。高頻度の編集が想定される場合は、Stop hookでまとめてフォーマットする方が効率的である。

例2: 危険コマンドのブロック(PreToolUse)

PreToolUse hookでは、exit code 2を返すことでツール実行をブロックできる。さらにJSON出力でpermissionDecisionによる精密な制御も可能である。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous.sh"
          }
        ]
      }
    ]
  }
}

.claude/hooks/block-dangerous.shの実装例:

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

# 危険なコマンドパターンをチェック
if echo "$command" | grep -qE '(rm -rf /|sudo rm|chmod 777|DROP TABLE)'; then
  # JSON出力による精密な制御
  cat <<EOF
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Dangerous command pattern detected: $command"
  }
}
EOF
  exit 0
fi

exit 0

例3: ツール入力の自動修正(PreToolUse updatedInput)

v2.0.10以降、PreToolUse hookがツール実行前に入力パラメータを修正できるようになった。Claudeに透過的にサンドボックス化や自動セキュリティ強制を適用できる。

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

# git pushをdry-runに自動変換
if [[ "$tool_name" == "Bash" ]] && echo "$command" | grep -q "git push"; then
  cat <<EOF
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Auto-converted to dry-run",
    "updatedInput": {
      "command": "${command} --dry-run"
    }
  }
}
EOF
  exit 0
fi

exit 0

例4: セッション開始時のコンテキスト注入(SessionStart)

SessionStart hookで開発コンテキストを自動読み込みし、環境変数を永続化できる。

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-init.sh"
          }
        ]
      }
    ]
  }
}

.claude/hooks/session-init.shの実装例:

#!/bin/bash

# 環境変数の永続化(SessionStart限定のCLAUDE_ENV_FILE)
if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=development' >> "$CLAUDE_ENV_FILE"
fi

# コンテキスト情報をJSON出力で注入
recent_changes=$(git log --oneline -5 2>/dev/null || echo "No git history")
open_issues=$(git log --oneline --all --grep="TODO" -3 2>/dev/null || echo "No issues found")

cat <<EOF
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Recent changes:\n${recent_changes}\n\nOpen items:\n${open_issues}"
  }
}
EOF
exit 0

例5: インテリジェントなStop Hook(Prompt型)

LLMベースのPrompt hookで、タスクの完了状態をコンテキストを踏まえて判断する。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "You are evaluating whether Claude should stop working. Context: $ARGUMENTS\n\nAnalyze and determine if:\n1. All user-requested tasks are complete\n2. Any errors need to be addressed\n3. Tests have been run and pass\n\nRespond with JSON: {\"decision\": \"approve\" or \"block\", \"reason\": \"your explanation\"}",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

高度な活用パターン

1. MCP Toolsとの連携

MCP(Model Context Protocol)経由で提供されるツールに対してもhookを設定できる。MCPツールは mcp__<server>__<tool> の命名パターンに従う。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__memory__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo '[MCP] Memory operation' >> ~/mcp-audit.log"
          }
        ]
      },
      {
        "matcher": "mcp__.*__write.*",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-mcp-write.py"
          }
        ]
      }
    ]
  }
}

2. Plugin Hooks

Pluginがhookを提供し、ユーザーやプロジェクトのhookとシームレスに統合できる。プラグインのhookはプラグイン有効化時に自動マージされ、既存のhookと並列で実行される。

{
  "description": "Automatic code formatting plugin",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

プラグインでは ${CLAUDE_PLUGIN_ROOT} 環境変数でプラグインディレクトリへの絶対パスを参照できる。

3. Skills/Subagentsフロントマターでのhook定義

設定ファイルとは別に、SkillsやSubagentsのYAMLフロントマターに直接hookを定義できる。これらのhookはコンポーネントのライフサイクルにスコープされ、そのコンポーネントがアクティブな間のみ実行される。

---
name: secure-operations
description: Perform operations with security checks
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/security-check.sh"
---

サブエージェントのStopフックは自動的にSubagentStopに変換される。

4. 監査ログとPermissionRequest自動制御

PermissionRequest hook(v2.0.45+)で権限ダイアログへの応答を自動化できる。

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Read",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/auto-approve-reads.sh"
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# .claude/hooks/auto-approve-reads.sh
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')

# ドキュメントファイルの読み取りを自動承認
if [[ "$file_path" == *.md ]] || [[ "$file_path" == *.txt ]] || [[ "$file_path" == *.json ]]; then
  cat <<EOF
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow"
    }
  }
}
EOF
  exit 0
fi

# それ以外はデフォルトの権限フローに委ねる
exit 0

→ 権限設定の詳細は自動承認設定ガイドを参照

5. マルチエージェントオーケストレーション

SubagentStop hookとStop hookを組み合わせることで、サブエージェント間のタスクハンドオフを自動化できる。

{
  "hooks": {
    "SubagentStop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/subagent-handoff.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-pipeline.sh"
          }
        ]
      }
    ]
  }
}

stop_hook_activeフラグをチェックして無限ループを防止することが重要である。

→ Agent Teamsの詳細はAgent Teams導入ガイドを参照

Hook入出力の詳細

入力(stdin JSON)

すべてのhookは以下の共通フィールドを含むJSONをstdinで受け取る。

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

出力制御

2つの方式がある(排他的に選択)。

方式1: Exit Code

  • exit 0 — 成功(stdoutはverboseモードで表示。UserPromptSubmit/SessionStartではコンテキストとして追加)
  • exit 2 — ブロック(stderrがエラーメッセージとしてClaudeに通知。JSON出力は無視)
  • その他 — 非ブロックエラー(stderrがverboseモードで表示)

方式2: JSON出力(exit 0と組み合わせ)

{
  "continue": true,
  "stopReason": "Custom stop message",
  "suppressOutput": false,
  "systemMessage": "Warning shown to user",
  "decision": "block",
  "reason": "Explanation",
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Auto-approved",
    "updatedInput": {},
    "additionalContext": "Extra context for Claude"
  }
}

セキュリティ考慮事項

CVE-2025-59536:設定ファイル経由のRCE脆弱性

2025年7月、Check Point Researchにより .claude/settings.json を通じた任意コード実行の脆弱性が報告された。悪意あるリポジトリのクローン時にhookが自動実行されるリスクがあり、2025年8月にAnthropicが修正を実施している。

セキュリティベストプラクティス

  • hookスクリプト内で入力を必ずバリデーション・サニタイズする
  • シェル変数は常にクォートする("$VAR" を使用、$VARではなく)
  • ファイルパスのパストラバーサル..)をチェックする
  • スクリプトパスには絶対パスまたは$CLAUDE_PROJECT_DIRを使用する
  • .env.git/、鍵ファイルなどの機密ファイルへのアクセスを回避する
  • hookの設定変更はセッション起動時にスナップショットとして取得され、実行中の変更は即座に反映されない(/hooksメニューでのレビューが必要)

Enterprise管理

allowManagedHooksOnly設定により、組織が承認したhookのみに制限できる。管理者ポリシーで設定されたhookは、ユーザー側のdisableAllHooks設定では無効化できない。

トラブルシューティング

デバッグ手順

  1. /hooks で登録状態を確認する
  2. claude --debug で実行詳細を確認する
  3. hookコマンドを手動で実行してテストする
  4. スクリプトの実行権限(chmod +x)を確認する
  5. JSON設定の構文を検証する

よくある問題

hookが発火しない場合

  • matcherのツール名が正確か確認する(大文字・小文字区別あり、Bashであってbashではない)
  • イベント名がPascalCaseか確認する(PreToolUseであってpreToolUseではない)

JSON出力がパースされない場合

  • シェルプロファイル(.bashrc等)の出力がstdoutに混入していないか確認する
  • exit code 0でのみJSON出力が処理される(exit 2ではstderrのみ使用)

タイムアウトの場合

  • デフォルトは60秒。hookごとにtimeoutフィールドで個別設定が可能
{
  "type": "command",
  "command": "your-slow-command",
  "timeout": 120
}

環境変数リファレンス

変数名説明利用可能なhook
$CLAUDE_PROJECT_DIRプロジェクトルートの絶対パス全hook
$CLAUDE_ENV_FILE環境変数永続化用のファイルパスSessionStartのみ
$CLAUDE_CODE_REMOTEリモート(Web)環境で"true"、ローカルCLIでは未設定全hook
${CLAUDE_PLUGIN_ROOT}プラグインディレクトリの絶対パスPlugin hooks

まとめ

Claude Code Hooksは、初期の4イベント・コマンド実行のみの仕組みから、11イベント・3実行タイプを備えたエコシステム統合型の自動化基盤へと進化した。Plugin hooks、MCP連携、Skills/Subagentsフロントマターでの定義など、Claude Codeの各機能との統合が深まっており、開発ワークフロー全体にわたる決定論的な制御が可能になっている。

適切に実装することで「モデルへの期待」から「確実な実行保証」への移行を実現できる。一方で、hookはユーザー権限で任意のコマンドを実行するため、セキュリティへの配慮は不可欠である。

関連記事

関連リソース


この記事は2025年1月18日に初版公開、2026年2月27日に最新仕様に基づき全面改訂しました。最新情報は公式ドキュメントをご確認ください。