Claude Code カスタム|Stop hook で自動テストを走らせる|146件0.07秒の実装公開
「テスト、実行するの忘れてました」——プログラミングを少しでも触ったことがある方なら、聞き慣れたフレーズではないでしょうか。
当社でも同じ事故が頻発しました。AI に新しい機能を作ってもらう。動いた。コミットする。次の日、別の場所が壊れていることに気づく。理由は単純で、テストを実行するのを毎回忘れていた からです。
解決策は意外と地味な仕組みでした。Stop hook という機能を使い、Claude Code のセッションが終わるたびに、自動でテストを走らせる。当社では 146 件のテストが 0.07 秒で全部回り、失敗があればその場で表示されます。テスト忘れによる事故はゼロになりました。
シリーズ「Claude Code を自分専用に育てる」第 3 回。今回は、誰の手も借りずに「やるべきこと」を AI に強制実行させる仕組みを、当社の実物の設定ファイルごと公開します。前回の deny で事故を防ぐ話と、今回の hook で自動実行させる話は、settings.json の表裏一体の機能です。
目次
Stop hook とは|「やるべきこと」を AI に強制実行させる仕組み

Stop hook とは
Claude Code のセッションが終わる瞬間に、決められたコマンドを自動実行する機能。テストの実行、コードの整形、デプロイ確認など「セッション終了時に必ずやるべきこと」を仕組みで強制できます。AI に頼まなくても勝手に走る、これが最大の特徴です。
「お願いベース」と「自動実行ベース」の決定的差
これまで紹介してきた CLAUDE.md と settings.json deny は、どちらも「AI への指示」でした。指示を読んでもらい、判断してもらい、行動してもらう。間に AI の判断が必ず挟まる仕組みです。
Stop hook は違います。間に判断を挟まない。セッションが終わった瞬間、設定したコマンドが必ず走る。AI が「今日は要らないかな」と判断する余地がありません。テストのような「絶対に毎回やるべきだが、つい忘れる」作業に最適です。
Claude Code のライフサイクルに 9 つのフックポイント
公式が用意しているフックポイントは複数あります。実用上覚えておくべきは 3 つだけ。
- PreToolUse: AI がコマンドを実行する直前。実行前の検証・パラメータ変更に使う
- PostToolUse: コマンドが終わった直後。整形・自動チェックに使う
- Stop: セッション全体が終わる瞬間。最終検証・テスト実行に使う
当社が今回紹介するのは Stop だけですが、PostToolUse も併用すると、コードを書くたびに自動で整形・型チェックを走らせる構成にできます。皆さんの開発スタイルに合わせて拡張してください。
出典: Anthropic Claude Code Hooks Reference(2026)
「うっかり忘れる」を構造で消すという発想
業務改善でよく言われる原則に「人間の注意力に依存する仕組みは必ず壊れる」というものがあります。チェックリストを作っても、運用 3 ヶ月で形骸化する。これは AI でも同じで、CLAUDE.md にどれだけ詳しく書いても、判断の瞬間に抜けることがあります。
hook はその外側で動きます。判断を挟まず、決まったタイミングで決まったコマンドが走る。仕組み化のひとつの完成形です。
当社の実装|Stop で pytest を 0.07 秒で回している実例

抽象論より実物。当社の .claude/settings.json に書かれている Stop hook の中身を、そのまま公開します。
当社の Stop hook 設定・実物
JSON の hooks.Stop セクションに、次の 1 ブロックが入っています。matcher は空文字(全セッション対象)、command は pytest をプロジェクト内のテストディレクトリで走らせる単純なシェルコマンド、timeout は 60 秒。それだけ。
| 設定項目 | 中身 | 役割 |
|---|---|---|
| matcher | 空文字 | 全セッション終了時に発火 |
| command | cd visual-generator && pytest tests/ -x --tb=short | tail -30 | テスト実行 → 失敗時はテール 30 行を表示 |
| timeout | 60 秒 | テストが暴走した時の安全弁 |
| statusMessage | 「KVG validator pytest を実行中...」 | 進行中であることを画面に表示 |
設定はこれだけ。146 件のテストが 0.07 秒で完走するため、ほとんど待たずにセッションが閉じます。失敗があれば赤字で表示され、原因がすぐ目に入る作りです。
環境変数で「プロジェクトルート」を取れる
command 内で $CLAUDE_PROJECT_DIR という変数を使うと、プロジェクトルートのフルパスが入ります。これにより、どのフォルダから Claude Code を起動してもテストが正しく実行されます。
同種の環境変数は他にもあり、編集対象ファイル名($CLAUDE_FILE_PATH)、実行されたツール名($CLAUDE_TOOL_NAME)、セッション ID($CLAUDE_SESSION_ID)などが利用できます。あなたが PostToolUse で「編集したファイルだけ整形する」設定にしたい時は、$CLAUDE_FILE_PATH が役立ちます。
失敗ログのテール 30 行が即座に見られる
テストが失敗した時に大量のログが流れると原因が見えない。当社では tail -30 で末尾 30 行に絞り、エラー内容と失敗テスト名だけを画面に出す設計にしました。
これは小さな工夫ですが、効きます。失敗を見た瞬間に原因が分かれば、その場で修正してもう一度セッションを回せる。「あとで見る」が「今すぐ直す」に変わります。
hook の 3 種類|PreToolUse / PostToolUse / Stop の使い分け

