Claude Codeのhooks(フック)は、「ファイルを編集した後」「コマンドを実行する前」といった節目ごとに、あらかじめ登録したコマンドをClaude Code自身に実行させる仕組みです。CLAUDE.mdに「編集したら整形して」と書いても、Claudeが忘れることはあります。hooksなら、Claudeの判断に任せず、毎回同じ処理を動かせます。

この記事は、Anthropicの公式ドキュメント(hooksの入門ガイドとリファレンス、設定・権限のページ)と公式の変更履歴を2026年10月21日に確認して書いています。図は公式ドキュメントに掲載されたものです。編集部は、公式の例のスクリプト2本に見本の入力を渡して結果を確かめましたが、Claude Codeの中でhooksを動かした実測は行っていません。

公式の変更履歴で確かめた時点の最新版はv2.1.305です。細かい仕様は、手元の版の公式ドキュメントで確かめてください。

Claude Codeのhooksとは:決まった時点で必ず動く処理

公式の入門ガイドは、hooksを「Claude Codeの動きの決まった時点で実行される、ユーザーが定義したシェルコマンド」と説明しています。Claudeがファイルを編集した、ツールを使おうとしている、返答を終えた、といった出来事(イベント)が起きるたびに、設定しておいたコマンドが動きます。

ポイントは「必ず動く」ことです。CLAUDE.mdやスキルに書いた指示は、Claudeが読んで判断する材料です。守られることが多くても、毎回の実行は保証されません。hooksは設定ファイルの決まりとしてClaude Code本体が動かすので、整形・記録・禁止のような「毎回同じでよい処理」に向いています。

仕組み誰が動かすか向いている使い方
CLAUDE.md・スキルClaudeが読んで判断する進め方や前提知識を伝える
権限ルール(allow・deny)Claude Codeが許可・拒否を決める使ってよいツールやコマンドを固定する
hooksClaude Codeが決まった時点で必ず実行する整形、通知、記録、条件付きの禁止、情報の追加
modsClaude Codeの中でJavaScriptの関数として動く画面の表示や独自のコマンドまで変えたい

hooksが動くタイミング:主なイベント

hooksは、イベントごとに設定します。公式リファレンスの一覧には、2026年10月21日時点で33種類のイベントが載っています。以前より種類が増えているため、少し前の解説記事とは数が合わないことがあります。最初に覚えるのは、次の表の7つで十分です。

イベント動くタイミング使い方の例
SessionStartセッションの開始・再開時(長くなった会話を要約して詰める「圧縮」の後も含む)作業の前提をClaudeへ渡す
UserPromptSubmitプロンプトを送った直後、Claudeが処理する前毎回の依頼に情報を足す、送信を止める
PreToolUseツールを実行する前危ないコマンドや大事なファイルの編集を止める
PermissionRequest許可を求める画面を出す時決まった確認だけ自動で許可する
PostToolUseツールが成功した後編集したファイルを整形する、実行したコマンドを記録する
NotificationClaude Codeが通知を出す時入力待ちをデスクトップ通知で知らせる
StopClaudeが返答を終えた時終わってよいかを確かめる
公式画像Anthropic「Hooks reference」掲載・2026年10月21日確認
hooksのイベントが動く順番の公式図。SessionStartの後、ターンごとにUserPromptSubmit、ツールの前後のPreToolUse・PermissionRequest・PostToolUseなどが回り、最後にStopが動く。NotificationやFileChangedなどは流れとは別に動き、終わりにSessionEndが動く

公式図:hooksのイベントが動く順番(Anthropic「Hooks reference」掲載。2026年10月21日確認)

図のとおり、イベントには「セッションに1回」「依頼1回ごと」「ツールを使うたび」の3つの頻度があります。

最初のhooksを設定する手順:入力待ちを通知する

公式ガイドの最初の例は、Claudeが入力や許可を待っている時に、デスクトップ通知を出すhookです。ターミナルを見張らずに、ほかの作業ができるようになります。

設定ファイルにhooksを書く

