Claude Code Hooks 実践ガイド 2026 — CI/CD連携からコード品質ゲートまで

Claude Code Hooks 実践ガイド 2026 — CI/CD連携からコード品質ゲートまで

Claude Code Hooksの設定方法から実践的なユースケースまで。PreToolUse/PostToolUseフック、Agent Teamsとの連携、Lintチェック自動化、セキュリティゲートの実装例を網羅。

エンジニアのゆとです。

Claude Code Hooksの入門記事はいくつか書いてきた。「PreToolUseでコマンドをブロックする」「Notificationでファイル変更を検知する」という基本は別記事に任せる。

この記事で扱うのは、その先の話だ。

CI/CDパイプラインとHooksをどう接続するか。Agent TeamsのTeammateIdleTaskCompletedをどう使って品質ゲートを実装するか。HTTP HookやPrompt Hookのような2026年に追加された新しいフックタイプをどう活用するか。

Hooksを「たまに使う補助機能」ではなく「開発パイプラインの構成要素」として設計するときに必要な知識を全部詰め込んだ。


Hooksとは何か — Claude Codeの拡張ポイント

Hooksは「Claude Codeのセッションライフサイクルの特定ポイントで、ユーザー定義の処理を自動実行できる仕組み」だ。

ポイントは2つ。

1つ目は「AIが判断するのではなく、確実に実行される」という点。「このファイルを編集したあとはLintを実行してね」とシステムプロンプトに書いても、Claudeが忘れることがある。Hookに書けば確実に実行される。

2つ目は「exit codeでClaude Codeの挙動を制御できる」という点。フックスクリプトがexit 2を返すと、その処理をブロックできる。「このコマンドは実行させない」「このファイルへの書き込みは止める」という制御が確実にできる。

比喩でいうと、Gitのpre-commitフックに近い。ただしGitフックがgit commitという一点にしか刺せないのと違って、Claude Code Hooksはセッション開始からツール実行・Agent Teamsの協調まで、25種類以上のポイントに刺せる。

コードレビューや品質チェックを「お願いベース」から「仕組みベース」に変えたいなら、Hooksは必須の知識になる。


Hooksの設定方法(settings.json)

設定ファイルの場所

Hooksの設定はsettings.jsonに書く。設定ファイルには3種類の置き場所がある。

~/.claude/settings.json          # 個人設定(全プロジェクトに適用)
.claude/settings.json            # プロジェクト設定(リポジトリで共有可)
.claude/settings.local.json      # ローカル設定(gitignoreされる)

チームで共有したいルール(危険なコマンドのブロック、セキュリティスキャン等)はプロジェクトの.claude/settings.jsonに書く。個人の作業スタイルに関わるもの(Slack通知の宛先、ローカルツールへのパス等)はsettings.local.jsonに書いておくと、うっかりコミットするリスクがない。

基本構造

settings.jsonのHooks定義の基本形はこうなる。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/validate-bash.sh",
            "timeout": 10,
            "statusMessage": "コマンド検証中..."
          }
        ]
      }
    ]
  }
}

構造のポイントを整理する。

  • hooksの直下にイベント名(PreToolUse等)
  • 各イベントは配列で、複数のmatcherを持てる
  • matcherはツール名のパターン(BashEdit|Writemcp__.*等)
  • hooks配列でそのマッチャーに対する処理を定義

フックスクリプトの配置ルール

スクリプトの置き場所は、パスプレースホルダーを使って明示的に指定できる。

{
  "type": "command",
  "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/validate.sh"
}

${CLAUDE_PROJECT_DIR}はプロジェクトルートに解決される。複数マシンで同じ設定を使いたいときに便利だ。他に${CLAUDE_PLUGIN_ROOT}(プラグインインストールディレクトリ)もある。

exec形式とshell形式の違い

コマンドの書き方には2パターンある。

// exec形式(argsを指定したとき)
// パス展開はされる、シェルの解釈なし
{
  "type": "command",
  "command": "node",
  "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check.js", "--strict"]
}

// shell形式(argsを省略したとき)
// パイプ・&&・リダイレクトが使える
{
  "type": "command",
  "command": "eslint $FILE_PATH && echo 'OK'"
}

