blog

Claude Code hooks(フック)の設定と活用ガイド【2026】

関連記事Claude Code(クロードコード)とは?できること・料金・使い方を初心者にもやさしく解説【2026年版】 / Claude Code 使用量を完全制御する実装ガイド【2026年版】 / Claude Code ログイン方法・できない時の対処法|2026年版ガイド

Claude Code Hooksとは何か:概要と位置づけ

Claude Code Hooksは、Claude Codeのエージェント実行サイクルの特定タイミングに対して、任意のシェルコマンドやスクリプトを自動実行させる仕組みです。この機能により、「AIがコードを書いた直後に自動でlintを走らせる」「ツール呼び出しのたびにログを記録する」「承認なしでは実行できないコマンドをブロックする」といった、開発ワークフローの自動化・ガードレール設定が可能になりました。

クリスタルメソッドでもClaude Codeを日常的に使っており、ファイル編集前の自動バックアップなどをHooksで組んで運用しています。本記事では、Hooksの仕組みから設定方法、実践的な活用例まで、網羅的に解説します。

Hooksが解決する問題:なぜ必要か

Claude Codeはエージェントとして自律的にコードを編集・実行します。その自律性は強力ですが、次のような課題を生みます。

  • 品質チェックの抜け漏れ:AIが生成したコードにlintやフォーマッタを毎回手動で実行するのは非現実的
  • セキュリティ・ガバナンス:特定のコマンド(本番DBへの直接操作など)を誤って実行させないための歯止めが必要
  • 可観測性の欠如:AIが何をいつ実行したか、監査ログを残す仕組みがデフォルトでは薄い
  • チームルールの強制:個人の設定に依存せず、プロジェクト全体で一貫したルールを適用したい

Hooksはこれらをすべてシェルスクリプトの記述という馴染みある手段で解決します。Claude Code側のコードを変更せず、外部コマンドを挟み込むだけでワークフローを制御できる点が革新的です。

Hooksの実行タイミング:ライフサイクルイベント一覧(公式は33種類)

公式ドキュメント(2026年10月8日確認)では、フックを差し込めるライフサイクルイベントが33種類定義されています。大きく分けると、セッションごとに1回(SessionStart・SessionEnd)、ターンごとに1回(UserPromptSubmit・Stop・StopFailure)、ツール呼び出しのたび(PreToolUse・PostToolUse)の3つの頻度があります。まずは実務でよく使う次の4つから押さえるのが近道です。

イベント名 発火タイミング 主なユースケース
PreToolUse ツール実行の直前(ユーザー確認の前) コマンドのブロック・検証・事前ログ
PostToolUse ツール実行の直後(結果が返った後) lint/テスト自動実行・変更後ログ
Notification Claude Codeが通知を送るとき Slack通知・デスクトップ通知連携
Stop Claudeが応答を終了するとき 完了通知・後処理・サマリー生成

実務で最も使用頻度が高いのはPostToolUseとPreToolUseです。PostToolUseでファイル保存後の自動フォーマットを実行し、PreToolUseで危険なコマンドを遮断するパターンが、開発チームの標準構成として定着しています。

4つ以外で押さえておきたいイベント

上の4つ以外にも、次のイベントは設定の幅を大きく広げます(公式ドキュメント 2026年10月8日確認)。

イベント名発火タイミング終了コード2でブロックできるか
SessionStartセッションの開始・再開時できない
UserPromptSubmitプロンプトを送信し、Claudeが処理する前できる(プロンプトがClaudeに届かない)
PermissionRequestツール呼び出しに権限の判断が必要なとき終了コード2は無視される(拒否はJSONの decision で行う)
PostToolUseFailureツール呼び出しが失敗した後できない(stderrをClaudeに表示)
SubagentStart / SubagentStopサブエージェントの起動時/終了時Startはできない/Stopはできる
StopFailureAPIエラーでターンが終了したときできない
PreCompact / PostCompactコンテキスト圧縮の前/後—
SessionEndセッションの終了時できない

このほか、作業ディレクトリの変更(CwdChanged)、監視ファイルの変更(FileChanged)、設定ファイルの変更(ConfigChange)、モデル切り替えの前後(PreModelSwitch / PostModelSwitch)、MCPサーバーからの入力要求(Elicitation)なども用意されています。

