Claude Code を本番のリポジトリに入れるかどうか、一度は迷ったことがあるのではないでしょうか。私も最初のうちは、サブディレクトリを切ってそこでだけ動かし、決して main ブランチには触らせないという運用をしていました。
理由はシンプルで、「自動で進めさせた結果、壊れたコミットが積まれていた」という事故が何度か起きたからです。テストが落ちているのに commit が走っていた、想定外のファイルが書き換えられていた、git の状態が復元できずに数時間をロールバックに費やした、といった経験は、一度でもすると慎重になります。
ただ、Claude Code を「危ないから使わない」ままだと、AIコーディングの恩恵を自分で削っていることになります。ここで必要なのは使う・使わないの二択ではなく、「失敗することを前提にした設計」に切り替えることです。
Plan Mode・TodoWrite・Hooks・Subagent・Rewind という Claude Code に備わっている5つの仕組みを、バラバラの機能ではなく1本の本番運用ワークフローとして束ねる方法を順を追って整理していきます。それぞれの解説記事はすでに公開しているので、ここで「実装として何を組み合わせると事故が再発しなくなるか」という設計の話に集中します。
「成功前提」の運用がどこで破綻するか
AI エージェントを使った開発で事故が起きるタイミングは、ほぼ決まっています。
ひとつ目は、Claude が「意図」を取り違えたまま長い作業を走らせてしまう場合です。ユーザーの依頼が曖昧なまま実装を始めると、後半に進むほど誤解の上に誤解が積まれていきます。人間同士であれば途中で「これで合っていますか」と確認しますが、AI は自律的に進めるほど確認を省略します。
ふたつ目は、副作用が見えない場所で発生する場合です。テストを壊した状態でコミットされる、マイグレーションが巻き戻せない形で走る、依存関係が密かに書き換わる、といったケースは、生成されたコードを読んだだけでは気づけません。
みっつ目は、失敗が累積する場合です。ひとつの失敗は気づいて直せても、小さなずれが数ターンにわたって積み上がると、元の状態を復元する方法がわからなくなります。特に AI が自律的にコミットを重ねていく運用では、巻き戻しのコストが指数関数的に上がります。
これらはいずれも「成功前提のワークフロー」で運用しているから起きます。期待した通りに進む前提でコードを書かせ、壊れたときに初めて対処しようとするから、対処できない状態まで進んでしまうのです。
求められるのは逆の思想、つまり「失敗前提のワークフロー」です。計画はずれる、生成は誤る、コミットは壊れる、という前提で仕組みを敷いておき、いつでも戻せる状態を維持します。そうすれば、Claude Code に自律実行を任せても事故がリポジトリに残らない運用が可能になります。
失敗前提ワークフローの全体像
私が現在 Dolice Labs の4つのサイトで実際に回しているワークフローは、Claude Code の5つの仕組みを直列に繋いだシンプルな構成です。
最初に Plan Mode で「何を・どこまで・なぜやるか」を確定させ、次に TodoWrite で工程を細かく分割して進捗を可視化します。危険な操作は Hooks で物理的にブロックし、影響範囲の大きい作業は Subagent に隔離させます。そして万一の際には Rewind でセッション全体を巻き戻します。
重要なのは、この5つを「必要なときに使う」ではなく、「毎回この順番で適用する」と決めてしまうことです。運用を標準化すると、記憶や注意力に依存せず事故を防げます。
次の章からは、それぞれを具体的な実装とともに見ていきます。
Step 1: Plan Mode で「何をやるか」を確定させる
Plan Mode は Claude Code に実装させる前に、計画だけを出力させる専用モードです。Shift+Tab で切り替えるか /plan で入ります。ここで重要なのは「計画を見てから許可する」という順番を強制することです。
実装に入る前に必ず計画を書かせる理由は、意図のずれを早期に検出するためです。曖昧な依頼でも Claude はそれらしい実装を始めますが、Plan Mode を挟むと「この粒度で理解しているのか」が可視化されます。ずれていれば、計画段階で言語化して修正できます。
私の運用では、Plan Mode の出力に以下の3点が含まれているかを必ず確認します。
変更対象のファイルパスが具体的に列挙されているか(曖昧な「関連ファイル」は不可)
変更の順序が可逆な形で分割されているか(マイグレーション → コード → テストの順など)
テスト戦略が明示されているか(既存テストを壊さない方法、新規テストの範囲)
この3点のいずれかが欠けていたら、そのまま実装に入らせず「計画を書き直して」と返します。Claude Code の Plan Mode は、ずれたまま進むのを止めるためのゲートだと考えてください。
Plan Mode の詳細な使い方は別記事で解説しています。ここで運用ゲートとしての位置づけを押さえておいてください。Claude Code Plan Mode 実践ガイド にステップバイステップの設定例があります。
Step 2: TodoWrite で進捗の逃げ道を作る
Plan Mode で計画が確定したら、TodoWrite に落とします。TodoWrite は Claude Code に内蔵のタスクトラッカーで、各ステップを pending → in_progress → completed で管理します。
失敗前提のワークフローで TodoWrite が重要な理由は、途中で止めても再開できる状態を常に保つためです。タスクが粒度よく分割されていれば、どのステップで何が壊れたかが明確になり、そのステップだけ戻せばよくなります。
私が TodoWrite に落とすときに意識しているルールは次の3つです。
1タスクにつき5〜15分で完了する粒度にする(大きすぎると失敗時の被害が増える)
検証ステップを必ず挟む(実装タスクの次は「テスト実行」か「差分レビュー」)
最後のタスクに「コミットする前に人間が確認」を明示的に入れる(自動コミットを禁止する合図)
特に3つ目は、失敗前提ワークフローの肝です。Claude Code に任せた作業の最後は、必ず人間が差分を見る工程を挟んでください。ここを省くと、AI 任せで壊れたコミットが積まれる経路が開いてしまいます。
TodoWrite の粒度と品質パターンは Claude Code TodoList 粒度と品質パターン にまとめています。
Step 3: Hooks で危険な操作を事前に止める
Hooks は Claude Code が特定のイベントを起こした瞬間にスクリプトを実行できる仕組みです。PreToolUse フックを使えば、Claude が「ツールを呼び出す直前」に介入して、危険な操作を物理的にブロックできます。
失敗前提のワークフローでは、Hooks は「人間の注意力を信じない安全装置」として機能します。どれだけ丁寧に計画を作っても、実装中のツール呼び出しで rm -rf や git push --force が走ってしまえば復旧困難です。これを Hooks で常時止める設計にしておきます。
以下は実際に私が ~/.claude/hooks/pre-tool-use-guard.sh として配置しているフックの例です。PreToolUse フックは Claude が実行しようとしているツール名と引数を標準入力 JSON で受け取り、終了コード 2 を返すと実行が拒否されます。
#!/usr/bin/env bash
# ~/.claude/hooks/pre-tool-use-guard.sh
# PreToolUse hook: 危険コマンドを Bash ツール呼び出し段階でブロックする
set -euo pipefail
# Claude Code からの JSON を受信(tool_name, tool_input が含まれる)
payload = $( cat )
tool_name = $( printf '%s' " $payload " | jq -r '.tool_name // ""' )
# Bash ツール以外は素通し(Read/Write/Edit はここで止めない方針)
if [ " $tool_name " != "Bash" ]; then
exit 0
fi
command = $( printf '%s' " $payload " | jq -r '.tool_input.command // ""' )
# 禁止パターン: 破壊的な rm・force push・history 書き換え
forbidden_patterns = (
'rm[[:space:]]+-rf[[:space:]]+/'
'rm[[:space:]]+-rf[[:space:]]+~'
'git[[:space:]]+push[[:space:]]+.*--force'
'git[[:space:]]+push[[:space:]]+.*-f([[:space:]]|$)'
'git[[:space:]]+reset[[:space:]]+--hard[[:space:]]+HEAD~'
'git[[:space:]]+filter-branch'
'git[[:space:]]+checkout[[:space:]]+\.'
'chmod[[:space:]]+-R[[:space:]]+777'
':\(\)\{.*\};:' # fork bomb
)
for pattern in "${ forbidden_patterns [ @ ]}" ; do
if printf '%s' " $command " | grep -Eq " $pattern " ; then
# 終了コード 2 で Claude に拒否理由を伝える
printf 'BLOCKED by pre-tool-use-guard: %s\n' " $pattern " 1>&2
printf 'Command was: %s\n' " $command " 1>&2
exit 2
fi
done
# ホワイトリストに通った場合のみ通す
exit 0
このスクリプトを ~/.claude/settings.json に登録すると、Claude Code が Bash ツールを呼び出そうとするたびに検査が走ります。
{
"hooks" : {
"PreToolUse" : [
{
"matcher" : "Bash" ,
"hooks" : [
{
"type" : "command" ,
"command" : "~/.claude/hooks/pre-tool-use-guard.sh"
}
]
}
]
}
}
動作確認は実際に Claude Code セッション内で「このリポジトリを rm -rf してから再生成して」と指示してみると、フックが BLOCKED by pre-tool-use-guard を返して止まるはずです。Claude 側にはブロック理由が見えるので、そのまま安全な手段(個別ファイルの削除など)へ切り替えさせることができます。
なぜ正規表現でパターンマッチしているかというと、Claude は文脈に応じて微妙に違う書き方をすることがあるからです(rm -rf ./ と rm -rf /home/user/ は厳密には違いますが、どちらもブロック対象にしたい)。ホワイトリスト方式で特定コマンドだけを通す設計も選べますが、開発中の柔軟性を考えると「明確に危険なパターンだけ落とす」ブラックリスト方式が現実的です。
Hooks の他のイベント(PostToolUse・UserPromptSubmit・Stop 等)と組み合わせれば、コミット直前に自動テストを走らせる仕組みや、長時間セッションで一定時間ごとにチェックポイントを強制作成する仕組みも作れます。入門は Claude Code Hooks 自動化テクニック から始めるのが早いです。
Step 4: Subagent で影響範囲を隔離する
Subagent は Claude Code から別のエージェントを起動して、独立したコンテキストで作業させる仕組みです。メインセッションから Task ツールで呼び出すと、指定した役割のサブエージェントが別プロセスで動き、結果だけを返してきます。
失敗前提のワークフローで Subagent が効くのは、「壊れてもメインの文脈を汚さない」という性質のおかげです。たとえば依存ライブラリのアップグレードは、影響範囲が広く失敗したときの復旧も重いので、メインセッションでいきなり走らせるとリスクが大きすぎます。これを Subagent に隔離すると、サブエージェントが内部で失敗しても、結果として返ってくるのは「やってみたが失敗した」というレポートだけで、メインリポジトリには痕跡が残りません。
以下は実際に私が使っているサブエージェント定義の例です。~/.claude/agents/dependency-upgrader.md に配置します。
---
name : dependency-upgrader
description : npm/pnpm パッケージのマイナーアップデートを一括で試す。型エラーとテスト失敗を必ずレポートし、コミットは行わない。
tools : Bash, Read, Edit, Grep, Glob
---
あなたは依存関係アップグレードの専門エージェントです。以下のルールを厳守してください。
# 目的
package.json に記載されたパッケージのうち、メジャーバージョンを上げず、マイナー/パッチのみを更新する。
# 手順
1. `npm outdated --json` で差分一覧を取得する
2. メジャーバージョンが上がるものは除外する
3. `npm update` で一括更新する(個別更新は不要)
4. `npm run typecheck` を実行し、結果を保存する
5. `npm test -- --run` を実行し、結果を保存する
6. 失敗があれば、そのパッケージだけを元のバージョンに戻す
# 禁止事項
- package.json の手動編集は行わない(npm コマンド経由のみ)
- コミット・プッシュは絶対に行わない(レポートのみ返す)
- メジャーバージョンのアップグレードは提案もしない
- node_modules の直接編集は行わない
# 出力フォーマット
更新に成功したパッケージと、失敗して戻したパッケージを以下の形式で返す:
## Succeeded
- <package>: <old> → <new>
## Reverted
- <package>: <reason>
## Next Steps
人間が確認すべき差分を箇条書きで示す。
この定義をメインセッションから @dependency-upgrader マイナー更新を試して のように呼び出すと、別プロセスで走ります。サブエージェントはコミット権限を意図的に持たせていないので(tools に Bash は入っていますが、プロンプト側でコミット禁止を明記しています)、仮に暴走しても影響範囲は node_modules と package-lock.json の変更止まりです。
Subagent 設計のコツは、権限を最小化し、出力フォーマットを固定することです。権限を広げると「気が利いた」動作をしてほしくなりますが、失敗前提のワークフローでは気が利くより壊さないほうが価値が高いです。実装の詳細は Claude Code Subagent パターン を参照してください。
Step 5: Rewind で「戻せる」保険をかける
Rewind は Claude Code のチェックポイント機能で、セッション中のファイル状態とメッセージ履歴を巻き戻せる仕組みです。/rewind コマンドで履歴のリストが表示され、任意の時点に戻ります。
失敗前提のワークフローで Rewind が最後の砦になる理由は、Plan Mode で意図を詰め、Hooks で危険操作を塞ぎ、Subagent で範囲を隔離しても、それでも発生する「文脈レベルの破綻」に対処できるためです。たとえば Claude が途中で仕様を別方向に解釈し始めた場合、個々のツール呼び出しは正しくても、全体としては別のものを作っている状態になります。こうしたケースでは Rewind で丸ごと戻すのが最も早いです。
私の運用では、Rewind を次の3つの場面で意図的に使います。
Plan Mode の計画とズレ始めたと感じた時点で、計画決定後まで戻す
テストが通らないコミットを作ってしまった場合、直前のグリーン状態まで戻す
サブエージェントの出力を受け取って反映したあと、意図と違うと分かった時点で反映前まで戻す
Rewind を「最後の手段」だと思わない点が肝心です。早めに使えば使うほど被害が小さく、失敗からの学習サイクルも短くなります。Rewind 運用の詳細は Claude Code /rewind コマンドとチェックポイント機能 完全ガイド で解説しています。
統合ワークフロー: 4つを1つのルーチンに束ねる
ここまでの5ステップを、私が実際に日々回しているルーチンとして1本にまとめます。新機能の実装・バグ修正・リファクタリングの区別なく、本番リポジトリで Claude Code を使うときはこの順番で進めています。
[0] リポジトリ状態をクリーンにする(git status で変更なしを確認)
↓
[1] Plan Mode で実装計画を出力させる(/plan)
- ファイルパス・変更順序・テスト戦略の3点を必ず含める
- 不足していれば「計画を書き直して」と返す
↓
[2] TodoWrite で計画をタスク分解させる
- 1タスク5〜15分粒度
- 検証ステップを各実装タスクの後に挟む
- 最後に「差分レビュー」タスクを必ず置く
↓
[3] 実装を開始させる(ここから Hooks が常時監視)
- PreToolUse フックが危険コマンドを自動ブロック
- 影響範囲が広い作業は Subagent に委譲
↓
[4] 各タスク完了後、TodoWrite の検証ステップで差分をレビュー
- ずれを感じたら即 /rewind
- テスト失敗なら直前のグリーン状態まで戻す
↓
[5] 最終タスク「差分レビュー」で git diff を人間が確認
- 問題なければ、人間がコミットメッセージを書いてコミット
- Claude 側に自動コミットさせない
このルーチンで重要なのは、Claude Code 側に自律コミットを任せないことです。実装・テスト・ドキュメント生成までは自動で進ませますが、コミットだけは必ず人間のゲートを通します。差分を目で見てから git commit するという1ステップを残すだけで、事故が main に流れる確率は劇的に下がります。
私の経験では、このルーチンを徹底してから Claude Code 起因の事故がほぼゼロになりました。以前は月に1〜2回、壊れたコミットをロールバックしていましたが、Plan Mode と Hooks の導入後はこの数ヶ月ほぼ発生していません。
よくある落とし穴と対処
失敗前提ワークフローを導入する過程でつまずきやすいポイントを3つ挙げておきます。
Plan Mode の計画を読まずに承認してしまう
最もよくある事故の原因です。Plan Mode は Claude に計画を書かせるだけで、人間が読まないと意味がありません。忙しいときほど「OK」で流してしまいがちですが、ここで5分の確認を省いたせいで1時間のロールバックが発生します。
対処としては、Plan Mode の出力を読み終わるまで明示的に次のコマンドを打たないルールにすることです。私はタイマーを5分セットし、そのあいだは画面を見るか、コーヒーを淹れに行くかします。こうすると「つい OK」を防げます。
Hooks の禁止パターンが厳しすぎて進まない
Hooks で守りを固めすぎると、今度は正当な操作までブロックされて開発が止まります。よくあるのが、git reset --hard を全面禁止にしたところ、Rewind 後の整合を取るための正当な reset まで止まってしまうケースです。
対処は、禁止パターンを「ルート直下への破壊」「履歴改変」「権限過剰」の3つに絞ることです。上のスクリプト例では HEAD~ 付きの reset だけを禁止しており、git reset --hard HEAD(ワーキングツリーの破棄のみ)は通しています。運用を回しながらブロックされた正当操作を記録しておき、定期的にパターンを見直してください。
Subagent の出力を鵜呑みにしてメイン文脈に反映してしまう
Subagent は独立した文脈で動くので、出力フォーマットを固定しないと「何を・どこまでやったか」が曖昧なレポートが返ってきます。これをメインセッションの Claude がそのまま信じて先に進むと、実際には行われていない作業を前提にコードを書き始めます。
対処は、Subagent 定義の # 出力フォーマット を具体的に書くことと、メインセッション側でも「Subagent の出力から、実際に変更されたファイルパスを列挙して」と再確認させることです。抽象的な「成功しました」という返答だけで次に進まないでください。
全体を振り返って: 次に試すべき一歩
本稿で紹介した失敗前提ワークフローは、一度に全部導入する必要はありません。効果が出やすい順に入れていくのがおすすめです。
最初に手を付けるなら、Plan Mode の徹底です。設定変更は不要で、Claude Code セッションで /plan と打つ習慣をつけるだけで始められます。これだけでも意図のずれが減り、半分くらいの事故は消えます。
次に試すなら、Hooks の PreToolUse フックです。上のスクリプトをそのままコピーして ~/.claude/hooks/ に置き、settings.json に追記すれば動きます。30分の設定で、破壊的コマンドに対する防御線が1本増えます。
Subagent と Rewind は運用が安定してきた段階で追加してください。いきなり全部入れると、どれが効いているのか分からなくなります。
明日からでもできる具体的な最初の一歩は、次に開く Claude Code セッションで /plan と打ってから依頼文を書くことです。5分かかるかもしれませんが、その5分が事故を防ぐ一番低コストな投資になります。
UNIX文化における「小さな部品を組み合わせる」「失敗しても復旧可能にする」という発想は、AIコーディングの運用設計にそのまま適用できます。