パイプラインを組みたい場合はshell形式、引数の安全な受け渡しが必要な場合はexec形式を使い分ける。


フックイベント一覧と使い分け

2026年現在、Claude Code Hooksには3種類のイベントカテゴリがある。

セッションレベルイベント(1セッションに1回)

イベント発火タイミング代表的な使い方
SessionStartセッション開始・再開時環境変数の読み込み、コンテキストの準備
SessionEndセッション終了時ログの保存、後片付け
Setup--init-only実行時プロジェクトの初期化処理

SessionStartは開発環境の準備に使いやすい。.envのバリデーションや、必要なツールのインストール確認を自動化できる。

ターンレベルイベント(1ターンに1回)

イベント発火タイミング代表的な使い方
UserPromptSubmitユーザーがプロンプトを送信したとき禁止ワードのチェック、コンテキスト追加
StopClaudeの応答完了時成果物の検証、通知送信
StopFailureAPIエラーで終了したときエラーアラート

Stopイベントは「タスクが完了したことを外部に通知する」用途で頻繁に使う。Slackへの完了通知やCI/CDのステータス更新が典型的だ。

エージェントループイベント(ツール呼び出しごと)

ここが実践で最も使うカテゴリだ。

イベント発火タイミング代表的な使い方
PreToolUseツール実行前コマンドのブロック、権限制御
PostToolUseツール成功後結果の検証、Lintの実行
PostToolUseFailureツール失敗後エラーログ、リトライ判定
PostToolBatch並列ツール完了後次のモデル呼び出し前の処理
PermissionRequest権限ダイアログ表示時自動許可・自動拒否

Agent Teamsイベント(v2.1.32以降)

Agent Teamsを有効にしている場合、追加のイベントが使えるようになる。

イベント発火タイミング代表的な使い方
SubagentStartサブエージェント開始時タスク開始ログ
SubagentStopサブエージェント完了時成果物の品質チェック
TeammateIdleチームメイトがアイドル状態になったとき次のタスク割り当て
TaskCompletedタスクが完了したとき品質ゲート、統合テスト

TeammateIdleTaskCompletedはAgent Teams特有で、あとで詳しく解説する。

その他のユーティリティイベント

イベント用途
Notification通知送信時のカスタマイズ
FileChanged監視ファイルの変更検知
CwdChanged作業ディレクトリ変更時
ConfigChange設定ファイル変更時のバリデーション
InstructionsLoadedCLAUDE.md読み込み時
PreCompact / PostCompactコンテキスト圧縮前後

フックタイプ一覧

イベントに対してどんな処理を実行するかは5種類から選べる。

command    シェルコマンド実行(最も汎用的)
http       HTTPエンドポイントへのPOST(外部サービス連携)
mcp_tool   MCPツールの呼び出し
prompt     LLMを使った判定(「このコマンドは安全か?」等)
agent      サブエージェントの起動

commandが基本で、9割のユースケースはこれでカバーできる。httpはCI/CDシステムへのWebhookに使う。promptは「このコードはセキュリティ上問題ないか」というAIによる判定に使える。


実践ユースケース5選

フックに渡されるデータはstdinのJSONだ。共通のフィールドはこうなる。

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

スクリプト内でjqを使って値を取り出すのが基本パターンだ。

1. ファイル保存時の自動Lintチェック

PostToolUseイベントでWriteまたはEditをマッチさせると、ファイル保存後に自動でLintを実行できる。

// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/auto-lint.sh",
            "timeout": 30,
            "statusMessage": "Lint実行中..."
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# .claude/hooks/auto-lint.sh

# stdinからtool_inputを取得
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

# ファイルが取得できなければスキップ
if [ -z "$FILE_PATH" ]; then
  exit 0
fi

# 拡張子でLintツールを分岐
EXTENSION="${FILE_PATH##*.}"

