TL;DR
Large migrations fail when an agent jumps straight to editing and fills its
context with the wrong files. The reliable pattern in Claude Code is to separate
research from execution: explore in plan mode, commit to a written plan, then
implement against a check Claude can run itself. Use /rewind checkpoints to back
out of dead ends, delegate exploration and review to subagents to keep the main
context clean, and fan out with claude -p when the same change has to land across
hundreds of files.
Key points:
- Use the four-phase loop: explore, plan, implement, verify.
- Give Claude a verification check (tests, build, linter) so it can iterate on its own.
- Checkpoints (
/rewind, Esc Esc) let you try risky changes and revert; they are local undo, not a replacement for git.
- For batch migrations, generate a file list and loop
claude -p over it with scoped --allowedTools.
Overview
A migration or large refactor is the case where Claude Code's main constraint
matters most: the context window holds the entire conversation, every file read,
and every command output, and model performance degrades as it fills. A naive
"migrate the whole codebase" prompt reads hundreds of files into one context and
produces worse edits as it goes.
The workflow below keeps each phase scoped. Exploration and review happen in
subagents or plan mode so they don't pollute the implementation context.
Implementation runs against a check that returns pass or fail, so Claude closes
its own loop instead of waiting for you to spot every mistake. And checkpoints
make ambitious, wide-scale changes safe to attempt because any step is reversible.
Workflow at a glance
Best for: framework upgrades, API/pattern migrations, large refactors, codemods
Core loop: explore -> plan -> implement -> verify
Key tools: plan mode, /rewind, subagents, claude -p fan-out
Safety net: session checkpoints plus git commits
The migration workflow
The recommended workflow has four phases. Run them in order; for a small,
one-sentence-diff change you can skip planning and ask Claude to do it directly.
# 1. EXPLORE — read and understand, no edits yet (plan mode)
claude --permission-mode plan
# In session:
# read /src/auth and explain how sessions and login work today.
# look at how environment variables for secrets are managed.
# Or delegate the reading so only findings return to your context:
# use a subagent to investigate how token refresh works and
# whether we already have OAuth utilities to reuse.
# 2. PLAN — produce a reviewable plan before anything touches disk
# In plan mode:
# I want to migrate this module to the new API. What files change?
# What is the order of operations? Create a detailed plan.
# Press Ctrl+G to open the plan in your editor and refine it.
# 3. IMPLEMENT — leave plan mode, code against a check it can run
# In default mode:
# implement the migration from your plan. run the test suite
# after each file and fix failures. address root causes.
# 4. VERIFY — fresh-context review of the diff, then commit
# /code-review # bundled skill: reviews the diff in a subagent
# commit with a descriptive message and open a PR
# If an approach goes wrong at any point, back out and retry:
# /rewind # or press Esc Esc on an empty prompt
Why each phase exists
- Explore keeps Claude from solving the wrong problem. Plan mode reads files
and answers questions but makes no edits until you approve.
- Plan gives you a diff you can review before code is written. Press
Ctrl+G
to open the plan in your text editor and edit it directly.
- Implement is where a verification check pays off: Claude does the work, runs
the check, reads the result, and iterates until it passes. Without a check,
"looks done" is the only signal and you become the verification loop.
- Verify with a fresh context. A reviewer subagent sees only the diff and your
criteria, not the reasoning that produced the change, so it grades the result on
its own terms.
Phase reference
| Phase |
What you do |
Command or action |
| Explore |
Read code, ask questions, no edits |
claude --permission-mode plan, or Shift+Tab to toggle plan mode mid-session |
| Explore (delegated) |
Offload file reads so only findings return |
use a subagent to investigate X |
| Plan |
Produce and refine a written plan |
Ask for a plan in plan mode; Ctrl+G to edit it |
| Implement |
Code against a runnable check |
Leave plan mode; ask Claude to implement and run tests/build |
| Verify |
Fresh-context review of the diff |
/code-review, or a verification subagent |
| Recover |
Undo a bad step |
/rewind or Esc Esc |
| Commit |
Persist the change |
commit ... and open a PR (uses gh pr create) |
| Resume |
Continue across sittings |
claude --continue or claude --resume |
Checkpoints: try risky changes safely
Claude Code automatically snapshots files before each edit, and every prompt you
send creates a checkpoint. This lets you attempt a wide-scale change and revert if
it doesn't work, instead of planning every move defensively.
Run /rewind, or press Esc twice when the prompt input is empty, to open the
rewind menu. From there you can:
- Restore code and conversation — revert both to a prior checkpoint
- Restore conversation — rewind the chat but keep current code
- Restore code — revert file changes but keep the conversation
- Summarize from here / up to here — compress part of the conversation to free context
Checkpoints persist across sessions and are cleaned up with the session after 30
days (configurable). Two limits matter for migrations:
- Bash changes are not tracked. Files modified by
rm, mv, or cp cannot be
undone through rewind. Only direct edits from Claude's file-editing tools are tracked.
- It is not version control. Treat checkpoints as local undo and git as
permanent history. Commit before a large migration so you have a real fallback.
Fan out across many files
When the same change has to land across hundreds or thousands of files, distribute
the work across parallel non-interactive invocations instead of one long session.
# 1. Have Claude list the files that need migrating
# e.g. ask it to write files.txt containing every file to change
# 2. Loop claude -p over the list with scoped tools
for file in $(cat files.txt); do
claude -p "Migrate $file from React to Vue. Return OK or FAIL." \
--allowedTools "Edit,Bash(git commit *)"
done
# 3. Test on 2-3 files, refine the prompt, then run the full set
--allowedTools restricts what each unattended invocation can do, which is the key
safety control when no human is approving steps. For batch runs that need to keep
moving without prompts but with a safety classifier, use auto mode:
claude --permission-mode auto -p "fix all lint errors"
For non-interactive runs, auto mode aborts if the classifier repeatedly blocks
actions, since there is no user to fall back to.
Set up before a large migration
- Write a CLAUDE.md. Run
/init to generate a starter file, then add the build
command, test runner, and any code-style rules that differ from defaults. Claude
reads it at the start of every conversation. Keep it short — a bloated CLAUDE.md
causes Claude to ignore your actual instructions.
- Define the verification check. Have a test suite, build, or linter ready so
Claude can self-correct. Spell out the check in the prompt: "run the tests after
implementing and fix failures."
- Reference existing patterns. Point Claude at a file that already follows the
target pattern (for example, "follow the pattern in HotDogWidget.php") rather than
describing it abstractly.
- Commit first. Get a clean git state so
/rewind plus git together cover both
session-level and permanent recovery.
Manage context during the migration
Long migrations fill the context window with file contents and failed attempts,
which degrades quality. Manage it actively:
/clear between unrelated tasks to reset context entirely.
- If you've corrected Claude more than twice on the same issue,
/clear and restart
with a sharper prompt that incorporates what you learned. A clean session with a
better prompt almost always beats a long polluted one.
- Use subagents for exploration and review so those file reads never enter the main
context.
- When approaching limits, Claude auto-compacts; for control use
/compact <instructions>,
for example /compact Focus on the API changes.
Troubleshooting
Claude edits the wrong files or solves the wrong problem. You skipped
exploration. Start in plan mode (claude --permission-mode plan or Shift+Tab),
have it read the relevant code and produce a plan, and approve it before any edits.
A change broke something and you want to back out. Run /rewind (or Esc Esc
on an empty prompt) and restore code, conversation, or both to a prior checkpoint.
If the breakage came from a bash command (rm/mv/cp), rewind won't help —
recover from git instead.
Quality degrades partway through a long session. The context window is filling.
/clear between tasks, delegate reads to subagents, or /compact with focus
instructions. After two failed corrections on the same issue, clear and restart.
Claude reports success but edge cases are broken. Don't trust unverified output.
Add a verification check it must run, and add an adversarial review step with
/code-review or a verification subagent that sees only the diff.
The fan-out loop does something unintended. Tighten --allowedTools to the
minimum set (for example "Edit,Bash(git commit *)") and test on a few files
before running at scale.
Related resources and next steps
Last reviewed: 2026-06-16. Grounded in the official Claude Code documentation for common workflows, best practices, and checkpointing. Part of the HeyClaude guides collection.