FLSoft Academy

MODULE 3 · EVERYDAY WORKFLOWS / 25 MIN Free NOVEMBER 2026 EDITION · CLAUDE CODE 2.1.318

Refactoring safely at scale

Plan and carry out multi-file refactors in small, verified steps, so a big change never leaves the codebase broken.

Updated 5 November 2026 · Reviewed 5 November 2026

What you’ll be able to do

Carry out a refactor that touches many files, such as renaming a concept, extracting a module or replacing a library, in small verified steps, so the code works after every step and nothing changes behaviour by accident.

Why this matters

A refactor changes how code is organised without changing what it does. That’s exactly what makes large refactors risky: success means “nothing visible changed”, so a subtle behaviour change can slip through unnoticed. And an AI that can edit forty files in a minute can also introduce forty subtle problems in a minute.

The answer isn’t to avoid big refactors with Claude. It’s to give the work a shape that makes mistakes small, visible and easy to undo: pin the current behaviour with tests, plan the change in small steps, and verify and commit after each one.

The strategy

  1. Pin behaviour: make sure tests cover what you’re about to change, before changing it.
  2. Plan in plan mode: break the refactor into small steps, each of which leaves everything working.
  3. Save the plan as a checklist in a file.
  4. One step at a time: change, run the tests, commit.
  5. Review the whole diff at the end against the original goal.

Exercise: extract and rename

Use a project of your own, or loop-practice (which by now has several helpers: slugify, truncate, capitalize). The example refactor:

“All string helpers live in the project root. Move them into src/strings/, one file per helper, with an index.js that re-exports them. Update every import.”

Step 1: Pin behaviour

Before we refactor: check the test coverage for all string helpers. Add
characterization tests for any behaviour that isn't covered yet. Don't
change implementation code.

Characterization tests record what the code does today, including odd edge cases, rather than what it ideally should do. Their only job is to tell you if a refactor changed behaviour.

What you’ll see: Claude reviews the existing tests, adds tests for uncovered cases (empty strings, unusual characters, boundary lengths), and runs them. They should all pass, because nothing has changed yet. Commit them.

Step 2: Plan

Switch to plan mode (Shift+Tab) and ask:

Plan the move into src/strings/ as a numbered checklist of small steps. Each
step must leave all tests passing.

What you’ll see: a plan of perhaps five to eight steps, such as “create src/strings/slugify.js and re-export it from the old location”, “update imports”, “remove the old file”. Good steps are small enough that each one can be checked by running the tests. Push back if a step does too much at once.

Step 3: Save the plan. Once you’ve approved it (which ends plan mode), ask:

Write this plan to docs/plans/strings-refactor.md as a checklist.

Step 4: Carry it out step by step

Do step 1 of @docs/plans/strings-refactor.md. Run the tests, tick the box,
and stop.

What you’ll see: one small change, the full test suite passing, and the checkbox ticked in the plan file. Review the diff and commit. Repeat for the next step.

After a couple of steps, if you trust the pattern, let Claude continue on its own:

Continue with the remaining steps one at a time. Run the tests after each
step and commit with a message naming the step. Stop if anything fails.

Step 5: Review the whole thing. Look at the complete diff against the starting point: did the refactor do what the plan said, and only that?

Useful refactoring prompts

  • “Find every caller of getUser, including dynamic or string-based references, before we change its signature.” Find all the places affected before changing anything.
  • “Rename Customer to Account everywhere, including tests, docs and comments, but not database column names.” Spell out what’s in scope and what isn’t.
  • “Replace moment with date-fns. Start with a table mapping each moment call we use to its replacement.” For a library swap, agree on the mapping first, then apply it.

Safety nets

  • Checkpoints: if a step goes wrong, Esc Esc → Restore code takes you back to before that prompt (lesson 1.2). Committing after each step gives you a second, permanent safety net.
  • Worktrees: for a risky refactor, run it in an isolated copy of the repository with claude --worktree strings-refactor (Module 7). Your main working copy stays untouched until you merge.
  • Huge mechanical changes: the built-in /batch command splits a large, repetitive change into many independent pieces and works on them in parallel, each in its own isolated copy, typically opening a pull request per piece. It needs a git repository.

Red flags to watch for

  • Tests changed in the same commit as the refactor. Characterization tests should stay unchanged; if one was edited, ask why.
  • Files changed that the plan didn’t mention. Ask for an explanation, or revert them.
  • “I also improved…”: unrequested improvements make the refactor harder to review. Ask Claude to keep them for a separate change.

Common mistakes

  • Refactoring untested code. Pin behaviour with characterization tests first.
  • Giant steps. If a step can’t be verified by running the tests, it’s too big.
  • Not committing between steps. Small commits are your undo history.
  • Mixing refactoring with new features. Do them in separate changes so each can be reviewed properly.

Verify it worked

  • Characterization tests were committed before any refactoring
  • A plan file with a checklist exists, and every item is ticked
  • Git history shows small commits, one per step, each with passing tests
  • The final diff matches the plan, with no unexplained changes

Knowledge check

3 QUESTIONS · PASS MARK 80%
1. What's the safest shape for a large refactor with Claude Code?
2. Before refactoring code with no tests, what should you do first?
3. Claude says the refactor is done, but the diff touches 40 files you didn't expect. What do you do?

Tip: select the text that's wrong before clicking, and it's quoted in your report.

Report a problem

Lesson: Refactoring safely at scale

What's wrong?