How to use Claude Code for large-scale legacy codebase refactoring
The biggest mistake is asking it to "refactor the auth module" in one go. That’s a recipe for hallucinations and broken imports. Instead, I use a "Discovery-first" workflow. I start by letting Claude Code map the dependency graph using grep and file reads before touching a single line of code.
I usually kick things off with a discovery prompt to establish a source of truth:
# First, I force it to index the relevant area
/ask "Search for all occurrences of the LegacyUserSession class and list every file that imports it. Create a temporary file called refactor_map.md detailing the call hierarchy."Once refactor_map.md exists, I feed that file back into the context for the actual migration. This prevents the tool from wandering off into irrelevant directories and keeps the token usage focused.
For the actual refactoring, I've had the best luck with "incremental extraction." Instead of changing a 2,000-line file in place, I tell Claude Code to extract logic into new, typed services and then swap the implementations. Here is the prompt pattern I use for the migration phase:
Using the map in refactor_map.md, extract the validation logic from userController.ts into a new file src/services/userValidation.ts. Ensure all types are explicitly defined. Once the new service is created, update userController.ts to use this service. Do not change any other logic in the controller.The "gotcha" with Claude Code is its tendency to over-optimize. It might see a piece of legacy code and decide to "improve" the logic while refactoring, which introduces bugs that are impossible to track. I now explicitly add Strictly preserve the existing business logic; do not optimize for performance or readability unless requested to my instructions.
To ensure I didn't break the world, I integrate the CLI with my test runner. I don't trust the AI's "I've verified the changes" message. I use a loop:
1. Run the refactor command.
2. Immediately execute: npm test src/services/userValidation.spec.ts
3. If it fails, I pipe the error directly back: /ask "The tests failed with the following error: [paste error]. Fix the implementation in userValidation.ts."
In terms of productivity gains, the speed of switching between grep, ls, and cat within the Claude Code terminal is where the real win is. I no longer spend 10 minutes jumping between tabs in VS Code just to find where a variable is defined before I can write a prompt.
Key config and workflow tips:
Keep .claudignore tight. If you have massive dist or node_modules folders that aren't properly ignored, the agent spends too many tokens scanning junk.
Use the /compact command frequently. When the conversation history gets long during a complex refactor, the agent can get confused. Compacting the history keeps the focus on the current file state.
Commit every single successful extraction. Do not let Claude Code refactor five files before you commit. If it hallucinates a breaking change in file #4, reverting is a nightmare.
This approach turned a three-day manual refactor of our session management into a four-hour supervised process. The tool isn't replacing the architect, but it's effectively replacing the "find-and-replace" drudgery.
All Replies (0)
No replies yet — be the first!
