本文へ移動
BenriWorks Lab

連載

Claude Code 集中講座

13回 / 全16

13/16

ガイド公開日

フックで、判断を挟まずに必ず起きることを決める

設定ファイルを開いた画面の前で、こちらを向いて座っている女性の開発者

Claude Code 集中講座の第13回。ライフサイクルの各点でシェルコマンドを走らせるフックの仕組みを、編集後の整形、危険なコマンドの遮断、文脈の差し込みという3つの例で扱います

第9回で、CLAUDE.md は文脈であって強制される設定ではないと書きました。第12回の終わりでも、サブエージェントは Claude が判断して動くものだと書きました。

判断を挟まずに必ず起きてほしいことは、別の仕組みで書きます。

フックは、判断の外にある

フックは、あなたが書いたシェルのコマンドです。Claude Code が、自分の動作の決まった時点でそれを実行します。

公式ドキュメントの言い方では、これが決定論的な制御をもたらします。モデルがそうすることを選ぶかどうかに頼らず、その動作が必ず起きます。

「コミット前に必ずリントを通す」を CLAUDE.md に書くと、たいてい通りますが、たまに飛びます。フックに書くと、飛びません。

設定は hooks の中に書く

設定ファイルに hooks という項目を足します。自分だけに効かせるなら ~/.claude/settings.json、チームで共有するならプロジェクトの .claude/settings.json です。

いちばん短い例を挙げます。ファイルを編集したあとに整形を走らせるものです。

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

構造は3段です。イベント名、条件、実行するコマンドの並び。matcherEdit|Write になっているので、ファイルを編集する道具のあとだけで動きます。編集されたファイルの場所は、標準入力に JSON で渡ってきます。

この1つを入れるだけで、「書式が揃っていないのでCIが落ちる」という種類の失敗が消えます。実際、BenriWorks でも書式の検査で何度か落としています。

よく使うイベント

公式ドキュメントに載っているイベントは30を超えますが、最初に知っておけばよいのは次の10ほどです。

イベントいつ起きるか
SessionStartセッションが始まる、または再開したとき
UserPromptSubmitあなたが依頼を送ったとき(Claude が処理する前)
PreToolUseツールの実行の前。止められる
PermissionRequest許可の判断が必要になったとき
PostToolUseツールの実行が成功したあと
PostToolUseFailureツールの実行が失敗したあと
Notification通知が出るとき(入力待ちなど)
StopClaude が応答を終えたとき
PreCompact文脈の圧縮の前
SessionEndセッションが終わるとき
セッションの流れに沿ってフックが起きる位置を示した図。セッション開始、依頼の送信、ツール実行の前、ツール実行の後、応答の終了、セッション終了の順に並び、ツール実行の前だけが処理を止められることが示されている
止められるのは実行の前。あとのフックは記録と後処理に向く

止められるのは PreToolUse です。ここが、いちばん強い使い道になります。

危ないコマンドを、判断の前に止める

第5回で、deny 規則の話をしました。あれはツールと指定の組み合わせで書くものでした。フックを使うと、もっと細かい条件で止められます。

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

スクリプトの中で、渡ってきたコマンドを読んで判定します。本番のデータベースの接続先が含まれていたら止める、--force が付いていたら止める、といった条件を書けます。

deny 規則で書けるものは deny 規則で、書けないものだけフックで。 規則のほうが読みやすく、設定ファイルを見ればすぐ分かるからです。

セッションの最初に、文脈を差し込む

もう1つの使い方です。フックの標準出力に書いた内容は、Claude の文脈に入ります。

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          { "type": "command", "command": "git log --oneline -10" }
        ]
      }
    ]
  }
}

これで、セッションの最初に直近のコミットが渡ります。「いま何をやっている途中か」を毎回説明せずに済みます。

同じ仕組みを UserPromptSubmit に付けると、依頼のたびに何かを差し込めます。ただし毎回入るので、短いものに限ってください。第9回で見たとおり、常に入るものが長いほど、1つ1つの重みは下がります。

matcher の書き方

matcher が何と照合されるかは、イベントによって違います。

イベント照合されるもの
PreToolUsePostToolUse などツールの名前BashEdit|Writemcp__.*
SessionStart開始の理由startupresumeclearcompact
SessionEnd終了の理由clearresumelogout
Notification通知の種類permission_promptidle_prompt

空文字にすると、そのイベントの全部で動きます。

SessionStart の照合先が「開始の理由」なのは便利です。新しく始めたときだけ文脈を差し込み、再開のときは何もしない、といった書き分けができます。

フックはあなたの権限で動く

ここは飛ばさないでください。

フックはシェルのコマンドです。あなたが手で打てることは何でもできます。 権限モードの外側にあり、分類器も通りません。

だから Claude Code は、設定ファイルのフックについて作業フォルダの信頼を条件にしています。他人のリポジトリを初めて開いたとき、そこに .claude/settings.json があってフックが書かれていても、信頼するまでは実行されません。

他人のリポジトリを開くときは、信頼する前に .claude/settings.json を読んでください。 これは Claude Code に限った話ではなく、リポジトリに入っている実行可能な設定全般に言えることですが、フックは特に見落とされやすい場所です。

何をフックにするか

3つの仕組みの線引きを、ここで整理しておきます。

書く場所性質
CLAUDE.md文脈。たいてい守られるコードの規約、構成の説明
許可の規則強制。ツール単位.env を読ませない
フック強制。任意の条件と処理編集後の整形、特定の条件での遮断

判断の順番は上からです。規約で足りるなら規約、規則で書けるなら規則、それでも足りないときだけフック。

フックは強力ですが、設定ファイルの中に処理が隠れます。半年後に「なぜか毎回これが走る」と悩むことになるので、増やしすぎないでください。入れたフックには、何のためかをコメントとして残せる場所(スクリプト側)に理由を書いておくと後が楽です。

手元と、その先

フックは手元のセッションの中で動きます。手元を離れたところ、たとえばプルリクエストの検査に同じことをさせたいなら、それは GitHub Actions の仕事です。書き方はCodex 集中講座の第13回にまとめてあります。

役割は分かれます。フックは書いている最中に効き、CI は出す前に効きます。同じ検査を両方に置いても構いません。むしろ、手元で通したものが CI で落ちるなら、手元の環境に記録されていない何かが残っているという情報になります。

次の回

第14回では、ここまで1つずつ動かしてきたセッションを並べます。作業ツリー、並行セッション、そして手元を離れたクラウドと web の話です。

参照した公式情報

  • Anthropic「Automate actions with hooks」「Hooks reference」「Configure permissions」(code.claude.com/docs、2026年9月時点)

よくある質問

CLAUDE.md に書くのとフックにするのは、どう違いますか
CLAUDE.md は文脈であって強制ではありません。読んで従おうとしますが、必ず守られる保証はありません。フックはシェルのコマンドとして決まった時点で実行されるので、Claude の判断に関係なく動きます。必ず起きてほしいことはフックにしてください。
フックはどこに書きますか
設定ファイルの `hooks` の中です。自分だけに効かせるなら `~/.claude/settings.json`、チームで共有するならプロジェクトの `.claude/settings.json` に書きます。イベント名を鍵にして、その下に条件と実行するコマンドを並べます。
フックは危なくないですか
あなたの権限でシェルのコマンドを実行します。つまり、あなたが手で打てることは何でもできます。だからこそ、リポジトリから受け取った設定ファイルのフックは、作業フォルダを信頼するまで実行されません。他人のリポジトリを開くときは、`.claude/settings.json` の中身を読んでから信頼してください。

こんな記事も読まれています