自分のすべてのプロジェクトで使うなら、~/.claude/settings.jsonに書きます。ファイルがなければ作ります。macOSの場合は次のとおりです。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

すでにhooksの項目がある場合は、全体を置き換えずに、Notificationを同じhooksの中へ並べて追加します。置き換えると、前からあったhooksが消えてしまいます。LinuxとWindows用の例も公式ガイドにあります。なお、hooksの設定はClaudeに「入力待ちの時に通知するhookを書いて」と頼んで作らせることもできます。

/hooksで設定が読み込まれたか確かめる

Claude Codeの入力欄で/hooksと入力すると、設定済みのhooksの一覧が開きます。Notificationの下に今のhookが出ていれば読み込まれています。この一覧は見るための画面で、ここから編集はできません。それぞれのhookがどの設定ファイルやプラグインから来たかも表示されます。

実際に試すには、まずShift+Tabを押して、画面下の表示が⏸ manual mode onになるまで切り替えます。許可の確認が毎回出る状態にしてから、許可が必要な作業をClaudeに頼み、ほかのアプリに切り替えて待ちます。デスクトップに通知が出れば成功です。今回はmatcherを空にしたので、このhookはすべての種類の通知で動きます。絞りたい時は、matcherに通知の種類を書きます。公式には12種類の値があり、主なものは次の3つです。

matcherの値動く時
permission_promptツールの許可を求める画面が出て、約6秒何も入力していない時(デスクトップ版やVS Codeでは数え方が異なる)
idle_promptClaudeが返答を終えてから約60秒、利用者が何も入力していない時
agent_completedバックグラウンドのセッションが終わった、または失敗した時(エージェントビューを開いている間だけ)

macOSで通知が出ない場合、公式ガイドは「スクリプトエディタ」に通知の許可がないことを原因に挙げています。ターミナルでosascript -e 'display notification "test"'を一度実行してから、システム設定の「通知」でスクリプトエディタの通知を許可してください。

hooksを書く場所と、効く範囲

hooksは、どのファイルに書くかで効く範囲が決まります。チームで同じルールを使うなら、プロジェクトの設定ファイルに書いてリポジトリに入れます。

書く場所効く範囲人と共有できるか
~/.claude/settings.json自分のすべてのプロジェクトできない(自分のパソコンだけ)
.claude/settings.jsonそのプロジェクトできる(リポジトリに入れられる)
.claude/settings.local.jsonそのプロジェクトできない(自分だけの設定)
組織の管理設定組織全体管理者が配る
プラグインのhooks/hooks.jsonプラグインを有効にしている間プラグインと一緒に配れる
スキル・サブエージェントの先頭の設定スキルを呼び出した後はそのセッションが終わるまで、サブエージェントは動いている間ファイルと一緒に配れる

複数の場所に書いたhooksは、置き換えではなく足し合わされます。また、クラウドで動くセッションは、手元の~/.claude/settings.jsonを読みません。手元では動くのにクラウドでは動かない時は、書いた場所を確かめてください。

hooksの設定の読み方:イベント・matcher・実行する処理

hooksの設定は3段の入れ子になっています。公式リファレンスの説明に沿うと、次の順に読みます。

  1. イベント:いつ動かすか(例:PreToolUse)
  2. matcher(マッチャー):そのイベントの中で、どの場合に絞るか(例:Bashツールの時だけ)
  3. 実行する処理:何を動かすか(例:typeがcommandのシェルコマンド)

ツールのイベントでは、matcherにツール名を書きます。"Edit|Write"のように|でつなぐと「編集か書き込みの時」になります。外部サービスとつなぐMCPのツールはmcp__サーバー名__ツール名という名前なので、mcp__github__.*と書けばGitHubサーバーのすべてのツールが対象になります。matcherは大文字と小文字を区別します。

さらに細かく絞りたい時は、処理の側にifを書きます。"if": "Bash(git *)"とすれば、Bashの中でもgitのコマンドの時だけスクリプトが起動します。公式リファレンスの次の図は、matcherとifの両方が合った時だけhookが動き、合わなければそのままツールが実行される流れを示しています。

