40
45

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【完全ガイド】Claude Code Hooks で開発ワークフローを自動化する ── 全14イベント徹底解説

40
Last updated at Posted at 2026-02-09

はじめに

Claude Code を使って開発していると、こんなことを感じたことはありませんか?

  • 「ファイルを編集したら自動でリンターを走らせたい」
  • 「危険なコマンドを実行する前にブロックしたい」
  • 「Claude の応答が終わったら通知音を鳴らしたい」
  • 「本番環境に影響するコマンドだけは絶対に自動承認させたくない」

Claude Code Hooks を使えば、これらすべてが実現できます。

Hooks は、Claude Code のライフサイクル上の特定のポイントで自動的に実行されるユーザー定義の処理です。シェルコマンドの実行はもちろん、LLM による判定やサブエージェントの起動まで、柔軟な自動化が可能です。

本記事では、全14種類のフックイベントを一つ一つ丁寧に解説し、実践的なユースケースも紹介していきます。


目次

  1. Hooks の全体像 ── ライフサイクルを理解する
  2. 設定ファイルの配置場所
  3. 基本構造を理解する ── 3階層のネスト
  4. Exit Code と JSON 出力による制御
  5. 3つのハンドラータイプ
  6. 全14イベント詳細解説
  7. 実践ユースケース集
  8. セキュリティに関する注意点
  9. よくあるハマりポイント
  10. まとめ

Hooks の全体像 ── ライフサイクルを理解する

Hooks を理解するには、まず Claude Code のライフサイクルを把握することが重要です。以下の図で全体の流れを見てみましょう。

この一連の流れの中に14箇所のフックポイントが用意されており、各ポイントに独自の処理を差し込むことができます。


設定ファイルの配置場所

Hooks の設定は JSON ファイルに記述します。用途に応じて複数の配置場所が選べます。

配置場所 スコープ チームで共有 用途
~/.claude/settings.json 全プロジェクト共通 No 個人の好みの設定(通知音など)
.claude/settings.json プロジェクト単位 Yes チーム共通のルール(危険コマンドのブロックなど)
.claude/settings.local.json プロジェクト単位 No 個人的なプロジェクト固有の設定
マネージドポリシー設定 組織全体 Yes エンタープライズ管理者による統制

設定ファイルを直接編集しても即座には反映されません。Claude Code はセッション起動時にスナップショットを取得し、セッション中はそれを使用します。外部から変更した場合は /hooks メニューで確認が必要です。

使い分けのコツ:

  • 通知音やログなど個人的な設定~/.claude/settings.json
  • 危険コマンドのブロックなどチームで統一したいルール.claude/settings.json へ(リポジトリにコミット)
  • API キーを含む設定など共有したくないもの.claude/settings.local.json

基本構造を理解する ── 3階層のネスト

Hooks の設定は3階層のネスト構造になっています。

{
  "hooks": {
    "PreToolUse": [          //  1層: Hook Event(いつ?)
      {
        "matcher": "Bash",   //  2層: Matcher Group(どの条件で?)
        "hooks": [
          {                  //  3層: Hook Handler(何をする?)
            "type": "command",
            "command": "echo 'Bashが実行されようとしています'",
            "timeout": 600
          }
        ]
      }
    ]
  }
}
役割
第1層 いつ 発火するか PreToolUse(ツール実行前)
第2層 どの条件 で発火するか "Bash" のときだけ
第3層 何を 実行するか シェルコマンド、プロンプト、エージェント

Matcher は正規表現で指定できるので、"Edit|Write" のように複数のツールにマッチさせたり、"mcp__.*" で全 MCP ツールにマッチさせたりできます。


Exit Code と JSON 出力による制御

Hooks の戻り値(Exit Code)によって、Claude Code の動作を制御できます。

Exit Code の意味

Exit Code 意味 動作
0 成功 stdout の JSON を解析し、アクション続行
2 ブロッキングエラー 対象のアクションをブロック(対応イベントのみ)
それ以外 非ブロッキングエラー verbose モードでログ表示、実行は続行

