05 - Planning and Large Refactors
📋 Jump to Takeaways🎁 You ask Claude to rename an API used in 40 files. Ten minutes later half the files are done, the build is red, and it's "fixing" a file it already fixed. What went wrong before the first edit?
Big changes fail when Claude starts editing before it understands the shape of the work. The fix is boring and it works: plan first, scope the blast radius, move in small committed steps, and keep the build green the whole way.
Plan Before You Edit
For anything beyond a one-file change, get a plan before any code. Use plan mode, or just ask for the approach first. You're checking that Claude understood the task the way you meant it, while a mistake still costs nothing.
Before you change anything: outline the plan for renaming
`fetchUser()` to `getUser()` across the codebase. List the files
you'll touch, the order, and how you'll verify each step.
Don't edit yet. Wait for my go-ahead.Read the plan like a code review. If it misses a caller, names the wrong file, or plans to "update tests later," fix it now. A wrong plan approved is 40 wrong edits.
Scoping a Migration
Never let Claude guess how big a change is. Discover the work list first, then transform against it. The cheapest way to find every call site is to look.
# Find everything that touches the old API before renaming
grep -rn "fetchUser(" src/ --include="*.ts" | wc -l
grep -rln "fetchUser(" src/ --include="*.ts"Now you both know it's 23 files, not "a few." Feed that list into the plan. A scoped migration has a finish line. An unscoped one thrashes until it runs out of context.
Incremental Changes with Git
Small verifiable steps beat one giant diff every time. Commit a clean checkpoint before you start, so you can always get back to green with one command.
git add -A && git commit -m "checkpoint: before getUser rename"Then have Claude do the rename in batches, not all at once. After each batch, you review the diff and commit. If batch three goes sideways, you git reset to batch two, not back to the Stone Age.
git diff --stat # what changed in this batch?
git add -A && git commit -m "rename fetchUser -> getUser (src/api)"Keeping the Build Green
Run tests and typecheck between steps, not at the end. A refactor that's been red for 30 files is a debugging session pretending to be a rename.
npm run typecheck && npm test -- --runTell Claude the build must pass before it moves to the next batch. When the checker is fast, this is your best guardrail, it catches a broken rename at file 3 instead of file 30. Wire it into a hook if you do this a lot (Lesson 07).
When the Plan Drifts
Sometimes the plan meets reality and reality wins. A "simple rename" turns out to need a signature change, or two call sites can't use the new API. When that happens, stop. Don't let Claude improvise across files.
Stop. The rename hit a case the plan didn't cover: three callers
pass a second argument the new API doesn't accept. Don't patch
around it. Re-plan how we handle those three, then continue.Thrashing looks like edits to files that were already done, growing diffs, and the same error three times. That's your signal to re-plan, not to say "keep going." A fresh plan on new information is cheap. A runaway agent burning context is not.
Key Takeaways
- Get a plan before any multi-file change and read it like a code review, a wrong plan approved becomes many wrong edits
- Scope migrations by finding every call site first (
grep -rln), so the change has a finish line instead of a guess - Commit a checkpoint before starting and after each batch, so you can
git resetto the last good state instead of unwinding everything - Run typecheck and tests between batches, not at the end, catching a break at file 3 beats debugging at file 30
- When the plan drifts, stop and re-plan on the new information, don't tell a thrashing agent to "keep going"
🎁 That rename was one stream of work. But what if you could split three independent jobs across three helpers running at once, without them tripping over each other?