公式画像Anthropic「Hooks reference」掲載・2026年10月21日確認
hookが動くかどうかの判定の公式図。Claudeがrm -rf /tmp/buildを実行しようとするとPreToolUseが起き、matcherのBashと、ifのBash(rm *)の両方に合うとblock-rm.shが動いて拒否を返し、ツールの実行が止まる。どちらかに合わなければhookは動かず、ツールが実行される

公式図:matcherとifでhookが動くかが決まる流れ(Anthropic「Hooks reference」掲載。2026年10月21日確認)

ただし公式ガイドは、ifによる絞り込みは「できる範囲での判定」であり、絶対に許可・拒否したいものは権限の仕組みを使うよう勧めています。この点は次の節でもう一度触れます。

hooksでツールの実行を止める方法

hooksの代表的な使い道が、PreToolUseで危ない操作を実行前に止めることです。hookのスクリプトは、Claude Codeから操作の内容をJSONという形式で受け取ります(標準入力)。結果は、終わる時の番号(終了コード)か、書き出すJSON(標準出力)のどちらかで返します。

終了コード2で止める

公式ガイドの例は、.envやpackage-lock.json、.git/の中のファイルの編集を止めるスクリプトです。.claude/hooks/protect-files.shに保存し、chmod +xで実行できるようにしてから、.claude/settings.jsonに登録します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

スクリプトは、編集しようとしているファイルのパスに保護したい文字列が含まれていれば、理由をエラー出力(標準エラー)に書いてexit 2で終わります。終了コード2は「止める」という意味で、書いた理由はClaudeに伝わり、Claudeは別のやり方を考えます。一方、exit 0は「このhookとしては何も決めない」という意味です。許可したことにはならず、通常の許可の確認がそのまま行われます。

編集部は、このスクリプトを公式ガイドのとおりに保存し、見本の入力を渡して結果を確かめました(macOS、jq 1.7.1。Claude Codeの中では動かしていません)。.envと.git/configは終了コード2で止まり、src/app.jsは0で通りました。ただし、文字列を含むかどうかで判定するため、.env.exampleやdocs/.envrc-guide.mdのような、止めたくないファイルも止まりました。自分のプロジェクトで使う時は、保護したいファイル名に合わせてパターンを直してください。

JSONで理由と判断を返す

終了コードでは「止める」か「何もしない」しか選べません。より細かく決めたい時は、exit 0で終わり、標準出力に次の形のJSONを書きます。

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Use rg instead of grep for better performance"
  }
}

permissionDecisionには、止めるdeny、利用者に確認画面を出すask、確認を省いて進めるallowなどを返せます。denyは、すべての許可を省くモードで起動していても有効です。逆にallowを返しても、設定ファイルの拒否ルール(deny)や確認ルール(ask)を超えて許可することはできません。複数のhooksが違う答えを返した時は、厳しい答えが優先されます。強い順にdeny(止める)、defer(判断を後に回す。-pでの実行時だけ使える)、ask(確認する)、allow(許可する)です。

permissionDecisionやadditionalContextは、hookSpecificOutputの中に入れます。外側に書くと、エラーも出ずに無視されます。一方で、StopやPostToolUseのdecisionのように外側(いちばん上の階層)に置く項目もあり、置き場所はイベントごとに違います。

サンプルのまま「安全装置」にしない

公式リファレンスには、rm -rfを含むBashのコマンドをdenyで止めるblock-rm.shの例もあります。編集部が見本の入力で試したところ、rm -rf /tmp/buildには拒否のJSONを返しましたが、オプションの順番を変えたrm -fr /tmp/buildには何も返しませんでした。Claude Codeの中では、このhookは判断をせず、通常の許可の確認に進むことになります。編集部の見方では、これは仕組みを説明するための短い例です。