Exit Code 2 が特に重要です。これを使うと「そのアクションを止める」ことができます。ただし、すべてのイベントでブロックできるわけではありません。

ブロック可能なイベント Exit 2 の効果
PreToolUse ツール呼び出しをブロック
PermissionRequest 権限を拒否
UserPromptSubmit プロンプト処理をブロック
Stop Claude の停止を防ぎ、続行させる
SubagentStop サブエージェントの停止を防ぐ
TaskCompleted タスク完了マークを防ぐ

JSON 出力で細かく制御する

Exit 0 で stdout に JSON を出力すると、さらに細かい制御が可能です。

{
  "continue": true,           // false にすると Claude が完全停止
  "stopReason": "処理を中断しました",  // 停止時のメッセージ
  "systemMessage": "注意: 本番DBへの接続を検出しました"  // 警告メッセージ
}

3つのハンドラータイプ

Hooks では、処理の実行方法を3種類から選べます。

1. Command Hook ── シェルコマンドを実行

最もシンプルで一般的なタイプです。任意のシェルコマンドを実行できます。

{
  "type": "command",
  "command": "npm run lint",
  "timeout": 600,
  "statusMessage": "リント実行中...",
  "async": false
}
フィールド 必須 説明
command Yes 実行するシェルコマンド
timeout No タイムアウト秒数(デフォルト: 600秒)
statusMessage No 実行中にスピナーに表示されるメッセージ
async No true でバックグラウンド実行

2. Prompt Hook ── LLM に判断させる

Claude モデルにプロンプトを送り、Yes/No の判定を得ます。シェルスクリプトでは判断しにくい「意味的な」チェックに向いています。

{
  "type": "prompt",
  "prompt": "以下のコード変更がセキュリティ上問題ないか判断してください: $ARGUMENTS",
  "timeout": 30
}

$ARGUMENTS にはフックの入力 JSON が展開されるので、ツール名や入力パラメータを参照して判断させることができます。

3. Agent Hook ── サブエージェントで検証

Read / Grep / Glob などのツールを使ってファイルを調査し、判定を返すサブエージェントを起動します。

{
  "type": "agent",
  "prompt": "テストファイルが存在し、カバレッジが80%以上あるか確認してください",
  "timeout": 60
}

使い分けの目安:

タイプ 向いているケース
Command 明確なルールに基づくチェック(コマンド名の検証、ファイルの存在確認など)
Prompt 文脈や意味を考慮した判断(コード変更の安全性チェックなど)
Agent ファイルを調査してから判断する必要があるケース(テストカバレッジの確認など)

全14イベント詳細解説

ここからが本記事の本題です。全14種類のフックイベントを一つ一つ解説していきます。


1. SessionStart ── セッション開始

🎯 一言で言うと: セッションが始まるときに環境を整える

いつ発火するか

  • 新規セッション開始時
  • 既存セッションの再開時
  • コンテキストクリア後
  • コンパクション後の再開時

Matcher で起動タイプを絞れる

Matcher値 意味
startup 新規セッション開始
resume 既存セッションの再開
clear コンテキストクリア後
compact コンパクション後

入力フィールド

共通フィールド(session_id, cwd, permission_mode 等)に加えて:

フィールド 説明
type 開始タイプ(startup / resume / clear / compact

ブロック: 不可

セッション開始自体を止めることはできません。

特別な機能: 環境変数の永続化

JSON 出力で hookSpecificOutput.env を返すと、セッション全体にわたる環境変数を設定できます。

{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "env": {
      "NODE_ENV": "development",
      "DATABASE_URL": "postgresql://localhost:5432/dev"
    }
  }
}

stdout がコンテキストに追加される

SessionStart は特別で、Exit 0 時の stdout の内容がClaude が見えるコンテキストとして追加されます。「このプロジェクトでは常にこのルールに従ってください」のようなガイダンスを注入するのに便利です。

設定例

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "echo '現在のNode.jsバージョン: '$(node -v)'. このプロジェクトではTypeScriptを使用してください。'"
          }
        ]
      }
    ]
  }
}

2. UserPromptSubmit ── ユーザー入力の検証

