はじめに
Claude Code を毎日使っていると、「保存したら構文チェックしておいて」「このコマンドはただの閲覧だから確認いらないよ」と、同じ指示を繰り返すことになります。これを毎回言わずに済ませるのが hooks です。
本記事では、自分の環境で実際に動かしている hooks をもとに、次の 3 点を整理します。
- 構文チェックを自動で走らせる
PostToolUseフック - 読み取り専用コマンドだけを自動許可する
PreToolUseフック - hooks 運用で見落としやすい落とし穴
hooks の基本
hooks は Claude Code のツール呼び出し(ファイル編集・コマンド実行など)の前後に、任意のスクリプトを実行させる機能です。設定は settings.json(プロジェクト共通)または settings.local.json(個人用)に書きます。
実運用で主に使っているイベントは以下です。
- PreToolUse … ツール実行前。許可・拒否・確認の判定を返せる
- PostToolUse … ツール実行後。結果を検査してフィードバックを返せる
- SessionStart … セッション開始時に 1 回。前回の作業状態の読み込みなどに使う
PostToolUse: 編集直後の構文チェック
ファイルが書き換えられた直後に、拡張子に応じて構文チェックを実行します。
const filePath = data.tool_input.file_path;
const ext = path.extname(filePath);
if (ext === '.php') {
runCommand('php -l ' + filePath); // 構文エラーがあれば例外を投げる
} else if (ext === '.js') {
runCommand('node --check ' + filePath);
}
終了コードの使い分け
| 終了コード | 挙動 |
|---|---|
| 2 | 出力が Claude への指示として渡り、修正を促す |
| 0 | 何も伝えずにそのまま続行 |
フック自身の不調は 0 で握りつぶす
php / node コマンドが見つからない等、チェック対象ではなくフック側の事情で失敗した場合は、終了コード 0 で静かに終えるようにしています。フックの不具合で本来の作業がブロックされるのを避けるためです。
「検出したい問題」は 2、「フックの実行環境の問題」は 0、と分けておくと、フックが原因で作業が止まる事故を防げます。
PreToolUse: 読み取り専用コマンドの自動許可
ファイル閲覧や一覧表示のような読み取り専用コマンドでも、パイプや複合コマンドを含むと Claude Code 標準の安全判定が決めきれず、毎回確認画面が出ることがありました。
そこで、読み取り専用と機械的に証明できた場合に限り allow を返すフックを用意しました。
console.log(JSON.stringify({
hookSpecificOutput: {
hookEventName: 'PreToolUse',
permissionDecision: 'allow',
permissionDecisionReason: '読み取り専用と判定できたため自動許可',
},
}));
permissionDecision に指定できる値は次の 3 つです。
| 値 | 挙動 |
|---|---|
allow |
確認なしで実行 |
deny |
実行を拒否 |
ask |
通常どおりユーザーに確認 |
判定できないときは「何も返さない」
設計上いちばん大事にしているのは、判定に自信がない場合は何も出力しないことです。何も返さなければ通常の確認フローに戻るので、判定漏れがあっても安全側に倒れます。allow を広く返すほど便利にはなりますが、その分だけ事故のリスクが増えます。
落とし穴: 壊れていても気づきにくい
hooks は「毎回自動で動く」ことが前提になるため、止まっていても気づきにくいという弱点があります。
実際にあったのが、複数の Claude セッションが同じ作業ディレクトリを同時に扱うための排他の仕組みです。「印(ロック)を置けたセッションだけが作業する」という設計でしたが、印を置く処理自体が失敗しても Claude はそれを検知せず、「取得できたので続行します」と進んでいました。
この経験から、hooks には次の確認をセットにしています。
- フックが出力するログを定期的に見る
- 意図的に失敗する入力を与え、きちんと検知されるかテストする
文章ルールとの使い分け
CLAUDE.md に書いた運用ルールは、読み飛ばされる可能性が残ります。hooks はルールの確認処理を強制的に実行させる手段なので、両者は役割が違います。
- 毎回同じ手順で機械的に確認できる → hooks
- 状況によって判断が変わる → 文章のルール
判断が必要なものまで hooks で固定すると、柔軟に動けなくなるので注意が必要です。
まとめ
-
PostToolUseの構文チェックは、終了コード 2 で知らせ、フック自身の不調は 0 で黙らせる -
PreToolUseの自動許可は、証明できるものだけallow、迷ったら何も返さない - hooks は壊れても気づきにくいので、ログ確認と失敗テストをセットで用意する
参考
このフック運用の背景は、Claude の一人称で書いている日記ブログにもまとめています。