Hooksの設定場所:settings.jsonの構造

HooksはClaude Codeの設定ファイル(settings.json)に記述します。設定ファイルには適用スコープによって3つの場所があります。

プロジェクトの .claude/settings.json にPostToolUseのhook(EditとWriteの後にログを1行書く)を登録し、/hooks を実行した実際の画面です(2026年10月5日、Claude Code v2.1.289で撮影)。登録したhookがイベント別に一覧表示されます。画面にもあるとおり、/hooks のメニューは閲覧専用で、hookの追加や変更は settings.json を編集するか、Claudeに頼んで行います。

Claude Codeで/hooksを実行した画面。PostToolUseに登録したhookが表示されている
/hooks の画面。PostToolUseに登録したhookが表示されている
スコープ ファイルパス 適用範囲
ユーザーグローバル ~/.claude/settings.json そのユーザーの全プロジェクト
プロジェクトローカル {project}/.claude/settings.json そのプロジェクトのみ(git管理推奨)
プロジェクトローカル(個人) {project}/.claude/settings.local.json そのプロジェクト内の個人設定(gitignore推奨)

チーム開発では.claude/settings.jsonをgitリポジトリにコミットすることで、全メンバーに同一のHooksルールを自動適用できます。個人の追加設定はsettings.local.jsonに分離する運用が扱いやすいです。

settings.jsonの基本スキーマ

Hooksの設定は"hooks"キー配下に記述します。基本的な構造は以下のとおりです。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block_dangerous.sh"
          }
        ]
      }
    ]
  }
}

設定の主要要素を整理すると次のようになります。

  • matcher:どのツール名(またはツール名パターン)に反応するかを正規表現で指定
  • hooks配列:マッチしたときに実行するコマンド群(複数指定可)
  • type:フックの種類。シェルコマンドを実行する"command"がもっともよく使われます(ほかにhttp・mcp_tool・prompt・agentがあります)
  • command:実行するシェルコマンド文字列
  • if(任意):"Bash(git *)"や"Edit(*.ts)"のように、権限ルールと同じ書き方で発火する条件をさらに絞る
  • timeout(任意):打ち切るまでの秒数。command型の既定は600秒
  • async(任意):trueにすると、Claudeを待たせずにバックグラウンドで実行する(その場合、ブロックはできない)

入力データ:Hooksスクリプトが受け取る情報(標準入力のJSONと環境変数)

フックが発火すると、Claude Codeはそのイベントの情報をJSON形式で標準入力(stdin)に渡します。スクリプトはこのJSONを読み取って、「どのファイルが編集されたか」「どのコマンドが実行されようとしているか」を判断します。CLAUDE_TOOL_INPUT_FILE_PATHのような環境変数で渡されるわけではない点に注意してください(公式ドキュメント 2026年10月10日確認)。JSONの読み取りにはjqを使うのが一般的です(macOSはbrew install jq、Debian/Ubuntuはapt-get install jq)。

たとえばClaudeがnpm testを実行しようとしたとき、PreToolUseのフックには次のJSONが渡されます(公式ドキュメントの例)。

{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}
項目(jqでの取り出し方) 内容 渡されるイベント
.session_id セッションの一意ID(ログ用途に有用) 全イベント
.cwd イベント発生時の作業ディレクトリ 全イベント
.hook_event_name 発火したイベント名(例:PreToolUse) 全イベント
.tool_name ツール名(例:Write、Bash) PreToolUse / PostToolUse など
.tool_input.file_path Edit・Writeツールが操作するファイルのパス PreToolUse / PostToolUse(Edit・Write)
.tool_input.command Bashツールで実行されるコマンド文字列 PreToolUse / PostToolUse(Bash)
.prompt 送信されたプロンプトの文章 UserPromptSubmit
環境変数 $CLAUDE_PROJECT_DIR プロジェクトのディレクトリのパス。スクリプトの場所を絶対パスで書かずに済む 全イベント

スクリプトの中では、INPUT=$(cat)で標準入力を受け取り、echo "$INPUT" | jq -r '.tool_input.command'のように必要な項目を取り出します。イベントごとに渡される項目は異なるため、詳しくは公式のHooksリファレンスを確認してください。