🎯 一言で言うと: ユーザーのプロンプトが処理される前にチェックする

いつ発火するか

ユーザーがテキストを入力して送信した直後、Claude のモデル処理が始まる

Matcher: なし(常に発火)

このイベントには Matcher を設定できません。毎回必ず発火します。

入力フィールド

フィールド 説明
prompt ユーザーが送信したプロンプトテキスト

ブロック: 可能

Exit 2 でプロンプトの処理をブロックし、プロンプト自体を消去します。機密情報の流出防止などに有用です。

stdout がコンテキストに追加される

SessionStart と同様に、stdout が Claude のコンテキストに追加されます。プロンプトに補足情報を付与するのに使えます。

設定例: プロンプトのコンテキスト補強

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo '補足: 現在のブランチは '$(git branch --show-current)' です。直近のコミット: '$(git log --oneline -1)"
          }
        ]
      }
    ]
  }
}

この設定により、ユーザーが何を入力しても、Claude には「現在のブランチ名」と「直近のコミット」の情報が自動的に追加されます。


3. PreToolUse ── ツール実行前の制御

🎯 一言で言うと: ツールが実行される前に許可・拒否・変更ができる、最も強力なフック

いつ発火するか

Claude がツール(Bash, Edit, Write, Read 等)を呼び出す直前

Matcher: ツール名(正規表現)

Matcher例 マッチ対象
Bash Bash コマンドの実行
Edit|Write ファイルの編集または書き込み
Notebook.* Notebook 系ツール全般
mcp__github__.* GitHub MCP サーバーの全ツール

入力フィールド

フィールド 説明
tool_name ツール名(例: "Bash", "Edit"
tool_input ツールに渡される入力パラメータ

ブロック: 可能

豊富な Decision Control

PreToolUse は最も細かい制御ができるイベントです。

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "本番データベースへの直接アクセスは禁止されています"
  }
}
permissionDecision 効果
"allow" ツール実行を許可(権限プロンプトをスキップ)
"deny" ツール実行を拒否
"ask" ユーザーに権限確認を表示

さらに、updatedInput でツール入力を書き換えたり、addedContext で Claude に追加情報を注入したりもできます。

設定例: 危険なコマンドをブロック

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); case \"$CMD\" in *'rm -rf'*|*'drop table'*|*'DROP TABLE'*) echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"危険なコマンドです\"}}' && exit 0;; esac"
          }
        ]
      }
    ]
  }
}

4. PermissionRequest ── 権限確認の自動化

🎯 一言で言うと: 「このツールを実行していいですか?」のダイアログを自動で判定する

いつ発火するか

Claude がツールを実行しようとして権限確認が必要になったとき、ダイアログが表示される直前

Matcher: ツール名

PreToolUse と同じツール名でフィルタ可能。

ブロック: 可能

Exit 2 で権限を拒否します。

Decision Control

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "applyPermissionRule": "always"
    }
  }
}

applyPermissionRule: "always" を指定すると、同じパターンの次回以降の権限確認を永続的にスキップするルールが追加されます。

PreToolUse との違い

比較 PreToolUse PermissionRequest
発火タイミング ツール実行前(常に) 権限が必要なときだけ
主な用途 ツール実行のブロック・変更 権限の自動許可・拒否
allow の意味 権限プロンプトをスキップ 権限を自動許可

設定例: 安全なコマンドを自動承認

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); case \"$CMD\" in 'npm test'|'npm run lint'|'npm run build') echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}';; esac"
          }
        ]
      }
    ]
  }
}

5. PostToolUse ── ツール実行後の後処理

🎯 一言で言うと: ツールが正常に実行された後にフォーマッタやリンターを走らせる

いつ発火するか

ツールが成功した直後。

Matcher: ツール名

入力フィールド

フィールド 説明
tool_name ツール名
tool_input ツール入力パラメータ
tool_result ツール実行結果

ブロック: 不可

ツールは既に実行済みなので、ブロックはできません。ただし decision: "block" を返すと、Claude に対して「問題があった」というフィードバックを送れます。

