「編集のたびに自動でフォーマットしたい」「.env や package-lock.json は絶対に書き換えさせたくない」「危険な rm -rf は止めたい」——こうした「必ずこうなってほしい」を、AIの気まぐれに頼らず確実に実現するのが Claude Code hooks(フック)だ。フックは Claude Code のライフサイクルの要所で自動実行されるシェルコマンドで、プラグインの構成要素にもなる。

本記事では、フックとは何か・イベント一覧・設定方法・入出力の契約・使い方・安全性を、公式ドキュメントに基づいて整理する。先に要点を3つ。① フックは「ハーネス(Claude Code 本体)が実行する確定的な処理」——モデルが「やろうと判断する」のを待たずに必ず走る。② settings.json にイベント名→マッチャ→コマンドの形で書く。③ PreToolUse などは終了コード2やJSONで“ブロック”できる——保護ファイル編集や危険コマンドを止められる。

CLAUDE CODE · HOOKS

ライフサイクルの要所で“必ず”走る

— モデルの判断ではなく、ハーネスが確定的に実行する

SessionStart セッション開始。出力をコンテキストに注入
UserPromptSubmit プロンプト送信時 [ブロック可]
PreToolUse ツール実行の直前=門番 [ブロック可]
PostToolUse ツール成功後=自動整形/監査に
Stop 応答終了時=テスト合格まで続行など [ブロック可]

各点で あなたのシェルコマンドが走る。PreToolUse で危険な操作を門前払い、PostToolUse で自動整形——が定番。

1. Claude Code hooks(フック)とは

公式ドキュメントの定義はこうだ:「フックは、Claude Code のライフサイクルの特定の時点で実行される、ユーザー定義のシェルコマンド。Claude Code の振る舞いに対する“確定的な制御”を提供し、特定の動作を(LLMが選ぶのではなく)常に起こるようにする」。プロジェクトのルールを強制したり、繰り返し作業を自動化したり、既存ツールと連携させたりするのに使う。

核心は 「決定論(determinism)」だ。「テストを流して」とお願いしても、モデルが流すかは“判断”次第。だが フックなら、ハーネスが必ず実行する——気まぐれが入らない。現在はコマンド(command)以外に HTTP・MCPツール・LLMプロンプト・サブエージェント検証といった種類も増えているが、まずは 「シェルコマンドを要所で必ず走らせる仕組み」と捉えれば十分だ。なお、LLMプロンプト型とサブエージェント型のフックには、「〜を止める」のような指示文で書くと止めるべきものを通してしまう不具合があり、v2.1.294 で直っている(公式の changelog)。

2. フックイベント一覧

イベントは「ライフサイクルのどこで発火するか」を表す。まずは定番の9つを押さえよう(“ブロック可”=終了コード2やJSONでその動作を止められる)。

イベント発火タイミングブロック
SessionStartセッション開始・再開時(stdout はコンテキストに注入)不可
UserPromptSubmitプロンプト送信時、Claude が処理する前(v2.1.299 以降はスキルやカスタムのスラッシュコマンドが展開される前で、ブロックするとコマンドに埋め込んだシェルコマンドも動かない、公式・更新履歴、2026年10月18日に確認)可
PreToolUseツール呼び出しの直前(主要な門番)可
PostToolUseツール成功後(※実行自体は取り消せない)不可
Notification通知(入力/許可待ち等)時不可
StopClaude が応答を終えるとき(ブロック=続行)可
SubagentStopサブエージェントが終了したとき可
SessionEndセッション終了時不可
PreCompactコンテキスト圧縮の前可

2026年の公式ドキュメントでは、これ以外にも PermissionRequest・PostToolUseFailure・ConfigChange・FileChanged・WorktreeCreate など多数のイベントが追加されている。ただしイベント名はバージョンで増減しうるので、本記事では安定している定番9つ+次章の契約を軸にする(最新の全リストは公式で確認を)。

3. 設定方法

フックは settings.json の "hooks" キーに書く。配置場所でスコープが決まる:ユーザー(~/.claude/settings.json)/プロジェクト(.claude/settings.json・git共有可)/ローカル(.claude/settings.local.json)/管理ポリシー(組織)/プラグインの hooks/hooks.json。JSONの形はこうだ。

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

構造は 「hooks → イベント名 → { matcher, hooks:[...] } の配列 → 各フックは type+command」。マッチャは対象ツール名を指定し、"*"(または省略)で全一致、"Edit|Write" のように | 区切り、その他の記号は正規表現(例 mcp__memory__.*)。大文字小文字は区別される。なお /hooks コマンドで設定済みフックを一覧できるが 読み取り専用——追加・変更は settings.json を直接編集する。全無効化は "disableAllHooks": true。

