「ファイルを30個リネームして、参照箇所も全部直して」とお願いしたら、Claude Code が「完了しました!」と返してきました。喜んでビルドを回したらコンパイルエラーの嵐 — 確認すると、リネーム自体はできていたものの、import の書き換えは半分の14ファイルで止まっていたのです。
エラーログには何も出ていません。Claude Code 側の言い分も「タスクは完了しました」のひと言。怒るより先に、どうすればこういう「途中で諦めるClaude」を未然に防げるかを考える必要がありました。
なぜ Claude Code は「途中で完了」と判断してしまうのか
最初に押さえておきたいのは、これは Claude のバグではなく、エージェント設計上の自然な振る舞いだということです。Claude Code はタスクを進める中で「もう十分やったな」と判断する内部基準を持っています。その基準は主に次の3つで動いています。
- トークン消費の累積感: 連続して大量の編集を続けると、内部的に「ここで一区切り」と判断しやすくなる
- エラー応答の不在: ビルドやテストを走らせていない場合、Claude は「動いていそうだ」と推測で完了を宣言する
- タスクの曖昧さ: 「全部直して」のような完了条件が数値化されていない指示は、Claude が独自に範囲を切ってしまう
この3つはどれも、こちら側のプロンプト設計と検証フローで対処できます。Anthropic が悪いわけでも、モデルが手抜きをしたわけでもないのです。私たちが「完了の定義」を渡し損ねていたという話です。
完走させるプロンプトの3要素
私が今、ファイル横断の変更を Claude Code にお願いするときは、必ず次の3要素をプロンプトに含めるようにしています。
1. 完了条件を数値で渡す
曖昧さを消すため、件数や対象ファイル数を明示します。
❌ 悪い例:
「src/ 以下の console.log を全部 logger.info に置き換えて」
✅ 良い例:
「src/ 以下の console.log を logger.info に置き換えてください。
事前に grep -r 'console.log' src/ で件数を数えて、
作業後にもう一度 grep して件数が 0 になることを確認してから完了報告してください。」「事前カウント → 作業 → 事後カウント = 0」というプロトコルを渡すだけで、Claude Code は格段に最後まで走るようになります。
2. チェックポイントを明示する
長いタスクは中間報告を要求します。これは Claude が「ここで完了したつもり」になるのを防ぐ効果が大きいです。
✅ 良い例:
「30ファイルのリネームを進めてください。
10ファイル終わるごとに、進捗(X/30)と次の10ファイルの計画を1行で報告してから次に進んでください。」明示的にチェックポイントを挟むと、Claude Code は内部で「まだ20ファイル残っている」というカウンタを保持しやすくなります。
3. 「完了報告のフォーマット」を指定する
最後に、完了報告そのものの形式を縛ります。
✅ 良い例:
「完了したら、以下のテンプレートで報告してください:
- 変更ファイル数: N件
- ビルド結果: PASS / FAIL
- テスト結果: PASS (N tests) / FAIL (N tests)
- 残作業: なし / あり(内訳)
ビルドかテストが FAIL の場合は『完了』と書かないでください。」「ビルドが通っていなければ完了と言うな」と明文化するのは、地味ですが効果絶大です。
自動検証ループの実装パターン
プロンプト工夫だけでは限界があります。私が今、本番案件で必ず仕込んでいるのが、Claude Code 自身に検証ループを回させるパターンです。Bash ツールを使った簡単な実装をご紹介します。
#!/usr/bin/env bash
# verify-rename.sh — リネーム作業の完走を保証する検証スクリプト
set -euo pipefail
OLD_PATTERN="$1" # 例: "console.log"
NEW_PATTERN="$2" # 例: "logger.info"
TARGET_DIR="${3:-src}"
# 1. 残存する旧パターンの数を数える
remaining=$(grep -r --include="*.ts" --include="*.tsx" \
-l "$OLD_PATTERN" "$TARGET_DIR" 2>/dev/null | wc -l)
# 2. ビルドが通るかを確認
build_status="PASS"
if ! npm run build > /tmp/build.log 2>&1; then
build_status="FAIL"
fi
# 3. テストが通るかを確認
test_status="PASS"
if ! npm test -- --run > /tmp/test.log 2>&1; then
test_status="FAIL"
fi
echo "----- VERIFICATION REPORT -----"
echo "Remaining files with '$OLD_PATTERN': $remaining"
echo "Build: $build_status"
echo "Tests: $test_status"
# 4. 完了条件を満たしていなければ非ゼロで終了
if [[ "$remaining" -ne 0 || "$build_status" != "PASS" || "$test_status" != "PASS" ]]; then
echo "❌ NOT COMPLETE — Claude must continue working"
exit 1
fi
echo "✅ ALL CHECKS PASSED"このスクリプトをプロジェクトの scripts/verify-rename.sh に置き、Claude Code への指示の最後に「bash scripts/verify-rename.sh console.log logger.info src を実行して、終了コードが 0 になるまで作業を続けてください」と添えるだけで、Claude が「ビルドが通っていないのにDoneと言う」事故が消えます。
Hooks と組み合わせるとさらに強くなる
Claude Code の Hooks 機能を使うと、検証ループを完全に自動化できます。PostToolUse フックで Edit ツール完了後に自動で検証スクリプトが走るように設定すると、Claude 側が完了を宣言する前に必ず実態と突き合わせる仕組みが組めます。
設定例(.claude/settings.json):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "bash scripts/verify-rename.sh console.log logger.info src 2>&1 | tail -5"
}
]
}
]
}
}検証スクリプトの出力が Claude のコンテキストに自動で流れ込むので、Remaining: 14 という事実を見た瞬間に「あ、まだ終わっていない」と気づいて作業を再開してくれます。Hooks の詳細な設計パターンは Claude Code Hooks の実践的活用ガイド もあわせてご覧ください。
私のプロンプトテンプレート
最後に、私が今、ファイル横断のリファクタタスクに使っている定番テンプレートをそのまま共有します。コピペで使ってみてください。
## タスク
[ここにやってほしい変更を1〜2文で]
## 完了条件(このすべてを満たすまで完了と判断しない)
1. 対象ファイル数: 事前カウントで N 件、作業後にもう一度 grep して 0 件
2. ビルドが通る: `npm run build` が成功
3. テストが通る: `npm test` が成功
4. 検証スクリプトが PASS: `bash scripts/verify-task.sh` の終了コードが 0
## 中間報告
10ファイル進めるごとに、`[X/N] 完了` と1行報告してから次に進んでください。
## 完了報告フォーマット
- 変更ファイル数: N
- ビルド: PASS / FAIL
- テスト: PASS (X tests) / FAIL
- 残作業: なし / あり(内訳)
ビルドかテストが FAIL の状態で「完了」と書かないでください。このテンプレートに切り替えてから、私の「Done と言われたのに半分しか終わっていなかった」事故はゼロになりました。最初は冗長に感じるかもしれませんが、検証フェーズの省略が引き起こす手戻りコストに比べれば、テンプレートの数行は安いものです。
まずは今日、検証スクリプトを1つ書いてみる
完走させる Claude Code を手に入れる一番の近道は、自分の今のプロジェクトで「リネーム」「リファクタ」「import 整理」などの繰り返し作業に対して、終了条件を数値で返すスクリプトを1つだけ書いてみることです。10行のシェルスクリプトで十分です。一度書いてしまえば、その後の同じ系統のタスクすべてで Claude を最後まで走らせられるようになります。