設定例: ファイル編集後にフォーマッタを自動実行

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); FILE=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path'); if [ -n \"$FILE\" ] && echo \"$FILE\" | grep -qE '\\.(ts|tsx|js|jsx)$'; then npx prettier --write \"$FILE\" 2>/dev/null; fi",
            "statusMessage": "コードフォーマット中..."
          }
        ]
      }
    ]
  }
}

6. PostToolUseFailure ── ツール失敗時のハンドリング

🎯 一言で言うと: ツールがエラーで失敗した後にログ記録やカスタムフィードバックを行う

いつ発火するか

ツール実行がエラーで終了した直後。

入力フィールド

フィールド 説明
tool_name ツール名
tool_input ツール入力パラメータ
tool_error エラー情報

ブロック: 不可

ツールは既に失敗済みです。decision: "block" で Claude にフィードバックを送れます。

設定例: ツール失敗をログに記録

{
  "hooks": {
    "PostToolUseFailure": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) | $(echo \"$INPUT\" | jq -r '.tool_name') | $(echo \"$INPUT\" | jq -r '.tool_error' | head -c 200)\" >> ~/.claude/tool-failures.log"
          }
        ]
      }
    ]
  }
}

7. Notification ── 通知イベント

🎯 一言で言うと: Claude Code の UI イベント(権限確認ダイアログ表示など)に反応する

いつ発火するか

権限確認ダイアログ、アイドル状態プロンプト、認証成功などの UI イベント発生時。

よくある誤解: 「Claude の応答完了」で Notification は発火しません。応答完了で発火するのは Stop イベントです。

Matcher: 通知タイプ

Matcher値 意味
permission_prompt 権限確認ダイアログが表示された
idle_prompt アイドル状態のプロンプト
auth_success 認証が成功した

ブロック: 不可

設定例: 権限確認が表示されたら音で知らせる

バックグラウンドで Claude を走らせているとき、権限確認を見逃さないための設定です。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Ping.aiff"
          }
        ]
      }
    ]
  }
}

afplay は macOS 専用のコマンドです。Linux の場合は paplayaplay を使ってください。


8. SubagentStart ── サブエージェント起動

🎯 一言で言うと: サブエージェントが生成されたことを検知する

いつ発火するか

Claude がサブエージェント(タスク実行のための子プロセス)を起動した直後。

Matcher: エージェントタイプ

Matcher値の例 意味
Bash Bash エージェント
Explore 探索エージェント
Plan 計画エージェント

入力フィールド

フィールド 説明
agent_type エージェントタイプ
agent_id エージェント識別子

ブロック: 不可

設定例: サブエージェントの活動をログ

{
  "hooks": {
    "SubagentStart": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); echo \"[START] $(date +%H:%M:%S) $(echo \"$INPUT\" | jq -r '.agent_type') ($(echo \"$INPUT\" | jq -r '.agent_id'))\" >> ~/.claude/agent-activity.log"
          }
        ]
      }
    ]
  }
}

9. SubagentStop ── サブエージェント完了

🎯 一言で言うと: サブエージェントの完了を検知し、必要なら続行させる

いつ発火するか

サブエージェントの処理が完了した時点。

ブロック: 可能

Exit 2 でサブエージェントの停止を防ぎ、処理を続行させることができます。

{
  "decision": "block",
  "reason": "まだタスクが完了していません。追加の検証を行ってください。"
}

Skills や Agents のフロントマターで Stop フックを定義すると、自動的に SubagentStop に変換されます。


10. Stop ── Claude の応答完了

🎯 一言で言うと: Claude が応答を終えたときに品質チェックや通知を行う、非常に実用的なフック

いつ発火するか

Claude のエージェントループが終了し、ユーザーの次の入力を待つ直前

Matcher: なし(常に発火)

入力フィールド

フィールド 説明
stop_reason 停止理由
stop_ts 停止タイムスタンプ

ブロック: 可能 ← ここが面白い!

Exit 2 で Claude の停止を防ぎ、応答を続行させることができます。これにより「テストが通るまで止まるな」のような強力な制御が実現できます。