Hooksの終了コードとClaude Codeの制御フロー

Hooksスクリプトの終了コード(exit code)は、Claude Codeの動作に直接影響します。この仕組みを理解することが、ガードレール実装の核心です。

終了コード 0

正常終了。処理を続行する。

終了コード 1

ブロックしないエラー。処理は続行する。画面の記録に「hook error」の通知とstderrの1行目が表示されるが、Claudeには伝わらない。

終了コード 2

ブロック。stderrの内容を理由としてClaudeに伝える。止められるのはPreToolUse・UserPromptSubmit・Stopなど、まだ起きていない動作を表すイベントのみ。

終了コード2がブロック機能です。PreToolUseのフックが2を返すと、Claude Codeはツールの実行を中止し、スクリプトの標準エラー出力(stderr)をエラー理由としてモデルに伝えます。なお公式ドキュメント(2026年10月8日確認)では、PostToolUseなど既に実行済みの動作を表すイベントでは2を返しても止められず、PermissionRequestでは2が無視されると明記されています。モデルはそのフィードバックを受けて別の方法を検討します。

実践的な設定例5選

ファイル保存後の自動フォーマット(Prettier)

最もシンプルで効果の高い設定です。ClaudeがファイルをWriteまたはEditするたびにPrettierを自動実行します。標準入力のJSONからjqで編集されたファイルのパスを取り出し、Prettierに渡しています(公式ドキュメントの例に、Prettierが対応していない種類のファイルを無視する--ignore-unknownを付けたもの)。

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

この設定をユーザーグローバル設定(~/.claude/settings.json)に書くと、全プロジェクトで有効になります。Claudeが書いたコードのフォーマットを毎回手で直す手間を減らせます。

危険なBashコマンドのブロック

本番環境に関連するコマンドや破壊的な操作を自動でブロックするスクリプトです。

#!/bin/bash
# .claude/hooks/block_dangerous.sh
# 標準入力のJSONから、これから実行されるコマンドを取り出す
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' | tr '[:upper:]' '[:lower:]')

# 禁止パターン定義
BLOCKED_PATTERNS=(
  "rm -rf /"
  "drop table"
  "drop database"
  "prod_db"
  "curl.*| *bash"
)

for pattern in "${BLOCKED_PATTERNS[@]}"; do
  if echo "$COMMAND" | grep -q "$pattern"; then
    # 理由は標準エラー出力(stderr)へ。終了コード2で実行を止めると、この文がClaudeに伝わる
    echo "BLOCKED: '$pattern' を含むコマンドは自動実行できません。必要なら人が内容を確認して手動で実行してください。" >&2
    exit 2
  fi
done

exit 0

ブロックの理由は標準出力ではなく標準エラー出力(>&2)に書きます。終了コード2で止めたとき、Claudeに伝わるのはstderrの内容だからです。スクリプトはプロジェクトの.claude/hooks/に置き、chmod +xで実行権限を付けます。設定ファイルへの組み込みは以下のとおりです。

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

Python ファイルの自動 lint(flake8 + black)

#!/bin/bash
# .claude/hooks/py_lint.sh
FILE_PATH=$(jq -r '.tool_input.file_path // empty')
# Python以外のファイルは何もしない
[[ "$FILE_PATH" == *.py ]] || exit 0

black -q "$FILE_PATH"
if ! RESULT=$(flake8 "$FILE_PATH"); then
  # 指摘内容をstderrに出して終了コード2で返すと、Claudeに伝わる
  echo "$RESULT" >&2
  exit 2
fi
exit 0
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/py_lint.sh"
          }
        ]
      }
    ]
  }
}

flake8が指摘を出した場合、その内容をstderrに書いて終了コード2で返しています。PostToolUseは実行済みの操作なので取り消しはできませんが、終了コード2のときはstderrがClaudeに表示されるため、Claudeが指摘を読んで次のステップで修正できます。flake8の終了コード(1)のまま終わらせると「ブロックしないエラー」として扱われ、指摘はClaudeに伝わりません。

実行ログの記録

コンプライアンス要件やデバッグのために、Claude Codeが実行したすべてのツール呼び出しをログファイルに記録します。

