Claude CodeのHooksの使い方メモ(2026年4月)
今回は、Mac(macOS 26.3.1)でのClaude Codeで使えるHooks(フック)の設定方法と使い方を整理します。
あくまで筆者の環境での運用に基づく内容なので、お使いの環境 やバージョンによって異なる場合があります。また、2026年4月時点の情報である点にご留意ください。
Claude Codeは会話の中でファイルの編集やコマンドの実行をしますが、その前後で何かを自動実行したい場面があります。編集のたびにフォーマッタを走らせたい、危ないファイルの変更をブロックしたい、応答が終わったら通知をさせたいなどあると思います。Hooksはこうした自動処理を設定するための仕組みです。
この記事のターゲット
Claude Codeの作業に自動処理を組み込みたい方
ファイル編集後のフォーマッタ自動実行を設定したい方
特定ファイルへの変更をブロックしたい方
Hooksとは
Hooksは、Claude Codeのライフサイクルの特定のタイミングで自動実行される処理です。
CLAUDE.mdに「フォーマッターを実行してください」と書いても、スキップされることがあります。CLAUDE.mdの指示は確率的で、遵守率は100%ではありません。Hooksはスクリプトとして毎回実行されるため、確実に動きます。「毎回必ず実行してほしい処理」にはHooksが向いています。
Hookのタイプは4種類あります。シェルコマンド(command)、HTTPリクエスト(http)、LLMプロンプト(prompt)、サブエージェント(agent)。ほとんどの用途ではcommandを使います。
設定方法
settings.jsonのhooksセクションに記述します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/format.sh"
}
]
}
]
}
}以下の記事で紹介した設定ファイルの配置場所(個人共通、プロジェクト共有、ローカル個人)のどこにでも書けます。
PostToolUseがイベント名、matcherがどのツールに反応するか、hooksの中に実行する処理を書きます。
主なイベント
PreToolUse
ツール実行前に発火します
ツールの実行を許可・拒否できるため、ファイル保護やコマンド検査に使います
PostToolUse
ツール正常完了後に発火します
フォーマッタの自動実行が典型的な使い方です。
Stop
Claudeの応答完了時に発火します
タスクの完了チェックに使えます
decision: "block"を返すとClaudeに作業の継続を指示できます
Notification
通知送信時に発火します
macOSのデスクトップ通知 やSlack連携に使います
SessionStart
セッションの開始・再開時に発火します
matcherで
compactを指定すると/compact後にコンテキストを再注入できます
ほかにもUserPromptSubmit(プロンプト送信直後)、SubagentStart/Stop(サブエージェントの開始・終了)、PreCompact/PostCompact(コンテキスト圧縮の前後)、FileChanged(ファイル変更監視)などのイベントがあります。
Matcherの書き方
matcherが空文字または省略だと、すべてにマッチします。Editのようにツール名を書くと完全一致です。Edit|Writeと|で区切るとOR条件になります。mcp__figma__.*のように正規表現も使えます。
ifフィールドを使うと引数レベルでフィルタできます。"if": "Bash(git *)"ならBashツールのうちgitコマンドのときだけ。"if": "Edit(*.ts)"ならTypeScriptファイルの編集時だけ発火します。フック自体の起動を条件で絞れるので、不要な実行を減らせます。
設定例
ファイル編集後の自動フォーマット
このブログでは、EditまたはWriteの後にPrettierを自動実行しています。実際に使っている設定です。
スクリプトはstdinからJSON形式でツールの入力を受け取り、ファイルの拡張子を見てPrettierを実行します。
#!/bin/bash
FILE_PATH=$(jq -r '.tool_input.file_path')
if [ -z "$FILE_PATH" ] || [ "$FILE_PATH" = "null" ]; then
exit 0
fi
case "$FILE_PATH" in
*.js|*.jsx|*.json|*.md|*.css)
npx prettier --write "$FILE_PATH" 2>/dev/null
;;
esac
exit 0
CLAUDE.mdに「Prettierを実行して」と書く必要がなくなります。
保護ファイルへの編集ブロック
PreToolUseで特定ファイルの書き込みをブロックする例です。
#!/bin/bash
FILE_PATH=$(cat | jq -r '.tool_input.file_path // empty')
case "$FILE_PATH" in
*.env*|*package-lock.json*)
echo "Blocked: $FILE_PATH is protected" >&2
exit 2
;;
esac
exit 0
exit 2を返すとブロッキングエラーになり、ツールの実行が中止されます。settings.jsonのpermissions.denyでも読み取りを禁止できますが、Hooksは書き込みの試行をブロックして理由を伝えられる点が違います。
デスクトップ通知(macOS)
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \\\\"Claude Code\\\\" with title \\\\"確認してください\\\\"'"
}
]
}
]
}
}/compact後のリマインダー
/compactで会話を圧縮すると、重要な前提が失われることがあります。
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: use R2Image for images. Run npm run build before commit.'"
}
]
}
]
}
}終了コードとパーミッションの関係
Hooksのシェルスクリプトは終了コードで挙動が変わります。exit 0は成功でstdoutのJSONが解析されます。exit 2はブロッキングエラーでツールの実行を中止します。exit 1はエラーですが処理は続行します。ファイル保護にはexit 2を使ってください。
パーミッションとの関係で押さえておくべき点が2つあります。PreToolUseフックでdenyを返すと、bypassPermissionsモードでもブロックされます。Hooksはパーミッション設定より強い制約を課せます。逆に、フックでallowを返してもsettings.jsonのdenyルールは上書きされません。制約の強化はできますが、緩和はできない設計です。
注意点
.zshrcにあるecho文がstdoutに混入してJSON解析が失敗するケースがあります。プロファイルの出力はif [[ $- == *i* ]]で対話シェルのみに限定すると回避できます。
Stopフックの中でClaudeに作業を継続させると、完了時にまたStopフックが発火して無限ループになることがあります。入力JSONのstop_hook_activeフィールドを確認して、すでにStopフック中なら即座にexit 0してください。
/hooksコマンドで現在の設定状態を確認できます(読み取り専用)。デバッグにはclaude --debug-file /tmp/claude.logが使えます。
このブログでは今のところPostToolUseのフォーマッタ自動実行だけを設定しています。CLAUDE.mdに書いていたルールのうち「毎回守ってほしいもの」をHooksに移すと、指示の遵守率に左右されず確実に動くようになります。まずは小さい自動化から試してみてください。