設定例: 応答完了時に通知音

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff"
          }
        ]
      }
    ]
  }
}

設定例: テストが通るまで停止させない

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm test 2>&1 || (echo 'テストが失敗しています。修正を続けてください。' >&2 && exit 2)",
            "timeout": 120,
            "statusMessage": "テスト実行中..."
          }
        ]
      }
    ]
  }
}

11. TeammateIdle ── チームメイトのアイドル制御

🎯 一言で言うと: Agent Teams のチームメイトがアイドルになるのを防ぐ

いつ発火するか

エージェントチームのチームメイトが作業を終え、アイドル状態に遷移しようとするとき。

ブロック: 可能

Exit 2 でアイドル化を防ぎ、stderr のフィードバックをチームメイトに渡して作業を続行させます。

Agent Teams 機能を使用していない場合、このイベントは発火しません。


12. TaskCompleted ── タスク完了の品質ゲート

🎯 一言で言うと: タスクが「完了」とマークされる前に品質チェックを行う

いつ発火するか

タスクが完了状態に遷移する直前。

ブロック: 可能

Exit 2 でタスク完了のマークを防ぎます。CI/CD のゲートチェックのようなイメージです。

設定例: テスト未通過のタスク完了を防ぐ

{
  "hooks": {
    "TaskCompleted": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm test 2>&1 || (echo 'テストが失敗しているため、タスクを完了できません' >&2 && exit 2)",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

13. PreCompact ── コンテキスト圧縮前

🎯 一言で言うと: コンテキストが圧縮される前にログや保存処理を行う

いつ発火するか

コンテキストが長くなりすぎて圧縮が必要になったとき、または手動でコンパクションが実行されたとき。

Matcher: トリガー方法

Matcher値 意味
manual ユーザーが手動で実行
auto 自動的にトリガー

ブロック: 不可

設定例

{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"[$(date)] Auto-compaction triggered\" >> ~/.claude/compact.log"
          }
        ]
      }
    ]
  }
}

14. SessionEnd ── セッション終了

🎯 一言で言うと: セッション終了時のクリーンアップやログ書き込みを行う

いつ発火するか

セッションが何らかの理由で終了する時点。

Matcher: 終了理由

Matcher値 意味
clear コンテキストがクリアされた
logout ログアウト
prompt_input_exit プロンプト入力から終了
other その他の理由

ブロック: 不可

セッション終了は止められません。

設定例: セッション統計の記録

{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); echo \"Session $(echo \"$INPUT\" | jq -r '.session_id') ended ($(echo \"$INPUT\" | jq -r '.reason')) at $(date)\" >> ~/.claude/session-history.log"
          }
        ]
      }
    ]
  }
}

実践ユースケース集

ここでは、実際の開発で役立つユースケースをいくつか紹介します。

ユースケース 1: 開発環境の自動セットアップ

セッション開始時に必要な環境情報を Claude に渡し、環境変数も設定する。

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"env\":{\"NODE_ENV\":\"development\",\"DB_HOST\":\"localhost\"}}}' && echo 'プロジェクト: '$(basename $(pwd))' | Node: '$(node -v)' | ブランチ: '$(git branch --show-current 2>/dev/null || echo 'N/A')"
          }
        ]
      }
    ]
  }
}

ユースケース 2: 包括的なファイル編集ガードレール

ファイル編集前に対象を検証し、編集後にフォーマッタとリンターを自動実行。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); FILE=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path'); if echo \"$FILE\" | grep -qE '(node_modules|dist|build|.min.)'; then echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"生成物・依存ファイルの編集は禁止されています\"}}'; fi"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); FILE=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path'); if echo \"$FILE\" | grep -qE '\\.(ts|tsx|js|jsx)$'; then npx prettier --write \"$FILE\" 2>/dev/null && npx eslint --fix \"$FILE\" 2>/dev/null; fi",
            "statusMessage": "フォーマット & リント実行中..."
          }
        ]
      }
    ]
  }
}

ユースケース 3: AI による品質ゲート

