Large Multi-File Changes and Refactors

Small edits with a coding agent are easy. The hard part is the change that touches twenty files: renaming a core type, extracting a service, swapping one library for another. This is where agents feel most powerful and where they most often leave you with a broken branch and a diff you cannot read.

The mistake is treating a big refactor like a big prompt. You do not fire one request and hope. You run it like a real engineering task: plan, small steps, tests between them, and a clean way to roll back.

Why big changes are where agents shine and go wrong

A large refactor is exactly the kind of tedious, mechanical work an agent is good at. Renaming a symbol across the repo, updating every call site, fixing the imports: boring for a human, fast for a model. It can grind through fifty files without missing a spot the way you would at file forty.

That same reach is the danger. Blast radius scales with the number of files touched. When a normal edit goes wrong, you have one bad function. When a refactor goes wrong, you have a branch where nothing compiles, a mix of correct and broken changes, and no idea which of the fifty edits caused the failure.

The model also loses the thread on long tasks. It starts strong, then drifts: invents a helper that already exists, half-migrates one module, or “improves” code you never asked it to touch. On a two-file change you catch that instantly. Across twenty files, drift hides in the noise.

Get a plan before any edit

The single most valuable habit for large changes: make the agent write a plan first, and approve it before it edits a single line.

Most agent tools support this directly. Claude Code has a plan mode; Cursor lets you ask for a plan in chat before switching to edits. If yours does not, do it in the prompt: “Do not edit anything yet. Give me a numbered plan of the files you will change and what each change is. Wait for my approval.”

A plan is cheap to produce and cheap to fix. A wrong plan costs one message to correct. A wrong refactor costs an hour of untangling a broken branch. You are moving the review from the expensive end (the diff) to the cheap end (the plan), which connects directly to how you prompt coding agents in the first place.

Read the plan for the things the model gets wrong before it gets them wrong: Is it touching files it should not? Did it miss a call site you know exists? Is it about to reinvent a helper you already have? Correcting those in the plan is one sentence; correcting them in code is a cleanup.

flowchart LR
    REQ([Refactor request]) --> PLAN[Agent writes<br/>numbered plan]
    PLAN --> REVIEW{Plan looks<br/>right?}
    REVIEW -->|no| FIX[Correct the plan]
    FIX --> PLAN
    REVIEW -->|yes| STEP[Do one step]
    STEP --> TEST[Run tests]
    TEST --> NEXT{More steps?}
    NEXT -->|yes| STEP
    NEXT -->|no| DONE([Review full diff])
Why review the plan instead of just reviewing the final diff?

Because a plan is short and a diff is long.

A twenty-file diff is genuinely hard to review. By the time you see it, the mistakes are already spread across the codebase, and untangling a half-right refactor is often slower than redoing it. A plan is five to ten lines. You can hold the whole thing in your head, spot the wrong assumption, and fix it with one reply.

Reviewing the plan does not replace reviewing the diff. It catches the structural mistakes early, so the diff you eventually read is smaller and closer to right.

Break it into steps, verify between each

Once the plan is approved, do not let the agent run the whole thing end to end. Break the refactor into steps and verify after each one, not at the very end.

A good step is independently checkable. For a library swap, the steps might be:

  1. Add the new library and a thin adapter, leave old code in place.
  2. Migrate module A to the adapter. Run tests.
  3. Migrate module B. Run tests.
  4. Delete the old library and the adapter. Run tests.

After each step, run the tests. This is the part people skip, and the part that saves you. If step 2 breaks three tests, you know the break is in module A, with a small recent diff to inspect. Let the agent do all four steps and test once at the end, and a failure tells you almost nothing: the bug could be anywhere across the whole change.

You can automate the checkpoint. Tell the agent to run the suite itself and stop if it goes red:

# Have the agent run this after each step and halt on failure.
npm test -- --run
if [ $? -ne 0 ]; then
  echo "Tests failed. Stop. Do not continue to the next step."
  exit 1
fi

Verifying between steps also keeps the agent honest. A red test is concrete feedback the model can act on, far better than you noticing at the end that something is subtly off, and it closes the loop while the context is still fresh, which is when a fix is cheap.

Branch discipline and small commits

Everything here rests on being able to undo. Before a large change, branch. This should be reflex, but it matters more with an agent because the volume of change is higher and the author is not you.