4. 入出力の契約

フックは 標準入力(stdin)にJSONを受け取り、終了コードまたは標準出力のJSONで結果を返す。

入力(stdin):session_id・transcript_path・cwd・hook_event_name などが共通。ツール系イベントは tool_name・tool_input(例 {"command":"rm -rf /tmp/build"})、UserPromptSubmit は prompt が加わる。終了コード:0=成功(一部イベントでは stdout がコンテキストに追加される。ただし PreToolUse の0は“承認”ではなく通常の許可フローに従う)、2=ブロック(stderr が Claude に渡され、修正の材料になる。JSON で allow を返してもこのブロックは覆せない)。

フック自体が失敗したとき(起動できない・タイムアウトした・想定外の終了コードで終わった)は、既定では多くのイベントで操作がそのまま通る。パスを打ち間違えた門番のフックは、エラーの通知を出すだけで何も止めない。v2.1.295 以降は、command と http のフックに "onFailure": "block" を付けると、失敗したときに操作を止められる(既定は "continue")。

# PreToolUse の構造化JSON出力で「拒否」する例(stdout に出す)
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "DBへの書き込みは禁止です"
  }
}
# 共通フィールド: continue(false で完全停止) / decision:"block"+reason /
#                additionalContext(Claudeへ追記) / updatedInput(引数を書換)

v2.1.300(2026年10月14日)以降、PreToolUse と PermissionRequest のフックが返す updatedInput は、Claude 自身の入力と同じように検証される。ツールが知らないキーは捨てられ、ツールが受け付けない入力を返すとその呼び出しは拒否される(更新履歴、2026年10月18日に確認)。

最重要の原則:「フックは制限を“きつく”できるが“緩く”はできない」。allow を返してもプロンプトを省くだけで、どのスコープの deny ルール(管理設定含む)も常に優先される。PreToolUse の deny は bypassPermissions / --dangerously-skip-permissions でもブロックする。ただしこの原則は settings.json などに書くフック(mod の公式ページでは「settings hook」)の話で、v2.1.287 以降の mod(関数で書くフックを持つプラグイン)が tool.check に答えると、ask ルールの確認や管理設定以外の PreToolUse フックのブロックを覆せ、auto モードでは承認した呼び出しが分類器を通らず、管理設定のある端末や Team・Enterprise プランでのサインイン時を除けば deny ルールが拒否した呼び出しまで承認できる(公式)。mod は信頼できる作者のものだけを入れること。つまりフックは権限評価を拡張できるが、土台となる許可ルールは別物だ——Claude Codeの権限ルール(allow/ask/deny)は settings.json に書く。権限設計の考え方は 権限モードとセキュリティも参照。

5. 使い方の例

公式が挙げる定番ユースケースを、設定とセットで。

USE CASES

定番の自動化

編集後に自動整形
PostToolUse+Edit|Write で prettier / linter を自動実行。
保護ファイルを守る
PreToolUse で .env・.git/ 等への編集を exit 2 でブロック。
危険コマンドを止める
PreToolUse で rm -rf 等を検知し deny を返す。
コンテキスト再注入
SessionStart の stdout で 規約やメモを毎回読み込ませる(圧縮後も)。
通知・監査ログ
Notification でデスクトップ通知、PostToolUse でコマンド履歴を記録。
終了前にテスト
Stop でテストが通るまで止めない(合格まで続行させる)。

補足:Claude は Bash 経由でもファイルを変えられる。全変更を捕捉したいなら、ターン毎に作業ツリーを走査する Stop フックを足す。

6. 安全性

フックは強力だが、あなたの権限で任意のシェルコマンドを自動実行する——ここを軽視してはいけない。

⚠️ 公式の警告

「コマンドフックは、あなたのユーザー権限のすべてでシェルコマンドを実行する。ユーザーアカウントが触れるファイルなら、変更・削除・読み取りのどれもできる。設定に加える前に、すべてのフックのコマンドを見直し、試すこと」。フックはファイル読取・コード改変・データ持ち出し・任意コマンド実行が可能——完全に信頼できるものだけを設定する。

フォルダの信頼(重要な安全機構):対話型のセッションでは、そのフォルダの信頼ダイアログを承認するまで、設定ファイルのフックは走らない(自分の ~/.claude/settings.json のものも含む)。一方 -p や SDK のセッションではダイアログが出ず信頼済みとして扱われるので、他人のリポジトリで回す前に .claude/ の設定を確かめる。なお、設定ファイルを直接書き換えた変更は、通常は自動で反映される。

