何のためのものか
Claude Code のライフサイクルの特定の時点で自動実行される、ユーザー定義のシェルコマンド・HTTP エンドポイント・LLM プロンプト。
CLAUDE.md が「守ってほしい」なら、hook は「守らせる」。 Claude の判断に関わらず動作をブロックしたいなら、こちらしかない。
触る
3 段のネストで書く。イベント → matcher group → handler の順。
~/.claude/settings.jsonか.claude/settings.jsonにhooksを書く/hooksメニューで設定を確認する- 実際に発火させる。settings ファイルの hook の直接編集はファイル監視で自動的に反映される
まず触るなら、セッションに 1 回だけ動く SessionStart か、編集のたびに動く PostToolUse が分かりやすい。
入れる
対象を絞る。ここが雑だと、関係ない場面で毎回動く hook ができる。
matcherはイベントごとに絞る対象が違う。PreToolUse/PostToolUseはツール名、SessionStartは開始方法(startup/resume/clear/compact/fork)、PreCompactはmanual/auto- matcher の書き方で評価が変わる。 英数字・
_・-・スペース・,・|だけなら完全一致(または区切りリスト)、それ以外の文字を含むとanchor 無しの正規表現になる。Edit.*はNotebookEditにも一致するので、全体一致には^Edit$と書く ifでさらに絞る。 permission rule 構文で"Bash(git *)"、"Edit(*.ts)"のように書く。ただしツールイベントでしか評価されない(それ以外のイベントではif付き hook は決して動かない)timeoutの既定はイベントと種類で違う。command/http/mcp_toolは 600 秒だが、UserPromptSubmitでは 30 秒、SessionEndの hook は 1.5 秒の予算を共有する- 待たせたくない処理は
async: true。終了時に Claude を起こしたいならasyncRewake: true
効かせる
返し方を使い分ける。
| やりたいこと | 返し方 |
|---|---|
| 成功。何も伝えない | exit 0(stdout はデバッグログ行き) |
| 止める。理由を Claude に伝える | exit 2(stderr がエラーメッセージとして Claude に返る) |
| 情報だけ Claude に渡す | exit 0 + hookSpecificOutput の additionalContext |
| ユーザーに警告を見せる | JSON の systemMessage |
| Claude の処理を完全に止める | JSON の continue: false(stopReason はユーザーにだけ見える) |
- exit 1 は非ブロッキングエラー。 ポリシーを強制するなら
exit 2を使う - 終了コードと JSON はどちらか一方。 JSON は exit 0 のときだけ処理される
- 止められないイベントがある。
PostToolUse(ツールは既に実行済み)、Notification、SessionStartなどは exit 2 でもブロックにならない - 動かないときはデバッグログ。 どの hook が一致したか、終了コード、stdout / stderr の全文が書かれる。
claude --debugで~/.claude/debug/<session-id>.txt、CLAUDE_CODE_DEBUG_LOG_LEVEL=verboseで matcher 照合の詳細まで出る
落とし穴
- command hook はユーザーの完全な権限でシェルコマンドを実行する。 設定に追加する前にレビューとテストを行う。シェル変数は常にクォートし、
..のパストラバーサルをブロックする - hook は制御端末を持たない。
/dev/ttyへエスケープシーケンスを書いても失敗する。通知やタイトルはterminalSequence、ユーザー向けメッセージはsystemMessage - 個別の hook だけを無効化する方法は無い。 一時停止は
"disableAllHooks": trueで全部か、settings からエントリを消すか - matcher 非対応のイベントに
matcherを書いても黙って無視される additionalContextは命令ではなく事実として書く。 システムコマンドのように書かれたテキストは prompt-injection 防御を起こし、コンテキストとして扱われないことがある- MCP ツールに一致させるには
mcp__<server>__<tool>の形。mcp__memoryのような完全一致文字だけの形は何にも一致しない