AI code migration: upgrade frameworks and languages with agents, safely

AI code migration: upgrade frameworks and languages with agents, safely

AI code migration means using coding agents, often alongside codemods, to move a codebase to a new framework, library version or language, with tests deciding when each file is done. This playbook covers which migrations suit AI, how to plan one, when to use codemods instead, how to run batches in parallel, and how to review the result without drowning.

In shortTL;DR
  • Agents handle the long tail of a migration that codemods can't express; codemods handle the mechanical, uniform changes more cheaply and predictably. Use both.
  • Write a migration guide (before and after examples, rules, definition of done) and pilot it on 10 to 20 representative files before scaling.
  • Gate every file on validation steps (tests, lint, type check) with retry loops; Airbnb used this shape to migrate nearly 3.5K test files in 6 weeks.
  • Fan out with claude -p in a loop or Claude Code's /batch, each worker in its own git worktree, then merge in small, reviewable pull requests.
  • Keep characterization tests and a rollback path; never ship a migration whose only evidence is that it compiles.

What is AI code migration?

AI code migration is the use of coding agents and language models to carry out a large, repetitive change across a codebase: upgrading a framework version, replacing a library, moving from JavaScript to TypeScript, or translating code to another language. The agent edits the files; tests, linters and type checkers decide whether each edit is acceptable.

Migrations suit AI well because they are wide rather than deep. The same kind of change repeats across hundreds or thousands of files, each slightly different, and the slight differences are what make pure find-and-replace or codemods fall short. That long tail is where engineers used to spend months.

Typical candidates:

  • Framework major versions (React, Angular, Django, Rails, Spring)
  • Test framework changes (Enzyme to React Testing Library, Mocha to Vitest, unittest to pytest)
  • Language upgrades (Python 2 to 3, Java 8 to 21) and gradual typing (JavaScript to TypeScript)
  • API replacements (deprecated SDK to its successor, one logging or HTTP library to another)

What results are realistic for AI-assisted migrations?

Published experience reports show large time savings when a strong validation pipeline is in place, with engineers still finishing the hardest files by hand. They don't show agents completing big migrations unattended and unreviewed.

Airbnb's engineering team described migrating nearly 3.5K React component test files from Enzyme to React Testing Library. They had estimated 1.5 years of manual engineering time and finished in 6 weeks. Their pipeline moved each file through validation steps (fixing Jest failures, then lint and TypeScript errors) with LLM-driven retry loops. It migrated 75% of target files in the first four hours, reached 97% after about four days of tuning, and engineers finished the remaining 3% over roughly another week.

Google's experience report on internal code migrations reaches a similar, qualitative conclusion: LLMs can reduce the time needed for migrations significantly and lower the barrier to starting them.

The common thread is that tests and automated checks did the verification, the long tail still needed people, and the work was organized as a pipeline rather than a single giant prompt.

Expect less from cross-language rewrites than from upgrades within one ecosystem. Moving a service from one language to another changes the standard library, concurrency model, error handling and third-party packages all at once, and behavior hides in those details. The translated code can read well and still differ in how it rounds numbers, parses dates or handles a null. If you must change languages, do it module by module behind a stable interface, run both implementations against the same inputs, and compare outputs before switching traffic. That comparison catches the differences that unit tests written in the new language would never think to check.

How do you plan an AI-assisted migration?

Plan the migration as you would for a team of new engineers: write down the rules, show examples, define done, and start with a pilot. An agent follows a clear migration guide far more consistently than ad-hoc prompts.

  1. Inventory. List every file affected and classify by pattern: simple, common variations, unusual. A coding agent can produce this list with counts.
  2. Strengthen tests first. Where the code to migrate has weak coverage, add characterization tests before changing anything. Our guide to refactoring legacy code with AI covers this step.
  3. Write the migration guide. A markdown file in the repository with rules and before and after examples.
  4. Define done per file. For example: tests pass, lint passes, type check passes, no new any, no skipped tests, no changed assertions.
  5. Pilot on 10 to 20 files chosen to cover each pattern. Fix the guide after every failure.
  6. Scale in batches, reviewing a sample of each batch.

A migration guide that works:

