1
1

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完全ガイド — 開発ワークフローを自動化する18イベントの活用法

1
Last updated at Posted at 2026-03-10

Claude Code Hooksによる開発ワークフロー自動化の全体像

はじめに

Claude Code には Hooks と呼ばれる仕組みがあります。これは、Claude Code のライフサイクル上の特定タイミングでシェルコマンドや HTTP リクエスト、LLM プロンプトを自動実行できる機能です。

Hooks を使うと、次のような自動化が実現できます。

  • ファイル編集後に自動でコードフォーマッター(Prettier など)を実行する
  • .envpackage-lock.json など保護すべきファイルへの書き込みをブロックする
  • Claude が入力待ちになったときにデスクトップ通知や Slack 通知を送る
  • コンテキスト圧縮(コンパクション)後にプロジェクト規則を自動注入する
  • すべての Bash コマンドをログファイルに記録する

公式ドキュメント(Automate workflows with hooks)をもとに、実際の設定方法から実践的なユースケースまでを解説します。

この記事で学べること

  • Claude Code Hooks の仕組みと 18 種類のイベント一覧
  • settings.json への設定方法とスコープ(グローバル/プロジェクト)
  • 自動フォーマット・ファイル保護・通知など実践的なレシピ
  • プロンプト型・エージェント型・HTTP 型の高度なフック

対象読者

  • Claude Code を日常的に使っているエンジニア
  • AI コーディングツールの自動化に興味がある方
  • CI/CD と同様にローカル開発にもガードレールを設けたい方

前提環境

  • Claude Code(最新バージョン推奨)
  • macOS / Linux / Windows(PowerShell)

TL;DR

  • Hooks はライフサイクルイベントにシェルコマンドを紐付ける仕組みで、18 種類のイベントをサポート
  • ~/.claude/settings.json(グローバル)または .claude/settings.json(プロジェクト)に JSON で設定
  • 主要イベント: PreToolUse(ブロック可)、PostToolUse(後処理)、Notification(通知)、SessionStart(コンテキスト注入)
  • フックタイプは command(シェル)、prompt(LLM)、agent(サブエージェント)、http の 4 種類

Claude Code Hooks の仕組み

Claude Code Hooksのライフサイクルとイベント発火タイミングの全体像

Hooks は Claude Code のエージェントループ上の特定ポイントで発火します。イベントが発火すると、Claude Code はイベント固有の JSON コンテキストをフックハンドラーに渡します。

フックの基本動作

Claude Code セッション
  │
  ├─ SessionStart   → フック発火(コンテキスト注入)
  │
  ├─ UserPromptSubmit → フック発火(プロンプト前処理)
  │
  ├─ PreToolUse     → フック発火(ブロック可能)
  │     │
  │     ▼ ツール実行
  │
  ├─ PostToolUse    → フック発火(後処理)
  │
  ├─ Stop           → フック発火(完了検証)
  │
  └─ SessionEnd     → フック発火(クリーンアップ)

フックハンドラー(シェルスクリプト等)は stdin で JSON を受け取り、stdout/stderr への出力と終了コードで Claude Code に応答します。

終了コード 動作
0 処理を続行。SessionStart / UserPromptSubmit では stdout の内容が Claude のコンテキストに追加される
2 アクションをブロック。stderr の内容が Claude へのフィードバックとして渡される
その他 処理を続行。stderr はログに記録される(Claude には渡されない)

全 18 イベント一覧

イベント 発火タイミング
SessionStart セッション開始または再開時
UserPromptSubmit プロンプト送信後、Claude が処理する前
PreToolUse ツール呼び出し前(ブロック可)
PermissionRequest 権限ダイアログ表示時
PostToolUse ツール呼び出し成功後
PostToolUseFailure ツール呼び出し失敗後
Notification Claude Code が通知を送信するとき
SubagentStart サブエージェント起動時
SubagentStop サブエージェント終了時
Stop Claude が応答を完了したとき
TeammateIdle Agent Team のチームメートがアイドル状態になるとき
TaskCompleted タスクが完了としてマークされるとき
InstructionsLoaded CLAUDE.md やルールファイルがロードされるとき
ConfigChange セッション中に設定ファイルが変更されたとき
WorktreeCreate ワークツリー作成時
WorktreeRemove ワークツリー削除時
PreCompact コンテキスト圧縮の直前
SessionEnd セッション終了時

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