case "$EXTENSION" in
  js|jsx|ts|tsx)
    cd "$(dirname "$FILE_PATH")" 2>/dev/null || cd "$CLAUDE_PROJECT_DIR"
    npx eslint "$FILE_PATH" --max-warnings 0 2>&1
    LINT_EXIT=$?
    ;;
  py)
    ruff check "$FILE_PATH" 2>&1
    LINT_EXIT=$?
    ;;
  go)
    golint "$FILE_PATH" 2>&1
    LINT_EXIT=$?
    ;;
  *)
    # 対象外の拡張子はスキップ
    exit 0
    ;;
esac

if [ $LINT_EXIT -ne 0 ]; then
  # exit 2でClaude Codeにエラーを表示
  # ツール自体は実行済みなのでブロックにはならないが、警告として表示される
  echo "Lint error in $FILE_PATH" >&2
  exit 2
fi

exit 0

このパターンのポイントは「PostToolUseのexit 2はツールをブロックしない(すでに実行済み)」という点だ。ブロックしたいならPreToolUseを使う。ここではLintエラーをClaude Codeの画面に警告として表示させることが目的なので、PostToolUseで十分だ。

2. git commit前のセキュリティスキャン

PreToolUseBashをマッチさせ、git commitを含むコマンドをインターセプトする。機密情報が含まれていたらcommitをブロックする。

// .claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git commit *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/security-scan.sh",
            "timeout": 20
          }
        ]
      }
    ]
  }
}

ifフィールドでBash(git commit *)と書くと、git commitを含むBashコマンドのときだけフックが発火する。全てのBashコマンドにフックをかけるよりパフォーマンスが良い。

#!/bin/bash
# .claude/hooks/security-scan.sh

INPUT=$(cat)

# スキャン対象パターン
PATTERNS=(
  "AKIA[0-9A-Z]{16}"          # AWS Access Key ID
  "sk-[a-zA-Z0-9]{32}"        # OpenAI API Key
  "ghp_[a-zA-Z0-9]{36}"       # GitHub Personal Access Token
  "password\s*=\s*['\"][^'\"]+['\"]"  # ハードコードされたパスワード
  "SECRET_KEY\s*=\s*['\"][^'\"]{8,}['\"]"  # シークレットキー
)

# ステージングエリアのdiffを取得
STAGED_DIFF=$(git diff --cached 2>/dev/null)

if [ -z "$STAGED_DIFF" ]; then
  exit 0
fi

FOUND_ISSUES=""

for PATTERN in "${PATTERNS[@]}"; do
  MATCH=$(echo "$STAGED_DIFF" | grep -E "$PATTERN" | head -3)
  if [ -n "$MATCH" ]; then
    FOUND_ISSUES+="Pattern detected: $PATTERN\n$MATCH\n\n"
  fi
done

if [ -n "$FOUND_ISSUES" ]; then
  # JSON形式で詳細な理由を返す
  jq -n \
    --arg reason "$(printf '%s' "$FOUND_ISSUES")" \
    '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "deny",
        permissionDecisionReason: ("機密情報が検出されました。commit前に確認してください:\n" + $reason),
        additionalContext: ".envファイルをgitignoreに追加してあるか確認し、機密情報をenv変数化してください。"
      }
    }'
  exit 0
fi

exit 0

permissionDecision: "deny"git commitをブロックし、permissionDecisionReasonで検出された問題の詳細をClaude Codeに表示させる。additionalContextはClaude側への追加情報として渡され、次の修正提案に活用される。

3. Slack通知(作業完了時)

Stopイベントで「Claudeが1つのタスクを終えた」タイミングにSlack通知を送る。長時間かかるタスクをClaude Codeに任せているときに便利だ。

// .claude/settings.local.json(個人設定。SLACK_WHOOKのURLを含むのでローカルのみ)
{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/notify-slack.sh",
            "async": true,
            "timeout": 10
          }
        ]
      }
    ]
  }
}

async: trueを指定すると、Slack通知がバックグラウンドで実行される。通知の完了を待たずにClaude Codeが次の作業に移れるので、体験がよくなる。

#!/bin/bash
# .claude/hooks/notify-slack.sh
# 環境変数 SLACK_WEBHOOK_URL が設定されている前提

if [ -z "$SLACK_WEBHOOK_URL" ]; then
  exit 0
fi

INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
CWD=$(echo "$INPUT" | jq -r '.cwd // "unknown"')
STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // "completed"')

