Can Claude Code handle code migrations?
Yes. Claude Code can upgrade frameworks, move code between languages and apply the same change across thousands of files, as long as you give it a way to check its own work. The test suite, the compiler and a written set of rules do most of the quality control; Claude does the volume.
Migrations suit an agent better than most tasks. The old code already describes the behavior you want, the tests say whether the new code matches, and the work splits into many small pieces that can run in parallel. Claude Code adds the pieces that make this practical: plan mode, subagents, worktrees, a /batch command and dynamic workflows. This guide covers what fits, a workflow, prompts and the traps to avoid.
What kinds of migrations fit Claude Code?
- Framework and library upgrades. Find every call to a deprecated API, plan the replacement and update call sites. Anthropic's common workflows page starts a refactor with "find deprecated API usage in our codebase".
- Language version upgrades. Python 2 to Python 3 is the example the best practices page uses for fanning out across files.
- Typing an untyped codebase. JavaScript to TypeScript is the example given for both
/batchand dynamic workflows. - Full language ports. Moving a project from one language to another, the largest kind, is covered in Anthropic's write-up below.
- Schema and API changes. Expand and contract changes, adapters and strangler patterns, which the deprecation and migration skill describes.
Migrations that need heavy redesign, not translation, still need a human design pass first. Claude can help draft and stress-test that design, but the decisions are yours.
How does Anthropic run large migrations with Claude Code?
Anthropic published how it runs large-scale code migrations with Claude Code. Two examples stand out. Jarred Sumner ported Bun from Zig to Rust, about a million lines in under two weeks, with 100% of the existing test suite passing in CI before merge; 19 regressions surfaced after merge and all were fixed. Mike Krieger ported a Python codebase to 165,000 lines of TypeScript over a weekend, with a final parity check that diffed every command's output against the Python original.
The process behind both is worth copying, even for much smaller jobs:
- Build a judge first. Get tests that run against both the old and new code, and check that they catch deliberately broken code. In the article's words, "a judge that doesn't catch breakage isn't a judge."
- Write a rulebook. Record translation rules, a dependency map and a list of gaps between the two languages before translating anything.
- Stress-test the rules on a small throwaway migration and add rules from what goes wrong.
- Translate in loops of implement, review and fix, with reviewers in separate contexts.
- Compile, run and match behavior, grouping failures by root cause rather than fixing them one at a time.
The core lesson: "you don't fix the code. You fix the process (loop) that produced the code." When the same mistake repeats, update the rulebook and regenerate, instead of patching files by hand. The article is also open about cost: the Bun port used billions of input tokens, so budget before you scale up.
What does a migration workflow look like in practice?
- Make the check runnable. Confirm
npm test,pytestor your build passes before you start, and fix flaky tests first. Anthropic's best practices put it plainly: give Claude "a check it can run". - Write the rules down. Put target versions, patterns to use, patterns to avoid and "do not change test assertions" in
CLAUDE.mdor a rules file. See the CLAUDE.md guide. - Plan before editing. Start with
claude --permission-mode plan, or pressShift+Tabuntil plan mode is on. Claude reads files and proposes a plan but makes no edits until you approve. The plan mode guide covers the flow. - Pilot on two or three files. The best practices page says to refine your prompt "based on what goes wrong with the first 2-3 files, then run on the full set."
- Fan out. Use
/batch, a dynamic workflow or aclaude -ploop (compared below). - Gate on the check. Use
/goalso Claude keeps going until the condition holds; the goal docs list "Migrating a module to a new API until every call site compiles and tests pass" as a typical use. - Review independently. Run
/code-reviewon the diff, or a subagent with your plan as the checklist, then review the pull request yourself.
Which Claude Code features help with a migration?
| Feature | What it does for a migration |
|---|---|
| Plan mode | Reads and proposes without editing, so you approve the approach first |
| Code intelligence plugins | Connect a language server so Claude sees type errors its edits introduce and finds references by symbol |
/batch <instruction> |
Splits a change into 5 to 30 units, each run by a background subagent in its own worktree |
| Dynamic workflows | A script Claude writes to run dozens to hundreds of subagents, which you can save and rerun |
claude -p loop |
Your own script calls Claude once per file, with pre-approved tools |
/goal |
Keeps Claude working across turns until a stated condition is met |
| Worktrees | claude --worktree <name> gives each session its own checkout and branch |
| Checkpoints | /rewind undoes Claude's file edits; files changed only by shell commands need git |
Dynamic workflows are available on all paid plans, and on Pro you turn them on from the Dynamic workflows row in /config. The workflows page includes this example prompt for a migration: "use a workflow to migrate every component under src/components/ from JavaScript to TypeScript, working on each file in its own isolated copy". The docs also warn that ultracode, a setting that plans a workflow for every substantive task, uses more tokens per request, so a session with it on reaches its usage limits sooner.
For a scripted fan-out, the best practices page shows a loop over a file list. This is its example, unchanged:
for file in $(cat files.txt); do
claude -p "Migrate $file from Python 2 to Python 3. Return OK or FAIL." \
--allowedTools "Edit,Bash(git commit *)" \
--permission-mode dontAsk
done
--permission-mode dontAsk denies anything not pre-approved, which matters for unattended runs. The headless guide covers the other flags.
Which prompts work well for migrations?
These are example prompts written for this guide. Adjust paths and versions to your project.
Find every use of the deprecated v1 client in src/. Group the call sites by pattern, propose a replacement for each pattern, and write the plan to MIGRATION.md. Do not edit code yet.
Migrate src/billing/ to the v2 client following MIGRATION.md. After each file, run the type checker and the billing tests. Do not change any test assertions. If a test fails for a reason the plan does not cover, stop and tell me.
Use a subagent to review this migration diff against MIGRATION.md. Flag weakened or deleted assertions, behavior changes, and any file outside src/billing/ that changed. Report gaps, not style.
/goal every file in src/legacy/ compiles under the new tsconfig, npm test exits 0, and no file under tests/ is modified, or stop after 20 turns
The refactoring prompts collection has more starting points.
What can go wrong, and how do you guard against it?
- Weakened tests. An agent told to make tests pass can edit the tests. Anthropic's article uses adversarial agents to check that rewritten tests don't weaken assertions. Locally, add an ask rule so Claude must ask before touching tests.
- Repeated mistakes. Fix the rule or prompt and regenerate, rather than hand-patching dozens of files.
- Runaway cost. Pilot first, use smaller models for routine translation where you can, and watch usage. The article's advice: "Don't use the largest model for everything."
- Lost work. Commit often.
/rewinddoes not undo files changed only by shell commands.
Here is an example project settings file, written for this guide with the documented permission rule syntax, not copied from Anthropic's docs. It makes Claude ask before editing anything under tests/ and blocks pushes:
{
"permissions": {
"ask": ["Edit(/tests/**)"],
"deny": ["Bash(git push *)"]
}
}
Rules are evaluated in order: deny, then ask, then allow. Pair this with the testing guide for building a stronger safety net before you start.
Can Codex or Cursor run migrations too?
Yes. OpenAI's Codex GitHub Action runs codex exec in CI and lists migrations among the repeatable tasks it can run from a workflow file; see the codex exec guide. Cursor's CLI has a -p print mode for scripts, covered in the Cursor CLI guide. The method above applies to any agent: a judge, a rulebook, a pilot and independent review.
How do you reuse migration prompts across projects?
The rulebook and review prompts are the part worth keeping. Kipt saves prompts and Agent Skills as Markdown in a private GitHub repo you own, with {{name}} blanks for things like the source and target versions, and installs your skills into Claude Code or Codex with one npx skills add command. To turn a migration prompt into a skill folder, try the free SKILL.md generator.