フックの設定場所でスコープが決まります。

設定ファイル スコープ 共有可否
~/.claude/settings.json 全プロジェクト共通 不可(マシンローカル)
.claude/settings.json プロジェクト単位 可(リポジトリにコミット可能)
.claude/settings.local.json プロジェクト単位 不可(gitignore 推奨)
プラグイン hooks/hooks.json プラグイン有効時 可(プラグインに同梱)

Claude Code が実行中のとき、設定ファイルを直接編集しても即時反映されません。/hooks メニューで確認するか、セッションを再起動してください。/hooks メニューから追加したフックは即時反映されます。

設定の基本構造

{
  "hooks": {
    "イベント名": [
      {
        "matcher": "マッチャーパターン(正規表現)",
        "hooks": [
          {
            "type": "command",
            "command": "実行するシェルコマンド"
          }
        ]
      }
    ]
  }
}

matcher はイベントによってフィルタリング対象が異なります。

イベント マッチャーの対象
PreToolUse, PostToolUse, PermissionRequest ツール名 Bash, Edit|Write, mcp__.*
SessionStart セッション開始理由 startup, resume, compact
SessionEnd セッション終了理由 clear, logout
Notification 通知タイプ permission_prompt, idle_prompt
PreCompact 圧縮トリガー manual, auto

マッチャーを空文字列 "" にすると、すべての発火条件に対してフックが実行されます。


実践レシピ集

PostToolUse/PreToolUse/Notificationそれぞれの典型的なユースケースフロー

レシピ 1: デスクトップ通知(macOS)

Claude が入力待ちになったときにデスクトップ通知を受け取ります。別の作業をしながら Claude に長時間タスクを任せるときに便利です。

~/.claude/settings.json に追加:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code が入力を待っています\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Linux では notify-send、Windows では PowerShell の MessageBox を使います。

レシピ 2: ファイル編集後に自動フォーマット

Claude がファイルを編集するたびに Prettier を自動実行します。コードスタイルの一貫性が保たれます。

.claude/settings.json に追加(プロジェクト単位):

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

jq で stdin の JSON から tool_input.file_path を抽出し、Prettier に渡しています。jq のインストールは brew install jq(macOS)または apt-get install jq(Debian/Ubuntu)。

レシピ 3: 保護ファイルへの書き込みをブロック

.envpackage-lock.json.git/ 配下への書き込みを防止します。誤った編集を事前に止められます。

まず .claude/hooks/protect-files.sh を作成:

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

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH is a protected file" >&2
    exit 2
  fi
done

exit 0

実行権限を付与:

chmod +x .claude/hooks/protect-files.sh

.claude/settings.json に登録:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

exit 2 で返すと、Claude は stderr のメッセージを受け取り、別のアプローチを検討します。

レシピ 4: Bash コマンドの全履歴をログに記録

Claude が実行したすべての Bash コマンドをファイルに記録します。監査やデバッグに活用できます。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '[now | todate, .tool_input.command] | @tsv' >> ~/.claude/command-log.txt"
          }
        ]
      }
    ]
  }
}

タイムスタンプ付きで ~/.claude/command-log.txt に追記されます。

レシピ 5: コンパクション後にプロジェクト規則を再注入

Claude のコンテキストウィンドウが満杯になると、コンパクション(要約)が行われます。この際、重要なプロジェクト規則が失われることがあります。SessionStartcompact マッチャーを使うと、圧縮後に自動でコンテキストを再注入できます。

.claude/settings.json に追加:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'リマインダー: パッケージマネージャーは npm ではなく Bun を使うこと。コミット前に bun test を実行すること。現在のスプリント: 認証リファクタリング。'"
          }
        ]
      }
    ]
  }
}

stdout への出力が Claude のコンテキストに追加されます。動的な情報(直近のコミット一覧など)を注入することも可能です。

{
  "command": "git log --oneline -5"
}

レシピ 6: 設定変更の監査ログ

設定ファイルが変更されるたびに監査ログに記録します。コンプライアンス要件がある環境で活用できます。

{
  "hooks": {
    "ConfigChange": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
          }
        ]
      }
    ]
  }
}

高度なフックタイプ

