はじめてのHook教科書
「フック」と聞いて、海賊船の片腕の船長くらいしか思い浮かばない――そんなあなたのための教科書です。この本を読み終える頃には、まったく別の「フック」があなたの開発の相棒になっているはずです。
そもそも「Hook」って何?
まず、日常語としての「hook(フック)」の意味から始めましょう。コートを掛ける壁の金具、魚を釣る針、カーテンを吊るす金具――どれも共通しているのは「何かが引っかかったら、それに連動して別のことが起きる」という性質です。カーテンフックに布を引っ掛ければ、布は勝手に吊り下がった状態になります。
Claude Codeの「Hook」も、考え方はまったく同じです。「何か特定の出来事が起きたときに、それに引っかけて、あなたが用意した処理を自動的に走らせる仕組み」――これがHookの正体です。
🎫 中心となる比喩:駅の自動改札
この教科書では、この後もずっと「駅の改札」を例に使っていきます。まずはその土台を作りましょう。
左:むかしの改札(お願いベース) / 右:今の自動改札(機械が必ず確認)
昔ながらの改札は、駅員さんが目視で切符を確認していました。これは「ちゃんと確認してくださいね」というお願いに支えられた仕組みです。駅員さんは基本的にちゃんと仕事をしてくれますが、混雑していたり、他のことに気を取られていたりすると、うっかり見落としてしまうこともあり得ます。
一方、今の自動改札機は違います。ICカードをタッチすれば、駅員さんの気分にも忙しさにも関係なく、機械が必ずチェックしてくれます。これがHookの本質です。
💡 ここが一番大事なポイント
CLAUDE.mdやDESIGN.mdは「駅員さんへのお願いメモ」。Claudeというとても優秀な駅員さんが読んで、基本的にはちゃんと守ってくれますが、絶対に見落とさない保証まではありません。Hookは「自動改札機そのもの」。AIの判断を経由せず、決まったタイミングで機械的に、必ず実行されます。
なぜHookが必要なのか
「優秀な駅員さんがいるなら、それで十分では?」と思うかもしれません。ここで、よくある「あるある」を考えてみましょう。
よくあるストーリー:あなたはCLAUDE.mdに「コミットする前には、必ずテストを実行してね」と書きました。ある日、Claudeは急いでいる作業の途中で、他にも大量の指示を抱えていました。結果、テストを実行せずにコミットしてしまいました。Claudeが「サボった」わけではありません。多くの指示の中で、優先順位づけを誤っただけです。
これは、事実としてAnthropic自身も認めていることです。Claude Codeの記憶の仕組み(CLAUDE.mdや自動メモリー)は、会話のたびに読み込まれますが、Claudeはそれらを「必ず実行する強制設定」ではなく「参考にする文脈」として扱います。つまり、CLAUDE.mdにどれだけ丁寧に書いても、それは最終的にはAIの判断を経由するのです。
もし「これだけは絶対に、例外なく起きてほしい」ということがあるなら、AIの判断を経由しない仕組みが必要です。それがHookです。Anthropic自身のドキュメントでも、そのような「絶対に起きてほしいこと」にはHookを使うべきだと述べられています。
比較表でもう一段深く整理
| CLAUDE.md / DESIGN.md | Hook | |
|---|---|---|
| 正体 | Claudeが読む指示文(お願いメモ) | 決まった瞬間に必ず走るプログラム |
| 実行の保証 | Claudeの判断次第。読み落とすこともある | AIの判断を経由せず、機械的に毎回実行 |
| 得意なこと | 方針・背景・理由など「考え方」を伝える | フォーマット・チェック・ブロックなど「作業」を確実に行う |
| 駅の比喩 | 駅員さんへの口頭のお願い | 自動改札機そのもの |
🎫 豆知識
CLAUDE.mdとHookは「どちらか一方を選ぶ」ものではありません。方針や考え方はCLAUDE.mdに、絶対に守ってほしいルールはHookに、と役割分担させるのが実務的な使い方です。
Hookの設計図を分解する
ここからは、実際にHookがどんな「部品」でできているかを、ゆっくり分解していきます。難しく見えても、部品ひとつひとつはシンプルです。
① どこに書くのか
Hookの設定は、JSON形式のファイルに書きます。置き場所は3種類あり、「誰に対して有効にしたいか」で使い分けます。
| ファイル | 効果範囲 | 駅の比喩でいうと |
|---|---|---|
~/.claude/settings.json | あなた専用。すべてのプロジェクトに効く | あなたが個人的に持っている、駅員としての「マイルール」 |
.claude/settings.json | プロジェクト共通。Gitに載せてチーム全員と共有 | その駅全体の「業務マニュアル」 |
.claude/settings.local.json | あなたのPCだけ。Gitには含めない | あなた個人の、他の駅員には見せないメモ |
② JSONの構造を分解する
Hookの設定は、入れ子になった箱のようなものです。外側から順番に見ていきましょう。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "実行したいコマンド" }
]
}
]
}
}
- "hooks" ―― 「ここからHookの設定ですよ」という一番外側の箱
- "PostToolUse" ―― いつ動くか(イベント名)。「改札の、どのタイミングのゲートか」にあたります
- "matcher" ―― 誰に対して動くか。「PASMOの人だけ対象にする改札」のような絞り込みです
- "type": "command" ―― どんな方法で処理するか。一番よく使うのは、シェルコマンドをそのまま実行する
commandタイプです - "command" ―― 実際に駅員(コンピューター)が行う処理そのもの
もう少し先まで知りたい人へ:type にはどんな種類がある?
command(シェルコマンドを実行)のほかに、外部のWebサービスにHTTPで知らせるhttp、AIに一次判断させるprompt、専用のサブエージェントに調査させるagentといった種類もあります。まずは一番使用頻度の高いcommandだけ覚えれば、実務の大半はカバーできます。
③ 結果はどう伝わるのか(終了コード)
コマンドを実行した結果、Hookは「終了コード」という数字でClaude Codeに結果を伝えます。ここだけ、しっかり覚えておきましょう。
💡 終了コードの意味
0 ―― 「問題なし、通ってOK」
2 ―― 「止めて!」という明確な合図(ただし、これが効くかどうかはイベントの種類による。詳しくは第4章)
それ以外の数字 ―― エラーとして扱われますが、必ずしも操作そのものが止まるわけではありません
代表的なイベントたち
Claude Codeには、Hookを引っ掛けられる「タイミング(イベント)」が30種類ほど用意されています。全部を一度に覚える必要はまったくありません。ここでは、実務でよく使う順に、少しずつ紹介していきます。
🎫 PreToolUse ―― 改札を「通る前」
Claudeが何か操作(ファイルの編集、コマンドの実行など)をしようとする、まさに直前のタイミングです。ここでHookが「ダメ」と判断すれば(終了コード2)、その操作は実際に実行される前に止められます。改札で言えば、不正乗車をしようとした人を、ゲートの前でしっかり止めるイメージです。危険なコマンドのブロックや、秘密ファイルへのアクセス防止など、「絶対にさせたくないこと」はここで止めます。
🎫 PostToolUse ―― 改札を「通った後」
操作が終わった直後のタイミングです。ここが初心者がいちばん誤解しやすいポイントなのですが、この時点ではもう改札を通過してしまっているので、その操作自体を取り消すことはできません。ただし、「実は問題があった」とClaudeに即座に伝えることはできます。ファイル保存後の自動フォーマットや、DESIGN.mdの検証など、「やったことをチェックして知らせる」用途で使います。
⚠️ ここ、間違えやすいので注意
「PostToolUseを使えば、ルール違反の編集を完全に防げる」は誤解です。防げるのはフィードバックが必ず返ることまでで、「そもそも書き込ませない」という強いブロックがしたいなら、次に出てくるPreToolUseを使う必要があります。
その他の代表的なイベント(まずは名前だけ知っておく)
- SessionStartClaude Codeとの会話が始まった瞬間。駅が開店するタイミングです
- UserPromptSubmitあなたが指示を送った瞬間。利用者が改札に近づいてきたタイミングです
- StopClaudeが「作業完了」と判断した瞬間。その日の営業を終えるタイミングです
- NotificationClaude Codeが何かを知らせようとする瞬間。駅内アナウンスのイメージです
もっと全部見てみたい人へ(上級者向け・眺めるだけでOK)
この他にも、権限確認のPermissionRequest、サブエージェントの開始・終了を示すSubagentStart/SubagentStop、作業ディレクトリの変更を示すCwdChanged、会話が長くなって要約される直前のPreCompactなど、合計で30種類ほどのイベントがあります。最初はPreToolUseとPostToolUseの2つが分かれば、実務の8割はまかなえます。
matcherで対象を絞り込む
matcherは、「どの操作の時だけ、このHookを動かすか」を絞り込むフィルターです。改札で言えば「PASMOの人だけ」「定期券の人だけ」のように、特定の条件の人だけをチェック対象にするイメージです。
| 書き方 | 意味 |
|---|---|
"Bash" | ターミナルでコマンドを実行するときだけ |
"Edit|Write" | ファイルの編集、または書き込みのときだけ(|は「または」の意味) |
"mcp__.*" | 外部サービス連携(MCP)のツールなら、なんでも(.*は「なんでも当てはまる」の意味) |
⚠️ 地味に間違えやすいポイント
matcherは大文字・小文字を区別します。"bash"と小文字で書いても、Bashという名前のツールには一致しません。コピー&ペーストして使うのが安全です。
実務で使えるレシピ集
ここからは、実際の設定例を「レシピ」としてまとめました。まずは動かしてみて、感覚をつかむのが一番の近道です。
保存したら自動でコードを整える
PostToolUseEdit|Writeファイルを編集・保存するたびに、フォーマッターを自動で走らせます。「フォーマットをお願いね」と毎回頼む手間がなくなります。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\"" }
]
}
]
}
}
危険なコマンドを未然にブロックする
PreToolUseBashファイルを一括削除するような、取り返しのつかないコマンドを、実行される前に食い止めます。
#!/bin/bash
# stdinからツールの入力(JSON)を受け取り、コマンド内容を確認する
INPUT=$(cat)
if echo "$INPUT" | grep -q "rm -rf"; then
echo "危険なコマンドのため、実行をブロックしました。" >&2
exit 2
fi
exit 0
秘密ファイル(.env など)を読ませない
PreToolUseEdit|Write|ReadAPIキーなどが入った設定ファイルに、Claudeがうっかりアクセスしないようにします。
#!/bin/bash
INPUT=$(cat)
if echo "$INPUT" | grep -q "\.env"; then
echo ".envファイルへのアクセスは許可されていません。" >&2
exit 2
fi
exit 0
DESIGN.mdの検証を自動で走らせる
PostToolUseEdit|Write以前の章で話した「DESIGN.mdのルールを本当に守らせたい」という悩みへの、実際の答えです。編集のたびに検証を走らせ、問題があればClaudeへ即座にフィードバックします。
#!/bin/bash
npx @google/design.md lint DESIGN.md
if [ $? -ne 0 ]; then
echo "DESIGN.mdの検証エラーです。色やコントラスト比を見直してください。" >&2
exit 2
fi
exit 0
📍補足:PostToolUseなので「すでに書かれた編集」を取り消すことはできませんが、問題があれば必ずClaudeに伝わるため、次のターンで自分から直しにいく可能性が高くなります。
作業が終わったら通知で知らせる
Stop長い作業が終わったタイミングで、音や通知で教えてもらいます。他の作業をしながら待てるようになります。
{
"hooks": {
"Stop": [
{ "hooks": [ { "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" } ] }
]
}
}
セッション開始時に最新の変更履歴を見せる
SessionStart会話を始めるたびに、直近のGitの履歴をClaudeに渡し、「前回何をしていたか」を思い出しやすくします。
{
"hooks": {
"SessionStart": [
{ "hooks": [ { "type": "command", "command": "git log --oneline -10" } ] }
]
}
}
つまずきやすいポイント
⚠️ その1:PostToolUseは「取り消し」ではない
何度でも繰り返しますが、これが一番多い勘違いです。PostToolUseは「もう起きたことについて、Claudeに伝える」仕組みで、「起きなかったことにする」仕組みではありません。
⚠️ その2:matcherの大文字・小文字
Bashとbashは別物として扱われます。公式のツール名をそのままコピーするのが安全です。
⚠️ その3:最初から作り込みすぎない
Hookは強力な分、複雑にしすぎると「なぜ動かないのか」が分かりにくくなります。最初は1つのシンプルなHookから始めて、慣れてきたら少しずつ増やしていきましょう。
自分で作ってみよう
ここまで読んで「自分で書くのは大変そう」と感じたなら、朗報があります。実は、自分でJSONやスクリプトを書かなくても大丈夫です。
- Claude Codeに、日本語でお願いする。「ファイルを保存したら自動でPrettierを走らせるHookを書いて」のように頼むだけで、設定ファイルとスクリプトを一緒に作ってくれます。
- まずは1つだけ試す。この章で紹介したレシピの中から、いちばん自分に必要そうなものを1つだけ選んで試してみましょう。
/hooksで確認する。ターミナルで/hooksと入力すれば、今どんなHookが設定されているか、一覧で確認できます。- 少しずつ育てる。慣れてきたら、他のレシピも1つずつ足していきましょう。
お疲れさまでした
CLAUDE.mdは駅員さんへのお願い、Hookは自動改札そのもの。この1行さえ覚えていれば、あとは必要なときにこの教科書に戻ってくれば大丈夫です。
参考文献(この教科書は以下の一次情報をもとに作成しました)
・Anthropic公式 Claude Code Docs「Hooks reference」 code.claude.com/docs/en/hooks
・Anthropic公式 Claude Code Docs「Best practices for Claude Code」 code.claude.com/docs/en/best-practices