やったこと
数百ファイル規模の機械的リネーム(識別子・ファイル名・ディレクトリ名の一括置換)を、Claude Code と一緒に 事故ゼロ・後戻りゼロ で完了した。
ポイントはひとつ。AI に何でもやらせない。
-
sedによる破壊的置換 → 人間が手動実行 -
git mvとgit grep/findによる検証 → AI が実行
これだけで、AI コーディングエージェントとの大規模リネームは劇的に安全になる。
なぜ AI に丸投げが危ないのか
- 部分マッチで意図しない箇所まで置換される(
OldNameを置換したらOldNameExtraまで壊れる) - 文字列リテラル
'oldname'のような 意味を持つ値 まで識別子と一緒に書き換えてしまう - PascalCase は直したが camelCase / kebab-case は取りこぼし
- 「終わりました」と言われたが grep すると数十件残っている
破壊的変更を一気に実行する性質と、検証を怠る性質が掛け算で事故になる。
解決策: 仕様書駆動 + 責務分担 + ステップループ
1. 仕様書を先に書く
設計書(何を何に変えるか・PR スコープの境界)と、実装計画書(AI が実行できる粒度のステップ)に分ける。人間がレビューして合意してから AI に渡す。
2. 責務を分担する
| 操作 | 担当 |
|---|---|
sed 一括置換 |
人間(手動) |
git mv |
AI |
git grep / find での検証 |
AI |
| 型チェック・テスト | 人間(手動) |
今回私のプロジェクトではClaude Codeのサンドボックスモードを採用していたため、破壊的コマンドは そもそも AI が実行できない。
ただし、あくまでこれは保険として機能しており、大事なのは具体的にどの手順でAIが何をするのかが明示的になっていることにフォーカスし仕様書を作成した。
3. ステップループで進める
1. AI: 「Phase X / Step Y: 〇〇の置換」と sed コマンドを提示
2. 人間: 手動実行して完了報告
3. AI: git grep で検証
4. OK → 次へ / NG → 残存箇所を特定して 2 に戻る
ポイントは、AIがすることだけではなく、しないことを人間(開発者)が実行すると明記することで、誤爆を防ぐ。
効いた小ワザ
長いパターンから先に置換する
# ✅ 長いほうを先に
sed -i '' 's/OldFooBar/NewFooBar/g' file.ts
sed -i '' 's/OldFoo/NewFoo/g' file.ts
逆順だと長いパターンが壊れる。
文字列リテラルを誤爆しない
識別子(後ろに英字が続く)だけ置換したいなら正規表現で絞る。
sed -i '' "s/oldname\([A-Za-z]\)/newname\1/g" file.ts
これで oldnameUser → newnameUser には変わるが、'oldname' リテラルは残る。
期待値付きの検証コマンド
「実行した」で AI が満足しないよう、何が出れば OK かをコメントで書く。
git grep -c 'OldRelationName' -- 'packages/foo/**/*.ts'
# 期待: 0
除外対象は ! -name で明示
find packages/foo -type f -name "*.ts" \
! -name 'legacy-component.tsx' \
-exec sed -i '' 's/OldName/NewName/g' {} +
コミット粒度を計画書で固定する
DB 層・バックエンド層・フロントエンド層を別コミットに分ける、と先に決めておくとレビューの認知負荷が一気に下がる。
まとめ
人間にも一定の主導権を持たせたAI駆動開発を行うときは、
- 仕様書と計画書を先に書く
- 破壊的操作は人間、git 操作と検証は AI
- ステップループで進める
これだけで優秀だが破壊行為はさせない役割として AI が機能する。サンドボックス制限は邪魔ではなく、安全装置として積極的に使う 視点を前提におくべきと学んだ。