docs/migration-enzyme-to-rtl.md
## GoalReplace Enzyme with React Testing Library in \*.test.tsx files.## Rules- Query by role or label (`getByRole`, `getByLabelText`), not by class or test id, unless no accessible query exists- Replace `wrapper.setState` with user interactions via `userEvent`- Do not change what a test asserts; if an assertion depends on internals, keep its intent and add a comment `MIGRATION-NOTE:`- Never delete or skip a test## ExampleBefore: `expect(wrapper.find('.error').text()).toBe('Required')`After: `expect(screen.getByRole('alert')).toHaveTextContent('Required')`## Done when`pnpm vitest run <file>` passes, `pnpm lint <file>` passes, `pnpm tsc --noEmit` passes

For writing task specs in general, see our guide on how to write tasks for AI coding agents.

Codemods or AI agents: which should do the migration?

Use codemods for changes that follow an exact syntactic pattern and agents for changes that need judgment. A codemod is a program that rewrites code through its syntax tree; it is fast, deterministic and free to run, but every edge case must be coded by hand.

ChangeBetter tool
Rename an import or function everywhereCodemod
Change an argument order consistentlyCodemod
Replace a deprecated API with a direct equivalentCodemod
Rewrite tests to a different testing approachAgent
Convert class components with lifecycle logic to hooksAgent
Add types to untyped JavaScriptAgent, then type checker
Files the codemod fails onAgent

The hybrid is usually best, and agents are good at writing codemods. Ask the agent to write a codemod for the mechanical part with jscodeshift, OpenRewrite, ast-grep or your language's equivalent, run it, and then work only on the files it couldn't handle:

prompt
Write a jscodeshift transform in codemods/rename-logger.ts that replacesimports of `legacyLogger` from 'src/log' with `logger` from 'src/lib/logger'and renames all call sites. Add tests for the transform with three fixturepairs. Run it on src/ in dry-run mode and list files it skipped or failed on.

The codemod gives you a predictable change you can review once; the agent handles the remainder file by file.

How do you run a migration in parallel batches?

After the pilot, run the migration file by file in parallel, each worker isolated, each file validated before it counts as done. Claude Code supports two ways to fan out.

Claude Code's /batch command. The best practices guide describes /batch <instruction> as splitting a change across 5 to 30 subagents, each working in its own git worktree. It suits medium migrations you supervise in one session.

A script that loops over claude -p. For larger or longer runs, generate a file list and run one non-interactive session per file, with only the tools the migration needs. This follows the pattern in the same guide:

migrate.sh
for file in $(cat files-to-migrate.txt); do  claude -p "Migrate $file following docs/migration-enzyme-to-rtl.md. \Run the file's tests, lint and tsc until they pass. Do not change assertions. \Reply with OK or FAIL and one line explaining why." \    --allowedTools "Edit,Bash(pnpm vitest run *),Bash(pnpm lint *),Bash(pnpm tsc *)" \    --permission-mode dontAsk >> migration-log.txtdone

The dontAsk permission mode allows only the pre-approved tools and denies anything else instead of stopping to ask, which is what an unattended loop needs. Run it on the pilot files first, read the log, fix the guide, then run the rest.

To run several workers at once without them overwriting each other, give each its own git worktree and branch; our guide to git worktrees for parallel agents shows the setup and cleanup.

Tip

Collect every FAIL into a second list. Rerunning failures once or twice often succeeds, which matches Airbnb's finding that retry loops helped more than prompt tweaking. What still fails after that goes to an engineer.

Batch runs over hundreds of files take hours. If you don't want them tied to your laptop staying awake, Orkio runs Claude Code on an always-on cloud box with your own Claude account, so the batch keeps going overnight and the branches are waiting for review in the morning.

How do tests keep an AI migration safe?

Tests are the definition of done in an AI migration: a file is migrated when its checks pass, not when the agent says so. Without them you are reviewing thousands of diffs by eye.

Build the safety net in layers:

  • Characterization tests for code with weak coverage, written before the migration starts.
  • Per-file validation steps run in order: unit tests, lint, type check, then build.
  • No weakening. Rules in the guide and in your review: no deleted, skipped or loosened tests. Check with git diff for changes to assertion lines.
  • Full-suite and end-to-end runs per batch, because a file can pass its own tests and break a caller.
  • Production signals after release: error rates and key metrics, with a rollback ready.