実務上は、入力を必ず検証・クォートする(jq で取り出す/未クォート変数は追加引数やシェル構文になり得る)、絶対パス・${CLAUDE_PROJECT_DIR} を使う、.env・.ssh 等の機微ファイルは触らない、ツール出力を eval しない、が鉄則。フックは制御端末を持たない(/dev/tty 不可)。組織では管理者が allowManagedHooksOnly でフックを制限できる。

まとめ

Claude Code hooks(フック)は、ライフサイクルの要所で自動実行されるユーザー定義のシェルコマンドで、「必ずこうなる」をモデルの判断に頼らず確定的に実現する仕組みだ。定番イベントは SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Notification / Stop / SubagentStop / SessionEnd / PreCompact の9つ(PreToolUse 等はブロック可=保護ファイルや危険コマンドを止められる)。設定は settings.json の "hooks" に イベント→マッチャ→type+command の形で書く。

入出力は stdin にJSON、終了コード0(成功)/2(ブロック)、または stdout の構造化JSON。原則は 「制限はきつくできるが緩くできない」(deny は常に優先。ただし mod は4節の例外)。定番ユースケースは 自動整形・保護ファイル防御・危険コマンド阻止・コンテキスト再注入・監査・終了前テスト。ただし 任意コード実行ゆえ、信頼できるフックだけ・入力は検証/クォートを徹底し、対話型ではフォルダを信頼するまで設定ファイルのフックは走らない点を理解しておく。関連:プラグイン、MCP、Claude Codeエラー集、mod(公式の概要)、mods の詳しい解説は「Claude Code の mods とは」。

Stop フックを自分で書かずに「条件を満たすまで続けさせる」だけなら、その場で使える /goal がある(会話の中だけで働くプロンプトのフック)。

FAQ

Q. フックは何のための機能ですか?
A. 「必ずこうしてほしい」を確定的に自動化する機能です。「編集後に整形」「保護ファイルは書き換えさせない」「危険な rm -rf は止める」「終了前にテストを通す」などを、AIの判断に頼らずハーネスが必ず実行します。フックは ライフサイクルの要所で走るシェルコマンドで、settings.json に設定します。

Q. どんなイベント(タイミング)がありますか?
A. 定番は SessionStart(開始)・UserPromptSubmit(送信時)・PreToolUse(ツール直前)・PostToolUse(ツール後)・Notification(通知)・Stop(応答終了)・SubagentStop・SessionEnd(終了)・PreCompact(圧縮前)の9つです。このうち PreToolUse・UserPromptSubmit・Stop・PreCompact 等はブロック可能で、操作を止められます。2026年版では他にも多くのイベントが追加されていますが、名前はバージョンで変わりうるので最新は公式で確認してください。

Q. 保護したいファイルや危険なコマンドを止められますか?
A. はい。PreToolUse フックで止められます。スクリプトで tool_input のファイルパスやコマンドを調べ、.env や rm -rf 等にマッチしたら 終了コード2(または JSON で permissionDecision:"deny")を返せばブロックされます。重要なのは deny は常に優先され、bypassPermissions でも止まること。フックは「制限をきつくする」方向にしか効きません。ただし、プラグインとして入れる mod(関数で書くフック)は tool.check でこの判定を覆せ、管理設定のある端末や Team・Enterprise プランでのサインイン時を除けば deny ルールが拒否した呼び出しまで承認できます(公式)。mod は信頼できる作者のものだけを入れてください。

Q. 設定を変えたのに反映されません。
A. 通常は自動で反映されます。設定ファイルを直接編集すると、ファイルの監視が変更を拾います。数秒たっても反映されないときは監視が変更を取りこぼした可能性があるので、セッションを再起動してください。JSON の書き間違い(末尾のカンマやコメント)も確かめましょう。また対話型のセッションでは、フォルダの信頼ダイアログを承認するまで設定ファイルのフックは走りません。なお /hooks は一覧の読み取り専用で、追加・変更は settings.json を直接編集します。

Q. フックは安全ですか?
A. 無条件には安全ではありません。フックは あなたの権限で任意のシェルコマンドを実行するため、公式も「フックはあなたのユーザー権限のすべてで動く」と警告しています。信頼できるフックだけを設定し、入力は jq で検証・クォート、絶対パスを使い、.env・.ssh 等は触らない、ツール出力を eval しないのが鉄則です。組織では管理者が allowManagedHooksOnly でフックを制限できます。