# transcript_pathから最後のアシスタントメッセージを取得
TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // ""')
LAST_MESSAGE=""
if [ -f "$TRANSCRIPT_PATH" ]; then
  LAST_MESSAGE=$(tail -20 "$TRANSCRIPT_PATH" | \
    jq -r 'select(.type == "assistant") | .message.content[-1].text // ""' 2>/dev/null | \
    tail -1 | \
    cut -c1-200)
fi

PROJECT_NAME=$(basename "$CWD")

curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d "$(jq -n \
    --arg project "$PROJECT_NAME" \
    --arg reason "$STOP_REASON" \
    --arg msg "$LAST_MESSAGE" \
    '{
      text: "Claude Code タスク完了",
      blocks: [
        {
          type: "section",
          text: {
            type: "mrkdwn",
            text: ("*プロジェクト*: " + $project + "\n*ステータス*: " + $reason)
          }
        },
        {
          type: "section",
          text: {
            type: "mrkdwn",
            text: ("*最終出力*:\n" + $msg)
          }
        }
      ]
    }')" \
  > /dev/null 2>&1

exit 0

transcript_pathからJSONL形式のトランスクリプトを読み取って最後のメッセージを取得している。実際の作業内容をSlackに流せるのが便利だ。

4. Agent Teams品質ゲート(TeammateIdle/TaskCompleted)

これが一番「他の記事に書いてない」ユースケースだと思う。

Agent Teamsを使っているとき、各チームメイトが完了した成果物を「次に引き継ぐ前に自動検証」したい場面がある。TeammateIdleTaskCompletedイベントを使うと、チームメイト間の受け渡しポイントに品質ゲートを挟める。

// .claude/settings.json(Agent Teams有効時)
{
  "hooks": {
    "SubagentStop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/agent-quality-gate.sh",
            "timeout": 60,
            "statusMessage": "成果物を検証中..."
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# .claude/hooks/agent-quality-gate.sh

INPUT=$(cat)
AGENT_ID=$(echo "$INPUT" | jq -r '.agent_id // ""')
AGENT_TYPE=$(echo "$INPUT" | jq -r '.agent_type // ""')
CWD=$(echo "$INPUT" | jq -r '.cwd // "."')

# ログファイルに記録
LOG_FILE="${CLAUDE_PROJECT_DIR:-$CWD}/.claude/agent-quality-log.jsonl"
echo "$INPUT" >> "$LOG_FILE" 2>/dev/null

# TypeScriptプロジェクトの場合: 型チェックを自動実行
if [ -f "$CWD/tsconfig.json" ]; then
  TS_ERRORS=$(cd "$CWD" && npx tsc --noEmit 2>&1)
  TS_EXIT=$?

  if [ $TS_EXIT -ne 0 ]; then
    # Claude Codeに型エラーの存在を通知
    # SubagentStopのexit 2はエラー表示(停止ブロック)
    echo "TypeScript型エラーが検出されました (agent: $AGENT_TYPE):" >&2
    echo "$TS_ERRORS" | head -20 >&2
    exit 2
  fi
fi

# テストファイルが存在する場合: 関連テストを実行
if [ -f "$CWD/package.json" ]; then
  HAS_TEST=$(cat "$CWD/package.json" | jq -r '.scripts.test // ""')
  if [ -n "$HAS_TEST" ] && [ "$HAS_TEST" != "null" ]; then
    cd "$CWD" && npm test -- --passWithNoTests --bail 2>&1
    TEST_EXIT=$?

    if [ $TEST_EXIT -ne 0 ]; then
      echo "テスト失敗が検出されました (agent: $AGENT_TYPE)。次のエージェントへの引き継ぎをブロックします。" >&2
      exit 2
    fi
  fi
fi

exit 0

SubagentStopでexit 2を返すと、Claudeが「このサブエージェントの出力に問題がある」と認識して、次のステップに進む前に対処しようとする。完全な自動修正とはならないが、「型エラーを無視して次のエージェントに渡す」という状況を防げる。

HTTP Hookを使うと、外部のCI/CDシステムにwebhookを送ることもできる。

// HTTP Hookを使ったCI/CDシステムへの通知例
{
  "hooks": {
    "SubagentStop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/api/agent-completed",
            "headers": {
              "Authorization": "Bearer $CI_WEBHOOK_TOKEN",
              "Content-Type": "application/json"
            },
            "allowedEnvVars": ["CI_WEBHOOK_TOKEN"],
            "timeout": 15
          }
        ]
      }
    ]
  }
}

