Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。
「ビルド通るまで直しといて」
そう頼んで席を立った僕が戻ってきたら、Claude Codeは22回ビルドを回した挙句、エラーを消すためにテストの中身をコメントアウトしていました。たしかにビルドは通っている。緑色のチェックも出ている。でも、壊れたコードはそのまま残っていたんです。
これ、AIが悪いわけじゃありません。僕が「直せ」とだけ言って、何をもって直ったとするかを決めなかった。ゴールが「ビルドが通る」だったから、AIは一番手っ取り早く通す道、つまりテストを黙らせる道を選んだだけです。
賢いAIに作業を任せるとき、必要なのは賢いプロンプトじゃありません。ビルドして、ちゃんと動くか軽く叩いて、ダメなら失敗ログを見て直す——この一連の流れを、AIの外側で回す仕組みです。これをハーネス(足場)と呼びます。今日はその中でも「スモークテストで回す」部分に絞って、実際の組み方を書きます。
ハーネスそのものの考え方(何を見せて、どこで止めるか)は Claude Codeに仕事を任せる足場の作り方 にまとめました。本記事はその続き、「テストで自動的に回す実装と運用」の話です。
この記事の要点
- スモークテストは「全部のテスト」じゃない。起動して主要な1本が通るかだけを30秒以内で確かめる軽い検査のこと。
- ループの肝は、失敗したらエラーログの中身をそのままAIに食わせて「これを直して」と返すこと。「直して」だけでは直らない。
- 暴走は2つで止める。試行回数の上限(例: 5回で打ち切り)と、危険な操作の前の人間確認ゲート(削除・本番反映・force pushは必ず聞かせる)。
- コピペで動く最小ループを下に置いた。
npm run buildを回して、失敗ログを添えてClaude Codeに渡し、最大5回まで自動で直させる構成。 - 緑になっても安心しない。テストを消して通したのか、本当に直ったのかを見分ける1行を仕込む。
スモークテストって、要するに何?
スモークテストは、電化製品の「電源を入れて煙が出ないか見る」検査が語源です。全機能を確かめるんじゃなくて、最低限ちゃんと動き出すかだけを見る。
ソフトウェアでいえばこんな感じです。
- Webアプリなら、トップページがHTTP 200で返ってくるか
- CLIなら、
--helpがエラーなく表示されるか - ライブラリなら、import して関数を1回呼んで例外が飛ばないか
- このブログなら、
npm run buildが最後まで通り、対象ページのHTMLが生成されるか
ポイントは速いこと。理想は数秒、長くても30秒で終わるものを選びます。なぜなら、AIに自動で回させると1作業で何度も実行されるからです。5分かかるテストを5回回したら25分。その間AIは止まって待つことになり、現実的に運用が続きません。
「全部のテストを回せばいいじゃないか」と思うかもしれません。でも最初は逆です。一番壊れたら困る経路を1本だけ選ぶ。それが緑なら次に進める、赤なら止める。この単純さが、自動ループを安全にします。
ビルド→スモークテスト→自動修正のループの組み方
流れはいつも同じ3ステップです。図にするとこうなります。
[1] AIにコードを直させる
↓
[2] ビルド & スモークテストを回す(人間ではなく機械が判定)
↓
通った? ── はい → 終了(人間が最終確認)
↓ いいえ
[3] 失敗ログをそのままAIに渡して「これを直して」→ [1]へ戻る
↑
ただし回数上限 or 危険操作の手前で必ず止める
ここで一番大事なのは [2] と [3] の境目です。多くの人がつまずくのは、[3] で「うまくいかなかったから直して」とふわっと頼むこと。これだとAIは推測で別の場所をいじり始めます。
正解は、ビルドの標準エラー出力(赤い文字で出るあれ)を、丸ごとコピーして渡すことです。TypeError: Cannot read property 'map' of undefined at src/list.ts:42 のような行が入っていれば、AIは「42行目のundefinedを直せばいいんだな」と一発で当てにいきます。
逆に、ログの最後の1行だけ渡すのは危険です。本当の原因は途中のスタックトレースにあることが多いから。僕は最初これで何度も遠回りさせました。
| やりがちなこと | 起きる事故 | こうする |
|---|---|---|
| 「直して」とだけ頼む | 関係ない場所をいじる | 失敗ログ全文を貼って渡す |
| ログの最終行だけ渡す | 見当違いの修正 | スタックトレースごと渡す |
| 無制限にリトライ | 22回ループ・テスト破壊 | 試行5回で打ち切り |
| 全部自動でやらせる | 削除・本番反映の事故 | 危険操作の前で人間に聞く |
暴走を止める2つのストッパー
自動修正ループの怖いところは、直らないときに永遠に回り続けることです。しかも前述の通り、行き詰まったAIは「テストを消す」「エラーを握りつぶす」みたいな、見かけだけ緑にする手に出ます。止め方は2つあります。
ひとつ目は回数の上限。「最大5回まで。それでも赤なら人間を呼ぶ」と決め打ちします。これがあるだけで22回ループは起きません。5回で直らない問題は、たいてい設計やデータ側の問題で、AIが何回叩いても直らないやつです。早めに人間が見たほうが速い。
ふたつ目は危険な操作の手前に置く確認ゲート。具体的には、ファイル削除・本番DBへの反映・課金API・git push --force といった「やり直せない操作」だけは、AIに勝手にやらせず、人間がOKを出すまで止めます。Claude Codeなら、この「実行前に止める」をフック(hooks)で機械的に強制できます。PreToolUse という、道具を使う直前に割り込める仕組みがあって、ここで危険なコマンドを見つけたらブロックするわけです。詳しい設定は Claude Code hooksの実務ガイド と公式の Hooks リファレンス にあります。
僕の運用ルールはシンプルです。最初は危険操作を全部「人間に聞く」にしておき、安全だと確信できた操作だけ、あとから自動に格上げする。逆をやると必ず事故ります。どこまで自動でやらせるかの段階づけは 権限の安全ラダー に整理しました。
コピペで動く最小ループ
説明より動かすのが早いです。npm run build をスモークテストとして使い、失敗したらログを添えてClaude Codeに渡し、最大5回まで自動で直させる最小ループを置きます。Node.jsとClaude Code CLI(claude コマンド)が入っていれば動きます。
ポイントは2か所だけ覚えてください。MAX_ATTEMPTS が暴走を止める上限、stderr を丸ごとプロンプトに混ぜているところが自動修正の心臓部です。
// smoke-loop.mjs
// ビルド(=スモークテスト)を回し、失敗したらログ付きでClaude Codeに直させる
import { execSync, spawnSync } from "node:child_process";
const MAX_ATTEMPTS = 5; // ← 暴走防止。これ以上は人間を呼ぶ
const SMOKE_CMD = "npm run build"; // ← 速くて壊れたら困る1本を選ぶ
// スモークテストを1回実行し、成功/失敗とログを返す
function runSmoke() {
try {
const out = execSync(SMOKE_CMD, { encoding: "utf8", stdio: "pipe" });
return { ok: true, log: out };
} catch (e) {
// 標準出力+標準エラーを丸ごと拾う(原因はここに全部入っている)
const log = `${e.stdout ?? ""}\n${e.stderr ?? ""}`.trim();
return { ok: false, log };
}
}
// 失敗ログを"そのまま"渡してClaude Codeに修正を依頼する
function askClaudeToFix(log) {
const prompt = [
"次のビルドが失敗しました。原因を特定して最小の修正をしてください。",
"テストやエラーチェックを削除・無効化して通すのは禁止です。",
"本当に原因を直してください。",
"----- 失敗ログ -----",
log.slice(-6000), // 長すぎると邪魔。末尾(=エラー本体)を優先して渡す
].join("\n");
// claude CLIを非対話モードで実行(-p はワンショット実行)
const res = spawnSync("claude", ["-p", prompt], {
encoding: "utf8",
stdio: "inherit",
});
if (res.status !== 0) throw new Error("Claude Codeの実行に失敗しました");
}
// メインループ
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
console.log(`\n=== スモークテスト ${attempt}/${MAX_ATTEMPTS} 回目 ===`);
const { ok, log } = runSmoke();
if (ok) {
console.log("✅ 通りました。最終確認は人間がしてください。");
process.exit(0);
}
console.log("❌ 失敗。ログをClaude Codeに渡して修正を依頼します。");
askClaudeToFix(log);
}
console.error(
`\n🛑 ${MAX_ATTEMPTS}回試しても直りませんでした。ここからは人間が見てください。`
);
process.exit(1);
実行はこれだけです。
node smoke-loop.mjs
数十行ですが、もう「ビルド判定」「失敗ログの受け渡し」「回数上限」「テスト破壊の禁止指示」が全部入っています。これがスモークテストループの骨格です。あとはここに、対象ファイルの限定や、危険操作のフックでの遮断を足していくと、安心して任せられる足場に育ちます。
ひとつ注意。このループは「AIに自動でコードを書き換えさせる」ので、必ずGitで戻せる状態で回してください。git stash や作業ブランチを切っておけば、変な修正をされても一発で巻き戻せます。これも立派な安全ゲートです。
どんな場面で効くか(3つ)
1. Astro記事サイトの公開前チェック
このブログでは、記事を直したあと npm run build が通るかをスモークテストにしています。frontmatterのタイプミスやリンク切れはビルドで赤くなるので、AIにログを渡せば自分で直します。緑になったら、公開URLでh1とCTAが正しいかだけ人間が目視する。最初に丸ごと任せたい人は 最初のリポジトリ監査チェックリスト から入ると安全です。
2. 小さなUI修正 ボタンの文言を変えるくらいの作業でも、ビルド+型チェックをスモークにします。AIが別のpropを壊しても、型エラーで即赤くなって自分で直す。人間はモバイル幅で折り返しを見るだけ。
3. ライブラリの依存更新
パッケージを上げると、地味なAPI変更で動かなくなることがあります。npm test のうち主要な1本だけをスモークにして回すと、AIが変更点を追って修正してくれる。全テストは最後に1回だけ回せば十分です。
僕がやらかした失敗3つ
正直に書くと、最初のスモークテストループは事故の見本市でした。
ひとつ目は、スモークテストを重くしすぎたこと。「どうせなら全テスト回そう」と5分かかるE2Eを入れたら、5回ループで25分待ち。AIは待つだけ、僕も待つだけで、結局手動に戻りました。今は30秒以内の1本に絞っています。
ふたつ目は、ログを要約して渡したこと。気を利かせて「ビルドが失敗しました」とだけ伝えたら、AIは見当違いの場所をいじり倒しました。生のスタックトレースを丸ごと貼った瞬間、急に一発で直すようになった。AIには遠慮せず原文を渡すのが正解です。
みっつ目は、回数上限を付けなかったこと。冒頭の22回ループはこれです。MAX_ATTEMPTS = 5 を足しただけで、直らない問題を早めに人間に回せるようになり、夜中に放置して朝ビックリ、が消えました。
よくある質問
Q. スモークテストと普通のテスト(ユニットテスト)は何が違うの? A. 目的が違います。ユニットテストは「機能が正しいか」を細かく確かめるもの。スモークテストは「とりあえず起動して主要経路が動くか」を速く確かめるものです。自動ループに使うのは速いスモークのほう。細かいユニットテストは、緑になった後の最終確認で回します。
Q. ビルドが通らないんじゃなくて、見た目がおかしいときは? A. 見た目はビルドの緑では拾えません。スクリーンショットを撮って人間が見るゲートを別に置くのが現実的です。「ビルドは機械、見た目は人間」と役割を分けると運用が崩れません。
Q. AIがテストを消して緑にするのを完全に防げる? A. 100%は防げませんが、減らせます。プロンプトで「テスト削除・無効化は禁止」と明示し、加えてテストファイルの行数や件数を修正前後で比べると効きます。テストが減っていたら自動で赤に倒す。コード例の禁止指示に、この行数チェックを足すのがおすすめです。
Q. claude -p って何?対話画面と違うの?
A. -p(print/ワンショット)は、対話画面を開かずにプロンプトを1回だけ実行して結果を返すモードです。スクリプトから呼ぶときに使います。詳しい使い方は公式の Hooks リファレンス と同じドキュメント群にまとまっています。
Q. 上限の5回って多すぎ?少なすぎ? A. 作業の重さによります。タイポ修正なら2〜3回で十分。リファクタなど複雑なものでも、5回で直らなければ設計側の問題であることが多いので、いったん人間が見たほうが速いです。まず5回で始めて、肌感で調整してください。
実際に試した結果
冒頭の「22回ループ・テスト破壊」事件のあと、僕は「賢いプロンプトでなんとかする」のを諦めました。代わりにやったのは、上の smoke-loop.mjs を作って、回数上限と「テスト消すの禁止」の2行を足しただけです。
それだけで、放置して朝ビックリがゼロになりました。直らない問題は5回でちゃんと僕に回ってくる。失敗ログを丸ごと渡すようにしたら、修正の的中率が体感で倍になりました。今では記事の公開前チェックも依存更新も、まずこのループに通してから人間が最終確認、という流れが定着しています。
賢いAIを探すより、転んでも戻せる足場を先に作る。遠回りに見えて、これが一番速い、というのが今の実感です。まずは自分のプロジェクトで一番速いコマンドを1つ選んで、SMOKE_CMD に入れるところから始めてみてください。
スモークテストループを実際の運用に落とし込むなら、権限設計やフックまで含めた型が手元にあると速いです。チームや実リポジトリへの展開で詰まったら 導入相談 で具体的な運用に落とせますし、すぐ使える型がほしい人は 教材一覧 から選べます。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Code 権限の“はしご”:厳しめから安全に allow を広げる5段
最初は ask/deny 多めで始め、検証が積み上がった操作だけ段階的に allow へ。Claude Code の権限を安全に緩める5段ラダーと、各段の昇格条件を実例で。