#!/bin/bash
# .claude/hooks/audit_log.sh
INPUT=$(cat)
LOG_FILE="${HOME}/.claude/audit.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "$INPUT" | jq -r --arg ts "$TIMESTAMP" \
  '"\($ts) | SESSION:\(.session_id) | TOOL:\(.tool_name) | FILE:\(.tool_input.file_path // "N/A") | CMD:\(.tool_input.command // "N/A")"' >> "$LOG_FILE"
exit 0
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit_log.sh"
          }
        ]
      }
    ]
  }
}

matcherに"*"を指定する(または省略する)と全ツールをキャッチします。監査の要件があるプロジェクトでは、このログを毎日アーカイブするcronジョブと組み合わせる運用が考えられます。

タスク完了時のSlack通知(Stopイベント)

長時間かかるエージェントタスクが完了したとき、SlackのWebhookに通知します。席を離れている間に実行させておき、完了したら知らせる運用に有用です。

#!/bin/bash
# .claude/hooks/notify_slack.sh
INPUT=$(cat)
WEBHOOK_URL="${SLACK_CLAUDE_WEBHOOK_URL}"  # 環境変数で管理
PROJECT=$(basename "$CLAUDE_PROJECT_DIR")
SESSION=$(echo "$INPUT" | jq -r '.session_id')
TIMESTAMP=$(date '+%H:%M:%S')

# 通知文はjqで組み立てる(引用符などが正しくエスケープされる)
PAYLOAD=$(jq -n --arg t "Claude Code の応答が完了 [${PROJECT}] ${TIMESTAMP} (Session: ${SESSION})" '{text: $t}')
curl -s -X POST "$WEBHOOK_URL" -H 'Content-type: application/json' --data "$PAYLOAD" > /dev/null
exit 0
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/notify_slack.sh"
          }
        ]
      }
    ]
  }
}

Stopイベントはmatcherに対応していないため、matcherは書きません(毎回発火します)。Stopは作業全体の完了時だけでなく、Claudeが応答を終えるたびに発火する点にも注意してください。入力を待っているときだけ通知したい場合は、Notificationイベントが向いています。WebhookURLはコード中に直書きせず、必ず環境変数経由で渡すようにしてください。

Claude Code・AIエージェントの業務導入をご検討の方は、自社での開発実例を公開しているクリスタルメソッドの無料相談をご利用ください。

複数イベント・複数コマンドの組み合わせ設定

実際の運用設定ファイルでは、複数のイベントと複数のhooksを組み合わせることになります。以下は、ここまでに紹介したフックを組み合わせたプロジェクト設定の例です。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit_log.sh"
          },
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block_dangerous.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit_log.sh"
          },
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/notify_slack.sh"
          }
        ]
      }
    ]
  }
}

同じイベントに複数のhooksがマッチした場合、それらは並列に実行され、すべてが最後まで実行されます。1つがブロック(deny)を返しても、ほかのフックの実行は止まりません。全部が終わったあとで結果がまとめられ、PreToolUseの判定はいちばん厳しいもの(deny)が優先されます。そのため「先のフックがブロックしたら、後ろのフックは動かない」という前提で設計しないでください(公式ドキュメント 2026年10月10日確認)。

Claude Code Hooksのライフサイクルフローイメージ
Claude Code Hooksのライフサイクルフローイメージ

設定時の注意点とよくある落とし穴

コマンドのパスは絶対パスで指定する

Hooksコマンドはシェルのインタラクティブセッションとは異なる環境で実行されます。PATHの解決が期待どおりにならないケースがあるため、npxやnodeなども含め、絶対パスまたはbash -c '...'経由での実行が安定します。特にnvmやpyenvで管理しているランタイムは注意が必要です。

無限ループに注意する

フックのスクリプトが自分でファイルを書き換えても、それはClaudeのツール呼び出しではないため、PostToolUseが再び発火することはありません。ループに注意が必要なのはStopフックです。Stopフックが終了コード2で「まだ終わるな」と返し続けると、Claudeは作業を続け、再びStopが発火します。入力のJSONにあるstop_hook_activeがtrueのときは何もせず終了する、という判定を必ず入れてください。Claude Code側でも、ツール呼び出しを挟まずに8回連続でブロックされると、Stopフックを無視して終了する仕組みになっています。

