DEV Community

Carlos Oliva Pascual
Carlos Oliva Pascual

Posted on • Originally published at stacknotice.com

Refactoring with Claude Code: The Workflow That Actually Works (2026)

Refactoring is where most developers discover Claude Code's real limitations — and its real strengths. Sent into a large file without context, Claude hallucinates method names and misses side effects. Given the right structure, it can refactor a 600-line god component in under ten minutes while keeping every test green.

The difference is entirely in the workflow.

Why Refactoring Is Hard for AI

A fresh context window knows nothing. It doesn't know that UserService calls AuthService under the hood. It doesn't know the database expects snake_case. It doesn't know you migrated from Redux to Zustand six months ago.

This is exactly why refactoring fails out of the box: you hand Claude a file, ask it to clean it up, and it invents new abstractions that break three other files you didn't show it.

The fix is context — but not context in the chat window. Context in your codebase.

Rule 0: Always Read Before Changing

Before asking Claude to refactor anything, make sure it has read:

  1. The file being changed
  2. Every file that imports from it
  3. Every file it imports from
  4. Relevant types or interfaces
# Instead of: "refactor UserService"
# Do this first:

claude "Read src/services/UserService.ts, src/types/user.ts, and every file
that imports UserService. Once you understand the full picture, summarize
what UserService does and what would break if we changed its interface."
Enter fullscreen mode Exit fullscreen mode

The summary step is not optional. It forces Claude to actually read instead of pattern-matching on the filename.

CLAUDE.md as Your Refactoring Brief

If you're doing a large refactoring effort that spans multiple sessions, your CLAUDE.md is the place to encode the rules.

# CLAUDE.md — Refactoring Context

## Current goal
Splitting the monolithic UserController into:
- UserAuthController (login, register, token refresh)
- UserProfileController (read/update profile)
- UserAdminController (admin-only operations)

## Rules for this refactor
- Keep all existing HTTP endpoints — external clients depend on them
- New services are injectable (constructor injection, not singletons)
- All database calls go through the repository layer, not direct Prisma calls
- Error responses follow the existing ErrorResponse type in src/types/errors.ts

## Already done
- UserAuthController: done, tests passing
- UserProfileController: done, tests passing
- UserAdminController: in progress

## Do not touch
- src/middleware/auth.ts — frozen until v2
- src/types/ApiResponse.ts — external contract
Enter fullscreen mode Exit fullscreen mode

This pays off immediately. Every new session starts knowing where you are, what the rules are, and what not to break. You skip five minutes of re-explaining the codebase at the start of each task.

The Four-Step Refactoring Workflow

Step 1: Understand

Never start with a change. Start with a question.

"Read src/components/UserDashboard.tsx and its imports. Tell me:
- What does it currently do?
- What are its dependencies?
- What state does it manage?
- What would be risky to move?"
Enter fullscreen mode Exit fullscreen mode

Step 2: Plan

Ask Claude to propose the refactoring before writing a single line.

"Based on what you've read, propose how you'd split UserDashboard into
smaller components. List each new component, what it would contain,
and what props it would need. Don't write any code yet."
Enter fullscreen mode Exit fullscreen mode

Review the plan. This is where you catch bad ideas before they're in the code.

Step 3: Execute in Chunks

Never ask Claude to refactor an entire large file in one shot.

"Implement step 1 from the plan: extract UserDashboardHeader into
its own file at src/components/UserDashboardHeader.tsx. Keep the
logic identical — no behavior changes, just extraction. Update
the import in UserDashboard.tsx."
Enter fullscreen mode Exit fullscreen mode

One thing at a time. One file changed, one file updated. After each chunk, run your tests.

Step 4: Verify

"The tests are passing. Now review the diff of what changed.
Does UserDashboard.tsx still have any logic that belongs in
UserDashboardHeader? Is there anything we missed?"
Enter fullscreen mode Exit fullscreen mode

Handling Large Files

Files over 400–500 lines hit a practical problem: Claude reads them, but the beginning is compressed by the time it's writing changes at line 450.

Strategy A: Read sections, not the full file

"Read lines 1-150 of src/services/OrderService.ts.
Tell me what those lines do and what functions they define."
Enter fullscreen mode Exit fullscreen mode

Work section by section. Use /compact between major chunks to keep the context clean.

Strategy B: Extract the interface first

"Read src/services/OrderService.ts and extract only the public
method signatures (not the implementations) into a summary.
We'll use this as our working reference while we refactor."
Enter fullscreen mode Exit fullscreen mode

Renaming at Scale

"I need to rename `userId` to `user_id` across the repository
to match our database naming convention.

1. First, use grep to find every file that uses `userId`
2. List them — don't change anything yet
3. I'll tell you which files to update"
Enter fullscreen mode Exit fullscreen mode

The list-first step is important. Blindly changing every occurrence will catch false positives — comments, test fixtures, generated code you shouldn't touch.

Extracting Services from God Components

The most common real-world refactoring: a React component that has grown to 500+ lines.

The extraction order matters:

  1. Extract types first — Zero risk, zero behavior change.
  2. Extract pure functions — Any function that doesn't touch state goes to utils.ts.
  3. Extract hooks — Any useState/useEffect cluster that belongs together becomes a custom hook.
  4. Extract sub-components — Once hooks are clean, JSX sections become obvious component boundaries.

Each step is a separate Claude session with a separate commit. Never combine steps.

Keeping Tests Green

Run tests after every step. Not after every session — after every step.

If your tests don't cover the code you're refactoring, write characterization tests before you start:

"Before we refactor UserService, write tests that cover its
current behavior. I don't care if the tests are ugly — I just
need a safety net that will tell me if the refactor changes
any observable behavior."
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

Pitfall 1: Showing only the file you're refactoring

Claude doesn't know what imports it. Refactors perfectly in isolation, three callers break.

Fix: Always show callers when refactoring public interfaces.

Pitfall 2: Long sessions for large refactors

Context degrades after 90 minutes. Claude starts forgetting CLAUDE.md rules and re-introducing patterns you already corrected.

Fix: Use /compact aggressively. Break multi-day refactors into sessions.

Pitfall 3: Not committing between steps

Every successful step deserves a commit. If step 4 breaks everything, you want git revert to step 3, not start from scratch.

A Real Example: Splitting a God Service

Session 1:
"Read OrderService.ts and all files that import from it. Summarize
what the service does and identify natural domain boundaries."

→ Claude identifies: payment logic, inventory logic, notification logic

Session 2 (after /clear):
"Read OrderService.ts. Extract all payment-related methods into
PaymentService.ts. Keep OrderService calling PaymentService —
no interface changes for callers."

→ Commit: "refactor: extract PaymentService from OrderService"

Session 3 (after /clear):
"Read OrderService.ts. Extract inventory methods. Same pattern."

→ Commit: "refactor: extract InventoryService from OrderService"
Enter fullscreen mode Exit fullscreen mode

Each session is focused, clean, and committed.

The Rule of One

Refactoring with Claude Code comes down to one principle: one thing at a time.

One file read. One change proposed. One step executed. One test run. One commit.

The urge to "just do the whole thing" leads to sessions where you've lost track of what changed, tests fail in three places, and you're debugging Claude's refactoring instead of shipping features.


Full guide with internal links at stacknotice.com/blog/claude-code-refactoring-guide-2026

Top comments (0)