Amazonで商品を見るセール会場へ

Claude Code│Hooksの設定方法|ファイル保存後の処理と危ないコマンドの止め方

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ツールが失敗したあと
NotificationClaude Codeが通知を出すとき
SubagentStart・SubagentStopサブエージェントが始まったとき・終わったとき
StopClaudeが返事を書き終えたとき
Claude Code公式ドキュメント「Automate actions with hooks」から主なものを抜粋

ほかにも、圧縮の前や設定の変更時など、細かいイベントがあります。

スポンサーリンク

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 にすると、許可の確認で待っているときだけに絞れます。

動かないときの確かめ方

  1. 対話中に /hooks を開き、イベントの横に設定の数が出ているかを見る
  2. settings.json がJSONとして正しいか(末尾のカンマなど)を見る
  3. フックへサンプルJSONを標準入力で渡して単独実行し、終了コードと標準エラーを確認する
  4. 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日に照合しました。実機でのフック統合・通知・権限拒否の再現は今回行っていません。

最新は公式ページで確認してください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

生成AIのおすすめ書籍

周辺機器の優先度

目次