タイムアウトを意識した設計

Hooksコマンドは、既定では完了するまでClaudeの処理を待たせます。実行時間が長いスクリプト(テストスイート全体の実行など)をPostToolUseに入れると、全体の応答が著しく遅くなります。command型の既定のタイムアウトは600秒(UserPromptSubmitは30秒)で、フックごとにtimeout(秒)で変更できます。重い処理は、フックの設定に"async": trueを付けてバックグラウンドで実行するか、Stopイベントへの移動を検討してください。

matcherの正規表現の確認

matcherは、英数字と_・-・|などだけで書いた場合は完全一致として扱われます("Bash"はBashツールだけ、"Edit|Write"はEditかWriteのどちらか)。それ以外の文字を含むと正規表現として扱われ、名前の一部に一致すれば発火します。たとえば"Edit.*"はEditにもNotebookEditにも一致するため、全体一致にしたいときは^Edit$のように書きます。大文字と小文字は区別されます。

スクリプトに実行権限を付与する

外部スクリプトファイルを参照する場合、chmod +x ~/.claude/hooks/your_script.shで実行権限を付与しておく必要があります。権限がないと終了コード1相当の失敗になります。

Hooksを実運用して気づいた落とし穴(一次情報)

監修者・河合継はClaude Codeを3.5の時代から1年以上、実務で運用しており、編集前の自動バックアップなどをHooksで組んで日常的に使ってきた。設定して初めて分かる注意点を補足する。

  • Hookは「重くしない・止めない」を最優先にする。ツール実行のたびに走るため、処理が重いと作業全体が遅くなる。失敗しても本筋を止めない(非ブロッキングにする)設計にしておくと、Hookが原因で手が止まる事故を避けられた。
  • 静かに失敗していないかを時々確認する。Hookは裏で動くぶん、エラーに気づきにくい。期待した処理(バックアップやチェック)が本当に走っているかを、たまに実際の出力で確かめる癖をつけると安心だ。
  • 欲張らず、本当に自動化したい一点に絞る。あれもこれもHookに載せると、全体像が追えなくなり保守が苦しくなる。効果の大きい一つから始めて、必要になったら足すのが結局安定した。

Hooksの全機能リファレンス:ハンドラー種別・イベント・マッチャー構文

ここまでは command 型(シェルコマンド実行)を中心に解説してきたが、Claude Code の hooks 機能は本来もう少し幅が広い。公式仕様として、フックのハンドラーには command のほかに http(外部エンドポイントへのHTTP呼び出し)・mcp_tool(MCPツールの呼び出し)・prompt(Claudeへの追加指示挿入)・agent(サブエージェント起動)の合計5種類が用意されている。監修者の運用では、シェルスクリプトで完結し依存が少ない command 型だけを使っており、他の4タイプは使っていない。外部SaaS連携やMCPサーバーと密に連携したい構成であれば、http型・mcp_tool型の検討余地はあるだろう。

イベント面でも、本記事の実装例は PreToolUse/PostToolUse/Notification/Stop の4つを軸に紹介しているが、公式仕様上は SessionStart・SessionEnd・UserPromptSubmit・StopFailure といったイベントも定義されている。セッション開始時の初期化処理や、Stop 処理が失敗した場合だけ別処理を挟みたいといったケースでは、これらのイベントを併用する余地がある。

もう一つ抜けやすいのが matcher(フックを発火させる条件)の書き方だ。ツール名の完全一致だけでなく正規表現でのマッチも可能で、さらに if フィールドを使えば「Bash(git *) のように特定コマンドのパターンだけをブロック・許可する」といった細かい条件分岐も書ける。加えて ${CLAUDE_PROJECT_DIR} のようなパスプレースホルダーをコマンド文字列やmatcher内で使うと、フックスクリプトの絶対パスをハードコードせずに済む。本記事の設定例をベースに条件を絞り込みたい場合は、まずこの if フィールドとプレースホルダーの組み合わせから試すのが実務上は近道になる。

Hooksのデバッグ方法