前の節で触れたとおり、hooksでの絞り込みは確実な判定ではありません。公式ガイドは、許可・拒否を固定したいものには、hooksより権限の仕組みを使うよう勧めています。ただし公式の権限ページによると、拒否ルール(deny)もClaudeが書いたコマンドの文字列で判定するため、/bin/rmやbash -c 'rm …'のような別の書き方は止まらず、セキュリティの境界ではないとされています。ファイルや通信を確実に制限したい時は、サンドボックス(実行できる範囲を区切る機能)を組み合わせます。編集部の整理としては、拒否ルールとサンドボックスで土台を固め、hooksは記録や追加の確認に使う、という役割分担が安全です。

よく使われるhooksの設定例

公式ガイドの例を、目的ごとにまとめました。

やりたいことイベントmatcher中身
編集したファイルを自動で整形するPostToolUseEdit|Write編集したファイルのパスをjqで取り出し、Prettierで整形する
会話の圧縮の後に前提を伝え直すSessionStartcompactプロジェクトの約束ごとをechoで出し、Claudeに渡す
計画の承認だけ自動で許可するPermissionRequestExitPlanMode許可を表すJSONを返す
実行したBashのコマンドを記録するPostToolUseBashコマンドの文字列をファイルに追記する

整形の例は、プロジェクトの.claude/settings.jsonに"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"と書く1行です。公式ガイドの例の多くは、JSONを読むためにjqを使います。入っていなければ、macOSではbrew install jqで入れます。また、Claudeはシェルのコマンドでもファイルを書き換えられるため、Edit|Writeだけではすべての変更を拾えません。すべての変更を見たい時は、返答の終わりに作業中のフォルダーをまとめて調べるStopを使うか、Bashも対象にしてgit status --porcelainで変更を調べる方法が公式ガイドで紹介されています。特定のファイルだけなら、何が書き換えても反応するFileChangedを使えます(監視するファイル名を指定します)。

自動で許可するhookを使う時は、matcherをできるだけ狭く絞ってください。matcherを空や.*にすると、ファイルの書き込みやシェルのコマンドまで、すべての許可を自動で通してしまいます。許可の確認そのものを減らしたい時は、autoモードの仕組みも比べてみてください。

会話の圧縮の後に前提を伝え直す例は、長い作業の途中で、Claudeが最初の指示を忘れやすいと感じている人に向いています。圧縮の仕組みは自動コンパクトの解説で説明しています。

コマンド以外のhooks:prompt・agent・HTTP・MCPツール

hooksの処理は、シェルコマンド(type: "command")のほかに4種類あります。

  • prompt:Claudeのモデルに1回だけ判定させます。例えばStopで「頼まれた作業が全部終わったか」を確かめ、終わっていなければ理由を返してClaudeに作業を続けさせられます。
  • agent:ファイルを読んだりコマンドを実行したりできるサブエージェントに確かめさせます。公式ドキュメントでは実験的な機能とされており、本番の運用ではコマンドのhooksが勧められています。
  • http:イベントの内容を指定のURLへ送ります(チーム共通の記録サーバーなど)。
  • mcp_tool:設定済みのMCPサーバーのツールを呼び出します。

決まりで判断できるものはコマンド、判断が必要なものはprompt、実際のファイルを調べる必要があるものはagent、と使い分けるのが公式の考え方です。編集部の補足として、prompt・agentはモデルを呼び出すため、その分のトークンを使い、プランの利用枠やAPI料金に反映されると考えられます。

hooksを使う前の安全確認

コマンドのhooksは、あなたのアカウントが持つ権限をすべて使ってシェルコマンドを実行する、と公式リファレンスは警告しています。つまり、あなたが触れるファイルは、hookのコマンドも読み書き・削除できます。入れる前に、次の点を確かめてください。

  • 中身を読んでから入れる:他人が作ったリポジトリやプラグインに入っているhooksは、何を実行するか確認してから使います。
  • フォルダーの信頼を確認する:対話で使う時は、起動時に出る「このフォルダーを信頼しますか」の確認で許可するまで、設定ファイルのhooksは実行されません。
  • claude -pに注意する:画面を開かずに1回だけ実行する-pやSDKで動かす時は、信頼の確認が出ず、フォルダーは信頼済みとして扱われます。自分が書いていないリポジトリで実行する前は、.claude/の設定を確認するか、--settings '{"disableAllHooks": true}'でその回だけhooksを止めます。
  • 書き方の基本を守る:入力をそのまま信じない、変数は"$VAR"と引用符で囲む、スクリプトは絶対パスで指定する、などが公式に挙げられています。