プロンプト型フック(type: "prompt"

確定的なルールではなく判断が必要な場合に、LLM(デフォルト: Haiku)にフックの処理を委ねます。

モデルは "ok": true(続行)または "ok": false(ブロック)を JSON で返します。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "要求されたすべてのタスクが完了しているか確認してください。完了していない場合は {\"ok\": false, \"reason\": \"残作業の内容\"} を返してください。"
          }
        ]
      }
    ]
  }
}

Stop イベントで使うと、タスクが本当に完了しているか LLM に判断させて、不完全な場合は作業を継続させることができます。

エージェント型フック(type: "agent"

ファイルの読み取りやコマンド実行が必要な検証には、サブエージェントを起動するエージェント型フックを使います。デフォルトタイムアウト 60 秒、最大 50 ターンのツール利用が可能です。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "すべてのユニットテストが通過することを確認してください。テストスイートを実行して結果を確認してください。",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

「プロンプト型はフック入力データだけで判断できる場合、エージェント型はコードベースの実際の状態を確認する必要がある場合」という使い分けが推奨されています。

HTTP 型フック(type: "http"

チームで共有する監査サービスや外部 Webhook にイベントデータを送信します。

{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/hooks/tool-use",
            "headers": {
              "Authorization": "Bearer $MY_TOKEN"
            },
            "allowedEnvVars": ["MY_TOKEN"]
          }
        ]
      }
    ]
  }
}

ヘッダー値には $VAR_NAME 形式で環境変数を埋め込めます。allowedEnvVars に列挙された変数のみ解決されます。

HTTP フックは /hooks インタラクティブメニューからは設定できません。設定ファイルを直接編集してください。


フックの設定手順

/hooks メニューを使う方法(推奨)

  1. Claude Code CLI で /hooks と入力
  2. フックを設定したいイベントを選択(例: Notification
  3. マッチャーを設定(すべてに適用する場合は *
  4. + Add new hook… を選択してコマンドを入力
  5. 保存先を選択(User settings でグローバル、Project settings でプロジェクト単位)

メニューから追加したフックは即時反映されます。

設定ファイルを直接編集する方法

  1. ~/.claude/settings.json または .claude/settings.json を開く
  2. hooks キーに上記の JSON 形式で設定を追加
  3. Claude Code を再起動するか、/hooks メニューを開いて変更を反映させる

トラブルシューティング

フックが発火しない

  • /hooks メニューでフックが正しいイベントの下に登録されているか確認する
  • マッチャーはツール名と大文字小文字を区別する(Edit は正しいが edit は不正)
  • PermissionRequest フックは非インタラクティブモード(-p)では発火しない。PreToolUse を代わりに使う

JSON パースエラーが発生する

~/.zshrc~/.bashrc に無条件の echo 文がある場合、その出力がフックの JSON 出力に混入して解析エラーになります。インタラクティブシェルのみで実行されるよう条件分岐を追加してください:

# ~/.zshrc
if [[ $- == *i* ]]; then
  echo "Shell ready"
fi

Stop フックが無限ループになる

Stop フックが Claude に追加作業をさせ続けると無限ループになります。stop_hook_active フィールドを確認して早期リターンしてください:

#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0
fi
# ... 残りのフック処理

デバッグ方法

  • Ctrl+O でバーボースモードを切り替え、フックの出力をトランスクリプトで確認できる
  • claude --debug でフルデバッグログ(どのフックがマッチしたか、終了コードなど)を出力できる

まとめ

Claude Code Hooks は、Claude のエージェントループに決定論的なコントロールを追加する仕組みです。LLM の判断に頼らず、「常にこのアクションを実行する」という保証が得られます。

主要なポイントをまとめます。

  • 18 種類のイベント: PreToolUse でブロック、PostToolUse で後処理、Notification で通知、SessionStart でコンテキスト注入など用途に応じて使い分ける
  • 4 種類のフックタイプ: シェルコマンド(command)、LLM 判断(prompt)、サブエージェント(agent)、HTTP(http
  • スコープ管理: グローバル(~/.claude/settings.json)とプロジェクト(.claude/settings.json)を使い分けてチーム共有も可能
  • 終了コード: 0 で続行、2 でブロック(stderr がフィードバック)

まずは Notification イベントのデスクトップ通知から始めて、徐々に PostToolUse による自動フォーマット、PreToolUse によるファイル保護へと広げていくのが実践的なアプローチです。

参考リンク

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?