「Claude Codeが返してきたコード、lintを通っていなかった」「formatが崩れていてレビューで指摘された」「壊れた状態のままPRに乗ってきた」といった声が、AIを使い始めたチームから最初に聞こえてくる悩みです。
問題はAIが完璧なコードを返さないことではなく、その出力を品質ゲートなしにそのまま採用してしまう運用体制にあります。人間のレビューだけに頼ると、AIが生み出すコードの量に追いつかず、いずれ壊れたコードがすり抜けてしまいます。
この記事では、Claude CodeのHooks機構を使って、出力を必ずlint、test、formatに通してから採用する仕組みの作り方を、現場で運用できる粒度で整理します。「AIが壊さない」のではなく「壊しても自動で気づく」設計に切り替えていきましょう。
なぜ「人間レビューだけ」では破綻するのか
AI生成コードに対する人間レビューの観点は、別記事 AI生成コードのレビューが甘くなる前に|現場で効く4観点(要件適合・暗黙仕様・テスト設計・依存範囲) で整理しました。あの4観点は、人間がじっくり読んで判断する領域です。
一方で、lint違反・format崩れ・既存テストの破壊といった機械的に検出可能な不具合は、人間が読む前に弾けるものです。にもかかわらず多くの現場では、これらが人間レビューの時間を圧迫しています。
- AIの出力スピードに、レビューの目が追いつかない
- 「動いているように見える」コードを、雰囲気で承認してしまう
- formatやlintの指摘がレビューの大半を占め、設計議論が薄まる
ここを自動化しないまま運用を広げると、AI導入の効果は「コードを書く時間」が短くなる代わりに、「レビューと手戻り」が増えるだけで終わります。
Claude Code Hooks とは何か
Hooks は、Claude Code がツールを呼び出す前後・セッションの開始終了など、決まったタイミングで任意のシェルコマンドを実行できる仕組みです。設定ファイルに登録しておけば、Claude Codeが意識しなくても、必ずそのコマンドが走ります。
品質ゲートとして使う観点では、特に次のタイミングが重要です。
- PostToolUse:ファイル編集系ツール(
EditやWriteなど)が実行された直後 - Stop:エージェントが応答を終えたタイミング
- PreToolUse:危険なコマンドや本番環境への操作を実行する前
PostToolUse でフォーマッタとlintをかけ、Stopでテストをまとめて回す、という二段構えにすると、編集のたびに即時で形を整えつつ、最終確認をまとめてできるようになります。
品質ゲートの3レイヤー設計
すべてを毎回フルで走らせると、応答が遅くなりエージェント体験が悪化します。Hooksは「速い処理ほど頻繁に、重い処理ほどまとめて」走らせるのがコツです。
レイヤー1:フォーマット(編集直後、常時実行)
PostToolUse で、編集対象ファイルに対してフォーマッタをかけます。prettier --write や ruff format、gofmt など、言語ごとの標準ツールで十分です。AIに「整形して」と頼むのではなく、Hooksで強制するのがポイントです。
レイヤー2:Lintチェック(編集直後、対象ファイルのみ)
同じく PostToolUse で、編集されたファイルだけにlintをかけます。違反があったら、その内容をエージェントに返して修正させます。プロジェクト全体にlintをかけると遅くなるので、編集差分だけに絞るのが運用上のコツです。
レイヤー3:テスト(応答完了時、関連スコープのみ)
Stop の段階で、影響範囲のテストを走らせます。すべてのテストを毎回回すのは現実的ではないので、
- 直近で編集したファイルに対応するユニットテストだけ走らせる
- 完全なスイートはCI側で担保する
という割り切りが現場に合います。Hooksの段階で全テストが失敗するとエージェントがうまく修正できなくなるため、この点は注意しましょう。
設定の最小テンプレート
Claude Codeの設定ファイル(.claude/settings.json またはユーザー設定)に、次のような形でHooksを登録します。実際のキー名はバージョンで変動するので、公式ドキュメントの最新仕様に合わせて読み替えてください。考え方の骨格は変わりません。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash .claude/hooks/format-and-lint.sh"
}
],
"Stop": [
{
"command": "bash .claude/hooks/run-related-tests.sh"
}
]
}
}
.claude/hooks/format-and-lint.sh の中身は、対象ファイルの拡張子で分岐させ、format → lint の順に走らせるだけのシンプルな構成にします。標準出力にエラー内容を出せば、Claude Codeはそれを読んで自分で修正してくれます。
#!/usr/bin/env bash
set -e
target="$CLAUDE_EDITED_FILE"
case "$target" in
*.ts|*.tsx|*.js) npx prettier --write "$target" && npx eslint "$target" ;;
*.py) ruff format "$target" && ruff check "$target" ;;
*.go) gofmt -w "$target" && go vet "$(dirname "$target")/..." ;;
esac
このレベルで十分に、「AIが壊しても自動で気づく」状態が作れます。最初から作り込みすぎず、現場で痛みを感じている言語だけ先に整備するのが運用の鉄則です。
運用に乗せるための3つの注意点
仕組みを入れる以上に、続けるための設計が大事です。
1. Hooksの実行時間を計測する
PostToolUseが毎回3秒かかると、エージェントの体感速度は激しく落ちます。time で実測し、1秒以内に収まる範囲でレイヤー分割してください。重いものはStopかCIに寄せます。
2. 失敗時のメッセージを「修正可能」な形にする
Hooksが赤く落ちた瞬間、Claude Codeはその出力を読んで再試行します。エラーメッセージが曖昧だと、AIは何を直せばいいか判断できず、無限ループに近い挙動になります。どのファイルの何行目で何が違反したか を必ず含めてください。
3. プロジェクトメモリと組み合わせる
Hooksは「壊れたら止める」装置ですが、最初から壊さないためには、AIに前提を渡しておく必要があります。プロジェクト固有のコーディング規約・命名・ライブラリ選択ルールは、別記事 Claude Codeに同じ前提を毎回書くのをやめる|CLAUDE.mdで渡すプロジェクトメモリの設計 で扱った CLAUDE.md に集約しておくと、Hooksに引っかかる頻度そのものが下がります。
組織としてAIを回すための「仕組み化」へ
Hooksの整備は、個人の便利機能ではなく、組織として安心してAIを使うための前提条件です。チームによってAI導入の進度に差があり、「使われない」と「使われすぎる」という両極端な状況が発生しがちなことは、別記事 Claude Code が社内で使われない3つの原因|定着させる3段階フレーム で整理した通りです。
Hooksで品質ゲートを自動化すると、
- AIを使うメンバーが増えても、最低品質が保たれる
- レビュー担当者が「設計と要件適合」に集中できる
- 「AIに任せて大丈夫か」という心理的ブレーキが下がる
という、定着フェーズの加速にも直結します。
まとめ
- Claude Codeの出力をそのまま採用するのではなく、Hooks で品質ゲートを通してから受け取る
- format、lint、testの3レイヤーを、PostToolUseとStopに振り分ける
- エラーメッセージは「AIが自分で修正できる粒度」で返す
- CLAUDE.mdなどのプロジェクトメモリと組み合わせて、そもそも壊さない確率を上げる
「AIに完璧を求める」のではなく、「壊しても自動で気づく」前提で仕組みを組むこと。この発想転換ができると、AI活用は一気に組織のレベルに到達します。
仕組み側だけでなく、AIに渡す指示、運用ルール、組織への組み込み方まで体系的に学びたい方は、テックエイドのAI実践シリーズ(AIX-101やAIX-102)が、Hooksを含めた品質担保の手順を実装パートで扱っています。あわせてご覧ください。