Commit after each verified step. Not one giant commit at the end, one commit per step that passed its tests. This buys you three things:

  • A safe rollback point. If step 4 goes wrong, git reset to the last good commit and you are back to a working tree, not stuck bisecting a thousand-line blob.
  • A readable history. “Add adapter”, “migrate module A”, “migrate module B” tells the story. One “refactor everything” commit tells you nothing in six months.
  • A smaller thing to review. Each commit is a self-contained diff you already checked. The final code review is then a walk through commits you understand, not one wall of changes.

Let the agent do the editing, but keep the commits yours. Review each step, then commit it deliberately. A tool that auto-commits its own work removes the exact checkpoint that lets you catch drift.

Contain the blast radius

The rest is about keeping the change small enough to stay in control of, even when the task itself is large.

Scope the files explicitly. Tell the agent which files or directories are in play, and which are off limits. “Only touch files under src/billing/. Do not change the API layer.” Left unscoped, an agent will happily “clean up” adjacent code, and now your billing refactor also rewrote the logging module for no reason.

Keep the diff readable. If a step is producing a diff you cannot follow, the step is too big. Stop and split it. A refactor you cannot review is a refactor you are merging on faith, which defeats the point of doing it carefully.

Stop the moment it drifts. When the agent starts editing files outside the plan, inventing abstractions you did not ask for, or “fixing” unrelated code, interrupt it. Do not let it keep going and sort it out later; later is a bigger mess. Correct course while the drift is one file, not ten. Same instinct as reviewing the plan: catch the wrong turn early, when it is cheap.

The through-line: you are trading one large unreviewable change for a sequence of small reviewable ones. That is the whole game with big refactors and agents.

Common beginner mistakes

  • One giant prompt, one giant diff. Firing “migrate us off the old ORM” and letting the agent run to completion, then facing an unreadable diff.
  • Tests only at the end. Running the suite once after everything, so a failure gives you no signal about which step broke it.
  • No branch, no commits. Doing a large change on your working branch with nothing to roll back to when it goes sideways.
  • Unscoped edits. Not telling the agent which files are off limits, so it “improves” code unrelated to the task.
  • Ignoring drift. Watching the agent wander outside the plan and hoping to clean it up later instead of stopping it now.
  • Approving a plan you did not read. Rubber-stamping the plan defeats the point; the plan is where the cheap corrections live.

Questions you will face in production

“The refactor is too big to plan in one go. What do I do?” Split it into independent refactors and do them one merged PR at a time. If you cannot describe the change as a short numbered plan, it is not one change, it is several. Land the adapter first, merge it, then migrate modules in later PRs. Small landed changes beat one heroic branch that never merges.

“The agent’s plan looks fine but the code keeps breaking mid-refactor. Why?” Usually the plan missed a dependency the model could not see: a call site in a file it never loaded, a config that references the old name. Feed it the failing test output and the specific file, and have it fix that one thing before moving on. Do not let it guess across the whole change at once.

“Should I let the agent commit and push on its own?” Let it edit and run tests. Keep committing and pushing as manual, deliberate steps you take after reviewing each one. The commit boundary is your rollback point and your review unit; handing it to the agent removes the checkpoint that makes large changes safe.

What to remember

  • Large changes are where agents shine and where blast radius bites; run them like real engineering tasks, not big prompts.
  • Make the agent write a plan and approve it before any edit. Fixing a plan is one sentence; fixing a bad refactor is an hour.
  • Break the change into independently checkable steps and run tests between each, not only at the end.
  • Branch first, commit after each verified step, so rollback is git reset, not git bisect.
  • Scope the files, keep each diff readable, and stop the agent the moment it drifts outside the plan.

What to study next

Large refactors often need the agent to reach beyond your files: run a migration against a real database, query your issue tracker, hit an internal API. That is what MCP and custom tools in your editor unlocks, giving the agent access to the systems a refactor actually touches, not just the code.

Further reading

Where this article comes from. This is a synthesis of common practice in AI engineering as of 2026, not a citation of any single paper. The sources above are where the mechanics come from. If you find an error or have a better source for a claim, the article gets fixed within a day, send me a note.


Auto-marks when you reach the end. Click to toggle.

If this helped, buy me a coffee

Everything is free. Tips keep me writing the rest.

Buy me a coffee →