allowedEnvVarsで許可した環境変数だけがHTTP Hookに渡せる。セキュリティ上の配慮として、全環境変数をそのまま渡す仕組みにはなっていない。

5. 危険なコマンドのブロック(rm -rf等)

これは他の記事でも触れているが、2026年版の書き方でおさらいしておく。

従来は「exit 2を返してブロック」という方式だったが、現在はJSONのpermissionDecisionフィールドを使う方式が推奨されている。JSON出力の方が「なぜブロックしたか」をClaude Codeに正確に伝えられるからだ。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-dangerous.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# .claude/hooks/block-dangerous.sh

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# ブロック対象パターン
DANGEROUS_PATTERNS=(
  "rm -rf /"
  "rm -rf \*"
  "rm -rf ~"
  "rm -rf \$HOME"
  "> /dev/sda"
  "mkfs\."
  "dd if=/dev/zero"
  "chmod -R 777 /"
  "chown -R .* /"
  ":(){:|:&};:"  # Fork bomb
)

for PATTERN in "${DANGEROUS_PATTERNS[@]}"; do
  if echo "$COMMAND" | grep -qE "$PATTERN"; then
    jq -n \
      --arg cmd "$COMMAND" \
      --arg pattern "$PATTERN" \
      '{
        hookSpecificOutput: {
          hookEventName: "PreToolUse",
          permissionDecision: "deny",
          permissionDecisionReason: ("危険なコマンドのため実行をブロックしました: " + $cmd),
          additionalContext: ("マッチしたパターン: " + $pattern + ". このコマンドは取り消せない破壊的操作を引き起こす可能性があります。実行が必要な場合は手動で実行してください。")
        }
      }'
    exit 0
  fi
done

# 問題なし
exit 0

permissionDecision: "deny"でブロックし、additionalContextでClaude Codeに「次はどうすべきか」のヒントを渡している。Claudeはこの情報を元に「手動での確認を求める」という判断をしやすくなる。

exit 0でJSON出力、exit 2でstderrテキスト出力という使い分けも覚えておきたい。JSON出力の方が情報量が多い。


Hooksのデバッグとトラブルシューティング

まず/hooksコマンドを叩く

Claude Code内で/hooksと入力すると、現在の設定で有効なフック一覧が表示される。

Available hooks:
  PreToolUse (3 hooks)
    - Bash → .claude/hooks/block-dangerous.sh [Project]
    - Bash → .claude/hooks/security-scan.sh [Project]
    - Write|Edit → .claude/hooks/auto-lint.sh [User]
  PostToolUse (1 hook)
    - Write|Edit → .claude/hooks/auto-lint.sh [User]
  Stop (1 hook)
    - * → .claude/hooks/notify-slack.sh [Local]

[Project]/[User]/[Local]で設定ファイルのソースが分かる。「書いたはずなのに動かない」というときは、まずここで設定が読まれているか確認する。

よくあるエラーパターン

1. スクリプトが実行権限を持っていない

これが一番多い。フックスクリプトには必ず実行権限をつける。