当社は Stop だけを使っていますが、他の 2 種類も理解しておくと拡張時に役立ちます。それぞれの使い所を整理します。
PreToolUse|「実行する前」の最終チェック
PreToolUse は、AI がコマンドを実行しようとした直前に発火します。実行を許可するか、ブロックするかを決められる強力なフックです。
典型的な使い方は 本番環境への接続をブロックする。AI が「本番 DB に接続してください」と言ってきた時、PreToolUse で接続文字列をチェックし、本番なら拒否する。判断を AI から取り上げて構造で守る、という意味で deny と近い使い方です。
PostToolUse|「実行した後」の自動整理
PostToolUse は、コマンドが終わった直後に発火します。整形・チェック・後始末に使います。
非エンジニアの読者の方には、たとえばこんな使い方が現実的。Markdown ファイルを編集した直後に、自動で見出しの階層を整える、改行を統一する、画像のパスを正規化する。手作業で毎回やっていた「整える」作業を、編集の度に自動化できます。
Stop|「全部終わった」最後の砦
そして Stop。セッション全体が終わる瞬間に発火する、最後の砦です。当社は pytest をここに置いていますが、他にも使い道は広い。
- 記事生成セッション終了時に「下書き一覧」を Slack に通知
- 翻訳セッション終了時に「未翻訳の項目」をリストで提示
- 顧客対応セッション終了時に「次回フォローアップ予定」をカレンダーに追加
業務に応じてカスタマイズできます。「セッションを閉じる前に、必ずやっておきたい何か」を思い浮かべれば、それは Stop hook の候補です。
運用してわかった|テスト忘れがゼロになる代わりの注意点

1 ヶ月運用して見えた「導入前に知っておくと得な注意点」を 3 つ。
注意点 1|hook 追加直後は再起動が必要
settings.json に新しい hook を書き足しても、すでに開いている Claude Code のセッションには即座には反映されません。Claude Code を再起動するか、新しいセッションを開く必要があります。
これに気づかず「設定したのに動かない」と当社も最初は焦りました。設定後は必ず一度再起動して動作確認。これが鉄則です。
注意点 2|timeout を長くしすぎない
timeout を 600 秒(10 分)まで延ばせますが、長くするほどセッション終了が遅延します。当社の 60 秒設定は「146 件のテストが 0.07 秒で終わる」前提だから成立しています。
テストの実行時間が長いプロジェクトでは、Stop hook ではなく PostToolUse で「変更したファイルに関連するテストだけ」を走らせる構成にする方が現実的です。皆さんのプロジェクト規模に合わせて選んでください。
注意点 3|失敗ログを「読む習慣」も同時に育てる
hook が自動で動いても、失敗ログを誰も読まなければ意味がありません。当社では「Stop hook が赤字を出したら、その場でセッションを閉じずに 1 分だけ確認する」をルールにしました。前回の CLAUDE.md の話で書いた「ルールの明文化」をここでも使い、CLAUDE.md に「Stop hook の赤字は必ずその場で読む」と書いておく構造です。
シリーズ次回予告
ここまでで「ルールの宣言(CLAUDE.md)」「物理的な禁止(deny)」「自動実行(hook)」の 3 つが揃いました。次回は 自分専用の slash command を作る方法、当社の /write-article・/log-done・/kvg-release の 3 つの実物を公開しながら、繰り返し作業を 1 行のコマンドに畳む手順を解説します。
Stop hook で自動テストについてよくある質問

テストフレームワークが pytest 以外でも Stop hook は使えますか
使えます。Stop hook の command にはどんなシェルコマンドでも書けるため、JavaScript なら npm test、Ruby なら bundle exec rspec、Go なら go test ./... のように、お使いの言語のテストコマンドをそのまま指定できます。テストフレームワーク非依存の機能です。
テスト以外で Stop hook に向いている用途はありますか
「セッション終了時に必ずやりたいこと」全般に向いています。たとえば編集ファイルの一覧を Git status で確認する、未コミットの変更があれば警告する、ToDo リストの更新を促す通知を出す、といった用途です。当社では将来的に「下書きの記事一覧を Google Chat に通知する」hook を追加する予定です。
hook の設定をチームで共有する場合の注意点は何ですか
command の中でローカル環境固有のパス(自分の Mac のユーザー名など)を直接書かないことです。代わりに $CLAUDE_PROJECT_DIR や $HOME などの環境変数を使うと、メンバー全員の環境で動きます。settings.json を Git に含める際は必ずこの確認を入れてください。
Stop hook が頻繁に失敗する時はどうすればよいですか
まずテストコマンドを手動で実行して、ターミナル上で同じ失敗が再現するか確認します。手動でも失敗するならテスト自体の問題、手動では成功するなら hook の環境変数や作業ディレクトリ設定の問題、と切り分けられます。timeout が短すぎて打ち切られている可能性もあるので、$? の終了コードと併せて確認してください。