Remember that Claude Code's checkpoints only track edits made with its file tools, not changes made by shell commands such as a codemod run. Commit before each batch so git can undo anything. For writing tests that would catch a real regression, see our guide on how to write unit tests with AI.

How do you review and merge a large AI migration?

Review a large migration in small pull requests grouped by pattern, with the mechanical parts reviewed once and the judgment parts sampled carefully. A single 2,000-file pull request gets rubber-stamped; twenty focused ones get read.

  • Separate codemod output from agent output. Review the codemod's transform and tests once, then skim its output. Spend attention on agent-edited files.
  • Group by directory or pattern so each pull request has one kind of change.
  • Sample deliberately. Read every file in the first batches, then a random 10 to 20% of later batches, plus every file that needed retries.
  • Search for the migration notes. MIGRATION-NOTE: comments mark places the agent was unsure; read each one.
  • Use a second reviewer model for a first pass on each pull request, keeping the human review.
  • Release behind a flag or in stages where the migration changes runtime behavior, not only tests.

What mistakes derail AI code migrations?

The failures repeat across teams, and each has a simple countermeasure:

MistakeCountermeasure
Starting at full scale without a pilotPilot 10 to 20 files and fix the guide first
No definition of donePer-file validation steps that must pass
Agent loosens tests to passRule against assertion changes; diff check
One huge pull requestSmall PRs grouped by pattern
Mixing the migration with refactorsMigration only; improvements in separate PRs
Ignoring the long tailPlan engineer time for the last few percent
Context overload from giant promptsOne file per session, guide in a file the agent reads

Your migration checklist

Use this list to start your next upgrade:

  • Inventory affected files and classify them by pattern
  • Add characterization tests where coverage is weak
  • Write the migration guide with rules, examples and a definition of done
  • Use a codemod for the mechanical part; have an agent write it
  • Pilot on 10 to 20 representative files and refine the guide
  • Fan out with /batch or a claude -p loop in isolated worktrees
  • Retry failures, then hand the remainder to engineers
  • Merge in small pull requests with sampled human review and a rollback plan

Frequently asked questions

Can AI convert code from one language to another?

Yes, for well-scoped modules with good tests, such as Python 2 to 3, JavaScript to TypeScript, or Java to Kotlin. Whole-application rewrites across languages are much riskier, because behavior hides in libraries, runtime details and edge cases. Convert module by module behind tests rather than in one pass.

How long does an AI-assisted migration take?

It depends on size, test coverage and how uniform the code is. Airbnb reported finishing a test framework migration estimated at 1.5 years of manual work in 6 weeks, but that relied on a strong validation pipeline and engineers finishing the hardest files by hand.

Should I use codemods or an AI agent for a migration?

Use a codemod when the change is a precise syntactic pattern that applies the same way everywhere, such as renaming an import. Use an agent when each file needs judgment, such as rewriting tests to a new testing philosophy. Many teams have the agent write the codemod, then run the agent only on files the codemod can't handle.

What is the biggest risk in AI code migration?

Silent behavior changes that pass weak tests. An agent can make code compile and tests pass by changing what the code does or loosening assertions. Strong characterization tests, rules against editing assertions, and review of a sample of every batch reduce that risk.

Which AI tools are used for large migrations?

Terminal coding agents such as Claude Code and Codex, run interactively for the pilot and non-interactively in scripts for batches, plus codemod frameworks such as jscodeshift, OpenRewrite or ast-grep for mechanical changes. Large companies also build internal pipelines on model APIs.

SOURCES

  1. Airbnb Tech Blog: Accelerating Large-Scale Test Migration with LLMs
  2. How is Google using AI for internal code migrations? (arXiv)
  3. Claude Code docs: Best practices
  4. Claude Code docs: Choose a permission mode
  5. Claude Code docs: Checkpointing
  • #code migration
  • #refactoring
  • #codemods
  • #claude code
  • #ai agents
Orkio team

The team building Orkio. We write about putting AI to work: coding agents that run overnight, always-on boxes and pull requests ready by morning.

Keep reading

All posts

07:06 · YOU MERGED #128

Go to sleep. Wake up to pull requests.

Start for $19 a month
© 2026 Orkio · Hosted in Europe TürkçeStatus