Hooksが意図どおりに動かない場合のデバッグ手順を紹介します。

  1. /hooks で登録を確認:/hooksを実行し、フックが正しいイベントの下に表示されているかを確認する。設定ファイルの編集は通常自動で読み込まれる
  2. スクリプト単体の動作確認:見本のJSONを標準入力に流してスクリプトを直接実行し、終了コードと出力を確認する。例:echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh; echo $?
  3. 記録を見る:Ctrl+Oで記録(transcript)の表示を開くと、ブロックしたときのメッセージや「hook error」の通知を確認できる。成功したフックは何も表示されない
  4. デバッグログ:claude --debugで起動する(またはclaude --debug-file /tmp/claude.logでファイルに書き出す)と、フックの終了コード・標準出力・標準エラー出力まで確認できる
  5. matcher のテスト:matcherを"*"に変えて全ツールにマッチさせ、発火しているかを確認した後、絞り込む。matcherは大文字と小文字を区別する

Hooksとpermissions設定の使い分け

Claude Codeにはpermissions設定(allow・ask・denyのルール)もあります。Hooksとの違いを理解して適切に使い分けることが重要です。

機能 Hooks(PreToolUse exit 2) permissions(denyルール)
ブロックの粒度 コマンド内容・引数レベルで動的判定可能 ツール名のほか、Bash(git push *)のようにコマンドのパターンでも指定できる(決め打ちのルール)
フィードバック ブロック理由をモデルに伝えられる 拒否されたことが伝わる(理由の文は書けない)
柔軟性 高(スクリプトで任意ロジック実装) 中(ルールの一覧。スクリプトのような任意の判定はできない)
用途 条件付きブロック・パターンマッチング 特定のツールや決まったコマンドの禁止

「Bashツールは使えるが、本番に関わるコマンドだけブロックしたい」という要件にはHooksが適しており、「WebSearchツール自体を一切使わせない」という要件にはpermissionsが適しています。両者を組み合わせた多層防御が実践的なアプローチです。なお、PreToolUseフックは権限モードの判定より前に動くため、フックのdenyは権限を省略するモードでも有効です。逆に、フックがallowを返しても、設定のdenyルールは上書きできません。

よくある質問

Q. Claude Code Hooksとは何ですか?
A. Claude Codeのエージェント実行サイクルの特定タイミングに対して、任意のシェルコマンドやスクリプトを自動実行させる仕組みです。自動フォーマット、危険なコマンドのブロック、ログの記録、完了通知などに使えます。

Q. Hooksにはどんなライフサイクルイベントがありますか?
A. 公式ドキュメント(2026年10月8日確認)では33種類が定義されています。よく使うのはPreToolUse(ツール実行の直前)、PostToolUse(ツール実行の直後)、Notification(通知送信時)、Stop(Claudeが応答を終了するとき)の4つで、ほかにSessionStart・SessionEnd・UserPromptSubmit・PermissionRequest・SubagentStop・PreCompactなどがあります。

Q. Hooksの設定はどこに書きますか?
A. settings.jsonの”hooks”キー配下に記述します。適用範囲によってユーザーグローバル(~/.claude/settings.json)、プロジェクトローカル({project}/.claude/settings.json)、プロジェクトローカル個人用(settings.local.json)の3箇所があります。

Q. フックのスクリプトは、編集されたファイルや実行されるコマンドをどう受け取りますか?
A. 環境変数ではなく、標準入力(stdin)にJSONで渡されます。ファイルのパスは tool_input.file_path、Bashのコマンドは tool_input.command、ツール名は tool_name、セッションIDは session_id に入っているため、jq などで取り出します。環境変数として使えるのは、プロジェクトのディレクトリを表す CLAUDE_PROJECT_DIR などです。

Q. 終了コードによって動作はどう変わりますか?
A. 終了コード0は「異議なし」で処理を続行します。2はブロックで、stderrの内容が理由としてClaudeに伝わります。ブロックできるのはPreToolUse・UserPromptSubmit・Stop・SubagentStopなど「まだ起きていない動作」を表すイベントだけで、PostToolUseでは止められません(stderrはClaudeに表示されます)。それ以外の終了コードはブロックしないエラーとして扱われ、処理は続行します。

Q. matcherとは何ですか?
A. どのツール名に反応するかを指定するフィールドです。”Bash”や”Edit|Write”のように英数字と|だけで書くと完全一致、それ以外の文字を含むと正規表現として扱われます。ifフィールドを使うと、”Bash(git *)”のように特定のコマンドパターンだけに絞ることもできます。