Claude の応答完了時に、別の LLM がコード品質を自動チェック。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "直前の変更内容を確認し、以下を検証してください:\n1. テストファイルが存在するか\n2. TypeScriptの型エラーがないか\n3. セキュリティ上の問題がないか\n問題があればblockしてください。",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

ユースケース 4: Slack 通知連携

長時間のタスクが完了したら Slack に通知を送る。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s -X POST -H 'Content-Type: application/json' -d '{\"text\":\"Claude Codeの処理が完了しました\"}' $SLACK_WEBHOOK_URL",
            "async": true
          }
        ]
      }
    ]
  }
}

ユースケース 5: 機密情報の流出防止

プロンプトに API キーやパスワードが含まれていないかチェック。

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); PROMPT=$(echo \"$INPUT\" | jq -r '.prompt'); if echo \"$PROMPT\" | grep -qiE '(api[_-]?key|secret|password|token)\\s*[:=]\\s*[\"'\\''\\w]'; then echo '{\"decision\":\"block\",\"reason\":\"機密情報が含まれている可能性があります。プロンプトから除去してください。\"}'; fi"
          }
        ]
      }
    ]
  }
}

ユースケース 6: git push の保護

main ブランチへの force push を絶対に防ぐ。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); if echo \"$CMD\" | grep -qE 'git\\s+push.*--force.*main|git\\s+push.*-f.*main'; then echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"mainブランチへのforce pushは禁止されています\"}}'; fi"
          }
        ]
      }
    ]
  }
}

セキュリティに関する注意点

Hooks は強力な機能ですが、セキュリティにも配慮が必要です。

  1. フックはユーザー権限で実行される ── フックが実行できることは、あなたのターミナルで実行できることと同じ
  2. 外部からの設定変更に注意 ── セッション起動後にフック設定が外部から変更された場合、Claude Code は警告を表示する
  3. stdout に機密情報を出力しない ── verbose モードで表示される可能性がある
  4. disableAllHooks: true で全フックを一時的に無効化できる
  5. エンタープライズ管理者allowManagedHooksOnly でユーザー定義フックをブロック可能

よくあるハマりポイント

存在しないイベント名

以下のイベント名は存在しません。設定すると Invalid key in record エラーになります。

❌ 間違い ✅ 正しい代替
PostResponse Stop(応答完了時に使う)
PreResponse UserPromptSubmit(プロンプト処理前に使う)
OnError PostToolUseFailure(ツール失敗後に使う)

設定が反映されない

設定ファイルを直接編集した場合、セッションの再起動が必要です。もしくは /hooks メニューで確認してください。

shell profile による JSON パースエラー

.bashrc.zshrcecho している場合、フックの stdout に余計なテキストが混入して JSON パースが失敗することがあります。フックスクリプトでは #!/bin/bash --norc を使うか、不要な出力がないか確認してください。


まとめ

Claude Code Hooks は、開発ワークフローを大幅にカスタマイズできる強力な仕組みです。

やりたいこと 使うイベント
環境の初期化 SessionStart
プロンプトの検証・補強 UserPromptSubmit
危険なコマンドのブロック PreToolUse
権限確認の自動化 PermissionRequest
ファイル編集後の自動フォーマット PostToolUse
エラーのログ記録 PostToolUseFailure
バックグラウンド動作中の通知 Notification
サブエージェントの監視 SubagentStart / SubagentStop
応答完了時の品質チェック Stop
タスクの品質ゲート TaskCompleted
セッション統計の記録 SessionEnd

まずは Stop イベントで応答完了時の通知音から始めてみることをおすすめします。たった数行の設定で、Claude Code の体験が大きく変わるはずです。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff"
          }
        ]
      }
    ]
  }
}

この設定を ~/.claude/settings.json に追加するだけ。Claude がバックグラウンドで作業を終えたら、すぐに気づけるようになります。

ぜひ自分の開発ワークフローに合った Hooks を見つけて、Claude Code をさらに便利にカスタマイズしてみてください。


関連記事

本記事の知識を使って、リアルタイムダッシュボードを実際に作る続編を書きました。

40
45
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
45

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?