Hooks(フック)は、Claude Codeが決まったタイミングで自動的に実行するコマンドです。
CLAUDE.md に書いた指示は守られないこともありますが、有効なフックはイベントと条件に従って実行されます。ただし無効化、未信頼の設定、起動失敗やタイムアウトがあり、実行成功を保証するものではありません。
- 書く場所:settings.json の hooks の中
- よく使うタイミング:ツールを使う前(PreToolUse)と使った後(PostToolUse)
- 実行前に止めたいとき:同期のPreToolUseフックで終了コード2を返す
- 確認:対話中に /hooks で一覧を見る
2026年10月23日に公式資料と照合しました。実行記録はWindows上のv2.1.284での9月29日の結果です。以下の例はコマンド型のフックで、現在はほかの種類もあります。
フックが動くタイミング
フックは、イベントと呼ばれるタイミングごとに設定します。
| イベント | 動くタイミング |
|---|---|
| SessionStart | セッションを始めたとき・再開したとき |
| UserPromptSubmit | こちらが指示を送った直後、Claudeが読む前 |
| PreToolUse | ツール(コマンドの実行やファイルの書き込み)を使う直前。止められる |
| PermissionRequest | ツールを使うのに許可が要るとき |
| PostToolUse | ツールを使い終えて成功したあと |
| PostToolUseFailure | ツールが失敗したあと |
| Notification | Claude Codeが通知を出すとき |
| SubagentStart・SubagentStop | サブエージェントが始まったとき・終わったとき |
| Stop | Claudeが返事を書き終えたとき |
ほかにも、圧縮の前や設定の変更時など、細かいイベントがあります。
settings.jsonの書き方
フックは、settings.json の hooks の中に、イベント名ごとに書きます。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "python .claude/hooks/log_edit.py" }
]
}
]
}
}matcher は、どのツールのときに動かすかの指定です。
Write|EditはWriteまたはEditツールに一致します。エディターでの手動保存や、Bash・PowerShell経由の変更をすべて監視するものではありません。
空にすると、そのイベントのたびに毎回動きます。
書くファイルは、自分の全プロジェクトならホームの .claude/settings.json、チームで共有するならプロジェクトの .claude/settings.json です。
既存のhooksを保持し、別イベントはキーを追加します。同じイベントへの追加は既存の配列へ要素を足し、同名キーを重複させないでください。
フックに渡される情報
フックのコマンドには、イベントの中身がJSONで標準入力から渡されます。
{
"session_id": "abc123",
"cwd": "/Users/sarah/myproject",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
}
}上は公式ドキュメントに載っている例です。
tool_name で使うツールが、tool_input でその中身(コマンドやファイルのパス)が分かります。
例1:ファイルを書いたら記録する
Pythonで、書き込まれたファイルのパスを hooks.log に残すスクリプトを作りました。
import json, sys, datetime
data = json.load(sys.stdin)
path = data.get("tool_input", {}).get("file_path", "")
with open("hooks.log", "a", encoding="utf-8") as f:
f.write(f"{datetime.datetime.now():%H:%M:%S} {data['tool_name']} {path}\n")この例はPythonを実行でき、プロジェクト直下で動かす前提です。.claude/hooks/log_edit.pyに保存し、PostToolUseから呼びます。相対パスのhooks.logは実行時の作業ディレクトリに作られます。移動先やworktreeで使う場合はパスを見直してください。
Claudeに hello.txt を作ってもらうと、hooks.log に次の1行が増えました。
13:24:17 Write C:\demo\hooks-demo\hello.txt同じ形で、ファイルを書いたあとに整形ツールやテストを動かせます。
例2:特定の文字列を含むBash呼び出しを止める
PreToolUse のフックが終了コード2で終わると、そのツールの実行は止められます。
そのとき標準エラーに書いた文は、理由としてClaudeに伝わります。
次のPythonコードを、プロジェクト内の.claude/hooks/block_rm.pyに保存してから設定を追加してください。
import json, sys
data = json.load(sys.stdin)
cmd = data.get("tool_input", {}).get("command", "")
if "rm " in cmd:
print("rm は使わないでください。消すファイルは人が確かめます。", file=sys.stderr)
sys.exit(2){
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "python .claude/hooks/block_rm.py" }
]
}
]
}
}Claudeに「rm hello.txt で消して」と頼んだ結果です。
消せませんでした — `.claude/hooks/block_rm.py` の PreToolUse フックが `rm` をブロックしたためです(「rm は使わないでください。消すファイルは人が確かめます。」)。`hello.txt` は残っています。コマンドの実行を許可していても、フックが先に止めています。
これは終了コード2の動作を学ぶ簡易例です。echo "rm test"のような無害な文字列も止め、PowerShellのRemove-Itemや別の削除経路は防ぎません。削除全般の防止には使えません。
終了コードとJSONの返し方
| 終わり方 | どうなるか |
|---|---|
| 終了コード0 | 有効なJSONの判断があれば適用。出力がなければ通常の権限判定へ進む |
| 終了コード2 | その操作を止める。標準エラーの文が理由として伝わる(止められないイベントもある) |
| それ以外の終了コード | 通常はエラーとして続行。onFailureやWindows環境などに例外あり |
判断をJSONで返す場合は、終了コード0で標準出力へ書きます。同期のPreToolUseの例と仕様は公式Hooks referenceを確認してください。
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "grep ではなく rg を使ってください"
}
}PreToolUseのJSONではdenyが拒否、askが確認要求、allowが承認を意味します。ただしallowでも既存のdeny/ask規則などを無効にはできません。非対話用途にはdeferもあります。
終了コード2とJSONは、1つのフックでどちらか片方だけを使います。
JSONで判断を返す場合は、診断メッセージを標準エラーへ出し、標準出力のJSONより前に案内文などを混ぜないでください。
JSONが反映されないときは、permissionDecisionがhookSpecificOutputの中にあるかも確認します。
Windowsで入力待ちを知らせる
Claudeがこちらの入力を待っているときに知らせる例です。
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
}
]
}
]
}
}この例はNotification全体を対象にするダイアログです。入力待ちだけとは限らず、閉じるまで待機するため、常用する前に対象イベントとタイムアウトを確認してください。今回ダイアログは実行していません。
matcher を permission_prompt にすると、許可の確認で待っているときだけに絞れます。
動かないときの確かめ方
- 対話中に /hooks を開き、イベントの横に設定の数が出ているかを見る
- settings.json がJSONとして正しいか(末尾のカンマなど)を見る
- フックへサンプルJSONを標準入力で渡して単独実行し、終了コードと標準エラーを確認する
claude --debugで起動し、~/.claude/debug/内のログでフックのエラーを見る(端末への直接表示ではない)
フックは、自分のPCの権限でそのままコマンドを実行します。
この記事のPython例はjson.load(sys.stdin)で入力を読むため、コマンドだけを起動すると入力待ちになる場合があります。
PowerShellではプロジェクト直下から、次のようにJSONを渡して終了コードを確認できます。
'{"tool_name":"Bash","tool_input":{"command":"rm hello.txt"}}' | python .claude/hooks/block_rm.py
$LASTEXITCODE
このテストはコマンド文字列をPythonへ渡すだけで、rm自体は実行しません。
例のスクリプトなら理由が標準エラーへ出て終了コードは2となり、commandをecho helloに変えると0になります。
2026年10月27日の確認では、PythonスクリプトへJSONを渡した単体実行でこの2通りを確認しました。
PowerShellのパイプ操作とClaude Codeからのフック起動は今回検証していません。
ほかの人が書いたプロジェクトの settings.json を使うときは、中身を読んでから信頼してください。
settings.json の置き場所と優先順位は、Claude Codeのsettings.jsonの場所と優先順位で紹介しています。
まとめ
- フックは有効な設定と条件に従って動く。実行結果も確認する
- settings.json の hooks に、イベント名・matcher・コマンドを書く
- イベントの中身はJSONで標準入力から受け取る
- PreToolUse で終了コード2を返すと、その操作を止められる
- 動かないときは /hooks と
claude --debugで確かめる
参考:Claude Code公式ドキュメント「Automate actions with hooks」(2026年10月23日に再確認)。
よくある質問:Claude CodeのHooks
Claude Codeのフック(Hooks)とは、何ですか?
Claude Codeが決まったタイミングで自動的に実行するコマンドです。
CLAUDE.md に書いた指示は守られないこともありますが、有効なフックはイベントと条件に従って実行されます。ただし無効化、未信頼の設定、起動失敗やタイムアウトがあり、実行成功を保証するものではありません。
フックは、どんなタイミングで動かせますか?
SessionStart(セッションを始めたとき・再開したとき)、UserPromptSubmit(指示を送った直後)、PreToolUse(ツールを使う直前。止められる)、PermissionRequest(許可が要るとき)、PostToolUse(ツールを使い終えて成功したあと)、PostToolUseFailure(失敗したあと)、Notification(通知を出すとき)、SubagentStart・SubagentStop、Stop(返事を書き終えたとき)などです。
ほかにも、圧縮の前や設定の変更時など、細かいイベントがあります。
フックは、どこに書きますか?
settings.json の hooks の中に、イベント名ごとに書きます。
自分の全プロジェクトならホームの .claude/settings.json、チームで共有するならプロジェクトの .claude/settings.json です。
既存のhooksを保持し、別イベントはキーを追加します。同じイベントへの追加は既存の配列へ要素を足し、同名キーを重複させないでください。
matcher は、何を決めますか?
どのツールのときに動かすかの指定です。
Write|EditはWriteまたはEditツールに一致します。エディターでの手動保存や、Bash・PowerShell経由の変更をすべて監視するものではありません。
空にすると、そのイベントのたびに毎回動きます。
フックのコマンドには、どんな情報が渡されますか?
イベントの中身がJSONで標準入力から渡されます。
tool_name で使うツールが、tool_input でその中身(コマンドやファイルのパス)が分かります。
危ないコマンドを、フックで止めるには?
PreToolUse のフックが終了コード2で終わると、そのツールの実行は止められます。
標準エラーに書いた文は、理由としてClaudeに伝わります。
記事の確認では、コマンドの実行を許可していても、フックが先に止めました。
例はBash入力の部分文字列を検出するだけです。誤検出や見逃しがあり、PowerShellや別ツールの削除を防ぐものではありません。
終了コードは、どう使い分けますか?
終了コード0でも、標準出力の有効なJSONで拒否などを指定できます。出力なしは通常判定へ戻るだけです。終了コード2の効果はイベントごとに異なります。
通常の失敗は処理を止めない場合があります。v2.1.295以降のonFailure: "block"など例外があるため、使用版と設定を確認してください。非同期フックは実行前の拒否には使えません。
判断をJSONで返す場合は、終了コード0で標準出力へ書きます。同期のPreToolUseの例と仕様は公式Hooks referenceを確認してください。
PreToolUseではdeny・allow・askに加え、非対話用途のdeferがあります。allowでもdeny/ask規則や対話必須の操作は別に評価されます。JSONは終了コード0で返します。
フックが動かないときは、どう確かめますか? 安全面の注意は?
対話中に /hooks を開き、イベントの横に設定の数が出ているかを見ます。
settings.json がJSONとして正しいか(末尾のカンマなど)、フックへサンプルJSONを標準入力で渡して単独実行できるかを確認し、claude --debug で起動し、~/.claude/debug/内のログを読みます。端末に直接表示されるわけではありません。
フックは、自分のPCの権限でそのままコマンドを実行するので、ほかの人が書いたプロジェクトの settings.json を使うときは、中身を読んでから信頼してください。
公式仕様は2026年10月23日に照合しました。実機でのフック統合・通知・権限拒否の再現は今回行っていません。
最新は公式ページで確認してください。