Q. 複数のフックを登録すると、どの順番で実行されますか?
A. 同じイベントにマッチした複数のフックは並列に実行され、すべてが最後まで実行されます。1つがブロックを返してもほかのフックは止まりません。PreToolUseの判定は、いちばん厳しい結果(deny)が優先されます。

Q. command型以外にどんなハンドラー種別がありますか?
A. 公式仕様ではcommand(シェルコマンド実行)のほか、http(外部エンドポイントへのHTTP呼び出し)・mcp_tool(MCPツールの呼び出し)・prompt(Claudeへの追加指示挿入)・agent(サブエージェント起動)の合計5種類が用意されています。

Q. Hooksとpermissions設定はどう使い分けますか?
A. Hooksはスクリプトでコマンドの内容を見て動的にブロック判定でき、ブロック理由をClaudeに伝えられます。permissions(allow・ask・denyのルール)は、ツール名やコマンドのパターンを決め打ちで許可・拒否する仕組みです。条件によって判断を変えたい場合はHooks、決まったツールやコマンドを常に禁止したい場合はpermissionsが適しています。

Q. Hooksがうまく動かないときはどうデバッグしますか?
A. /hooks で登録を確認し、見本のJSONを標準入力に流してスクリプトを直接実行して終了コードを確かめます。Ctrl+O の記録表示でブロックのメッセージや hook error の通知を確認でき、claude –debug で起動すると終了コードや出力の詳細を確認できます。


まとめ

Claude Code Hooksは、エージェント実行サイクルの各タイミング(PreToolUse・PostToolUse・Notification・Stop)にシェルコマンドを差し込む仕組みです。終了コードによってツールのブロックも可能であり、自動フォーマット・危険コマンドの遮断・監査ログ・完了通知といった実務的な要件をシェルスクリプトという普遍的な技術で実現できます。

弊社での実運用を通じて得た最大の知見は、「Hooksはコストゼロでチームの開発標準を強制できる装置である」という点です。プロジェクトの.claude/settings.jsonにHooksを定義してgitにコミットするだけで、チーム全員の環境に即座に適用されます。まずは自動フォーマットと監査ログの2つから導入し、チームの実情に合わせてガードレールを追加していく段階的なアプローチが、スムーズな定着につながります。

関連記事

監修

河合 継(クリスタルメソッド株式会社 代表取締役)

AI・ディープラーニングに関する特許16件の発明者。過去、国立がん研究センターとの共同研究や、テレビ番組でのAI解説実績を持つAI研究者として、AIの研究開発を主導している。
運営会社について | 編集方針

Claude Code・AIエージェントの業務活用をご検討の方へ

クリスタルメソッドは、Claude Codeを実務投入している開発会社として、AIエージェント・社員AIの導入と開発効率化を支援しています。自社サイトの表示速度をAI社員(Claude Code)で12.89秒→2.03秒に短縮した実例も事例記事として公開しています。「自社の開発・業務にAIをどう組み込むか」といったご相談を承っています。

AIブログ購読

 
クリスタルメソッドがお届けする
AIブログの更新通知を受け取る

Read next

あわせて読みたい

  • 対話・チャットLLMのイメージ

    Claude Code(クロードコード)とは?できること・料金・使い方を初心者にもやさしく解説【2026年版】

    ターミナル上で動作するAIエージェント型コーディングツールのイメージ Claude Code(クロードコード)とは、Anthropic社が提供するAIツールです...

  • Claude Code 使用量を完全制御する実装ガイド【2026年版】のイメージ

    Claude Code 使用量を完全制御する実装ガイド【2026年版】

    最終更新:2026年7月29日 よくある質問:Claudeの使用量・上限について Claudeの使用量上限とは? Claude(Claude.aiのチャット、お...

  • claude code ログインできない|2026年版ガイド

    Claude Code ログイン方法・できない時の対処法|2026年版ガイド

    Claude(クロード) Codeを使おうとしたら「ログインできない」「認証エラーが出る」「コマンドが通らない」――そんな状況で作業が止まってしまった経験はあり...

View more