また、管理設定がなく、TeamやEnterpriseプランのログインも使っていない環境では、入れているmodsが、PreToolUseのhookで止めた操作を許可できる場合があると公式ガイドは注記しています。hooksで止めているつもりでも、入れているmodsも確かめてください。

会社で使う場合は、管理者が組織の管理設定でallowManagedHooksOnlyを設定すると、個人・プロジェクト・プラグインのhooksを動かさず、管理設定と、管理側で強制的に有効にしたプラグインのhooksだけに限定できます。

hooksが動かない・効かない時の確認

公式ガイドのトラブル対処から、よくある症状と確かめる順番をまとめます。

hookが動かない

  • /hooksで正しいイベントの下に出ているかを見ます。出ていなければ、JSONの書き間違い(余分なカンマ、コメント)とファイルの場所を確かめ、セッションを開き直します。
  • matcherがツール名と大文字・小文字まで一致しているかを見ます。
  • PreToolUse(実行前)とPostToolUse(実行後)を取り違えていないかを見ます。
  • /hooksに「Only hooks from managed settings run here」と出る時は、組織の設定で管理設定以外のhooksが止められています。

「hook error」と表示される

スクリプトが想定外の終了コードで終わっています。公式ガイドのとおり、見本のJSONを渡して単体で動かすと原因を切り分けられます。

echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
echo $?

「command not found」なら絶対パスか$CLAUDE_PROJECT_DIRで指定し、jqがなければ入れます。chmod +xで実行の許可も付けます。

JSONを返しているのに効かない

よくある原因は2つです。1つは、シェルの設定ファイル(~/.bashrcなど)が文字を出力し、JSONの前に余計な行が入っているケースです。hooksは通常、対話でないシェルで動きますが、Git BashやBASH_ENVの設定など一部の環境では設定ファイルが読み込まれます。出力が{で始まらないとJSONとして読まれません。もう1つは、permissionDecisionなどの項目をhookSpecificOutputの外に書いているケースです。どちらも、claude --debugで起動してデバッグの記録を見ると見つけられます。

Stopのhookで作業が終わらない

Stopのhookが毎回「まだ終わらないで」と返すと、Claudeは返答を終えられず、作業を続けることになります。ただしClaude Codeは、ツールを使わないまま8回続けて終了を止められると、hookを無視して返答を終えます。スクリプトでは入力のstop_hook_activeを確かめ、trueならexit 0で終わるようにします。

hookが何をしたかは、Ctrl+Oで開く記録の画面で確かめられます。成功時は基本的に何も表示されないので、結果そのものを見て確認します。すべてのhooksを一時的に止めたい時は、設定ファイルに"disableAllHooks": trueを書きます。ただし、管理設定のhooksは止まらず、プロジェクトの設定にfalseがあると自分の設定のtrueは上書きされます。プロジェクトの設定に関係なく、その回だけ止めたい時は、--settings '{"disableAllHooks": true}'を付けて起動します。設定に残したまま、1つのhookだけを止める方法はないため、1つだけ止めたい時は、そのhookを設定から削除します。

まとめ:hooksは「毎回同じでよい処理」から小さく始める

Claude Codeのhooksは、Claudeの判断に任せず、決まったタイミングで必ずコマンドを動かす仕組みです。通知・整形・記録のように、毎回同じでよい処理から始めると、効果が分かりやすく安全です。

止める用途に使う時は、公式の例をそのまま安全装置にしないことが大切です。権限の拒否ルールとサンドボックスで土台を固め、hooksは記録や追加の確認に使います。/hooksでの確認と、見本の入力での単体テストを習慣にしましょう。Claude Code全体のできることや使い始め方を確認したい方は、Claude Codeとは?できること・料金・利用環境の選び方から読み始めてください。