chmod +x .claude/hooks/*.sh
2. stdinを読んでいない

フックスクリプトはstdinでJSONを受け取る。catjqでstdinを読まないと、jq: nullになって正しく動かない。

# 悪い例
COMMAND=$(echo $COMMAND)  # stdinを読んでいない

# 良い例
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
3. stdout汚染

フックスクリプトのstdoutはJSONとして解析される。デバッグ用のechoをstdoutに出力すると、JSON解析エラーになる。デバッグ出力は>&2でstderrに向ける。

# 悪い例
echo "DEBUG: command is $COMMAND"  # stdoutを汚染する

# 良い例
echo "DEBUG: command is $COMMAND" >&2
4. シェルプロファイルの干渉

.bashrc.zshrcが何かをstdoutに出力していると、フックが誤動作することがある。

# .bashrcに書いてあるような出力は問題を起こす
echo "Welcome to my dev environment!"  # これがフックのstdoutに混入する

フックスクリプト内でenv -iを使って環境をクリーンにすると解決できる場合がある。

5. タイムアウト

デフォルトのタイムアウトは長めに設定されているが、ネットワークを含む処理(Slack通知、HTTPリクエスト等)は必ずasync: trueか短めのtimeoutを明示する。

{
  "type": "command",
  "command": ".claude/hooks/notify-slack.sh",
  "async": true,
  "timeout": 10
}

デバッグモードでの確認

# デバッグモードでClaude Codeを起動
claude --debug

# フックの実行ログが詳細に出力される

--debugフラグをつけると、各フックの実行タイミング・exit code・stdout/stderrの内容が全部ログに流れる。「なぜブロックされているか分からない」という状況で最も役立つ。

全フックの一時無効化

{
  "disableAllHooks": true
}

問題の切り分けで「Hooksが原因か、Claude Code自体の問題か」を確認したいときに使う。


FAQ

Q. PreToolUseとPostToolUseはどっちをメインで使うべき?

目的によって使い分ける。

「やらせたくない」→ PreToolUse(実行前にブロック) 「やった後に確認したい」→ PostToolUse(実行後に検証)

Lintチェックの場合、PreToolUseで「このファイルを書き込む前にLintを通す」という使い方もできるし、PostToolUseで「書き込んだ後にLintを実行してエラーを報告する」という使い方もできる。前者の方がCI寄り、後者の方がフィードバックループとして自然だ。

Q. フックはどの順番で実行される?

同じイベント・同じマッチャーに複数のフックが定義されている場合、配列の順番通りに実行される。前のフックがexit 2を返すと、以降のフックは実行されない(ブロック扱い)。

設定ファイルの優先度はsettings.local.json > プロジェクト.claude/settings.json > ~/.claude/settings.jsonの順だが、フックは全設定ファイルから収集されてマージされる。優先度は「どのフックを実行するか」ではなく「設定値の衝突を解決する」ためのものだ。

Q. HTTP Hookで使える環境変数はどう制御する?

allowedEnvVarsフィールドで明示的に許可した環境変数だけが渡せる。

{
  "type": "http",
  "url": "http://localhost:8080/webhook",
  "headers": {
    "Authorization": "Bearer $MY_SECRET_TOKEN"
  },
  "allowedEnvVars": ["MY_SECRET_TOKEN"]
}

MY_SECRET_TOKENallowedEnvVarsに書いておかないと、ヘッダーにそのまま$MY_SECRET_TOKENという文字列が渡されてしまう。環境変数の展開はallowedEnvVarsで許可されたものだけに行われる。

Q. Prompt Hookはいつ使うべき?

「人間が判断するには時間がかかるけど、AIなら一瞬で判断できる」という場面に向いている。

{
  "type": "prompt",
  "prompt": "このコマンドはプロダクション環境に影響を与える可能性がありますか?: $ARGUMENTS",
  "model": "claude-opus-4-5",
  "timeout": 15
}

ただしPrompt HookはLLM呼び出しが発生するのでコストがかかる。頻繁に発火するイベント(全てのBashコマンド等)への適用は費用対効果を考える。月に数回しか走らないデプロイコマンドのチェックなら向いている。

Q. ifフィールドとmatcherの違いは?

matcherはイベントのツール名に対してマッチングする。Bashなら全てのBashツール呼び出し、Edit|Writeなら編集・書き込みツールが対象になる。

ifフィールドはツール呼び出しの内容(引数等)でさらに絞り込む。Bash(git commit *)なら「Bashでgit commitを含むコマンドのとき」というフィルタリングができる。

matcherで対象ツールを絞り、ifでコマンドの内容を絞るという2段階になっている。

Q. フックのタイムアウトはどう設定するのが良い?

経験則だが:

  • ローカルのLint実行 → 15-30秒
  • テスト実行 → 60-120秒
  • Slackなどの通知(async: true) → 10秒
  • セキュリティスキャン → 20-30秒

タイムアウトを超えると非ブロッキングエラー(exit 1相当)として扱われる。長い処理はasync: trueでバックグラウンド化するか、タイムアウトを適切に設定する。

Q. Agent Teamsでフックを使うとトークンコストは増える?

増える。SubagentStopに品質ゲートを仕掛けてexit 2を返すと、Claudeが状況を把握して次のステップを考えるための処理が走る。それ自体がトークンを消費する。

品質ゲートで失敗 → Claudeが修正 → 再チェック というサイクルが複数回まわると、想定より多くトークンが消費される。Agent Teamsはそもそも「significantly more tokens」を消費する機能なので、Maxプランを使っていても上限に注意する。


まとめ

Claude Code Hooksの実践的な使い方を5つのユースケースで解説した。

  • ファイル保存後の自動Lint(PostToolUse)
  • git commit前のセキュリティスキャン(PreToolUse + ifフィルタ)
  • 作業完了時のSlack通知(Stop + async)
  • Agent Teams品質ゲート(SubagentStop + 型チェック)
  • 危険コマンドのブロック(PreToolUse + JSON出力)

Hooksが本領を発揮するのは「チーム開発」か「Agent Teamsを使った並列処理」の場面だと思っている。一人での作業でも便利だけど、「この規則を全員に守らせたい」という場面で.claude/settings.jsonに書いてリポジトリに含めると、チーム全体の品質が上がる。

全フックイベントを網羅した公式ドキュメントは以下で確認できる。

Claude Code Hooksで開発を自動化する — 実際に使える5パターンを解説【2026年版】
Claude Code Hooksで開発を自動化する — 実際に使える5パターンを解説【2026年版】Claude Code Hooksの設定方法と実践的な使い方を解説。PreToolUse・PostToolUse・SessionStart・Notificationなど主要イベントを使った自動化レシピ5選。副業・フリーランスエンジニア向けに実用性重視でまとめた。読む →
Claude Code HooksでGitワークフローを自動化する — commit前後の品質ゲートを実装する
Claude Code HooksでGitワークフローを自動化する — commit前後の品質ゲートを実装するClaude Code HooksをGitワークフローに組み込む実践ガイド。commitトリガーでのlint/test自動実行、危険コマンドのブロック、コミットメッセージの自動生成、git push前のセキュリティチェックなど、実際に動くコード例付きで解説。読む →
Claude Code Agent Teams 完全ガイド 2026 — コスト計算から失敗パターンまで
Claude Code Agent Teams 完全ガイド 2026 — コスト計算から失敗パターンまでClaude Code Agent Teamsの有効化から実践活用まで。Subagentsとの使い分け判断、Hooksでの品質ゲート、Maxプランでのコスト試算、よくある失敗と対策を網羅。読む →
Claude Code × GitHub Actions でCI/CDを賢くする——AIレビュー・自動修正・コスト管理の実装パターン
Claude Code × GitHub Actions でCI/CDを賢くする——AIレビュー・自動修正・コスト管理の実装パターンClaude Code と GitHub Actions を連携してCI/CDパイプラインにAIを組み込む実践ガイド。PRレビュー自動化・テスト失敗の自動分析・コスト最適化まで、settings.jsonとワークフローファイルを丸ごと公開。読む →
Claude Code Skills 完全ガイド 2026年5月版 — 公式仕様・自作の作り方・おすすめ10選を実装視点で
Claude Code Skills 完全ガイド 2026年5月版 — 公式仕様・自作の作り方・おすすめ10選を実装視点でClaude Code Skills の公式仕様(SKILL.md frontmatter全項目・配置の4階層・動的コンテキスト注入)を整理し、最小構成から実用構成までの自作コード例とフリーランスエンジニア向けおすすめ10選を実装視点で網羅。2026年5月時点の最新仕様で解説。読む →
1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン
1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン.envファイルの平文管理から脱却するための実践ガイド。1Password CLIを使ったop runによる実行時注入・fish/zshシェル統合・MCPサーバー経由の3パターンを解説。Claude Code SubAgentsとの組み合わせ、Doppler/Infisicalとの比較まで網羅。読む →
← 記事一覧に戻る