CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-04-18Intermediate

Three Months of Cutting Technical Debt in Half with Claude Code — A Practical Record

A three-month hands-on record of tackling accumulated technical debt using Claude Code. Covers visualization, prioritization, and automated refactoring — with real numbers showing what actually changed.

technical debtrefactoring4Claude Code196code qualityindie dev10

When you've been running a personal app for a few years, there comes a day when you open a file and realize: I can't read my own code anymore. Comment-outs layered on top of each other, functions called from somewhere unknown, logic duplicated in five places with subtle variations. If that sounds familiar, this post is for you.

That was exactly my situation. Running two apps simultaneously while continuously adding features had left my codebase in what I call the "works but untouchable" state — functional, but too fragile to refactor safely.

So at the start of 2026, I committed three months to seriously tackling technical debt using Claude Code. This is the record of what I did, in what order, what worked, and where Claude hit its limits.

Step One: Build a Debt Map — Put Numbers on the Problem

The most common reason refactoring stalls before it starts is the question "where do I even begin?" Without a concrete map, you work on whatever annoys you most rather than what matters most.

The first thing I did was ask Claude Code to generate a technical debt inventory. Running this from the project root:

claude "Analyze this entire repository and produce a Markdown report covering:
1. All TODO/HACK/FIXME/XXX comments with file locations
2. Duplicate code patterns (50+ lines of similar logic)
3. High-complexity functions (5+ levels of nesting or conditionals)
4. Circular module dependencies
5. Files with zero test coverage (if test config exists)
 
For each item, add a 1-5 star rating on two axes: 'blast radius if it breaks' and 'difficulty to fix'."

Claude spent a few minutes scanning the whole repo and produced a surprisingly specific report. My numbers:

  • TODO/HACK comments: 47 instances (23 of them over two years old)
  • Obvious duplicate code: 8 patterns (~1,200 lines)
  • Circular dependencies: 3 module pairs
  • Files with zero test coverage: 67% of the codebase

Something shifts when you move from "my code is kind of a mess" to "I have 3 circular dependencies and 8 duplicate patterns." The problem becomes bounded, approachable. That map made it possible to prioritize without getting overwhelmed.

Prioritization: The Urgency × Impact Matrix

With a map in hand, the next challenge is deciding what to tackle first. My mistake in previous attempts was starting with whatever looked the ugliest. Aesthetically offensive code isn't always the most dangerous code.

The key to getting useful prioritization from Claude is including your real-world constraints:

claude "Using the debt report we just created, help me prioritize the work.
Constraints:
- I have 1-2 days per week available for refactoring
- I cannot break live functionality (this is a production app)
- I'm planning to add Feature X in three months, and its surrounding modules need to be clean first
 
Given these constraints, please categorize items into: 'this week', 'this month', and 'within three months'."

The output gave me something concrete: tackle the 8 duplicate code patterns first (this week and next week), skip the circular dependency resolution until month two because the blast radius is too large to handle quickly.

Crucially, telling Claude about the upcoming Feature X caused it to flag which debt items lived in that feature's neighborhood — and those jumped to the front of the queue.

Removing Duplicate Code: Safe Refactoring with Subagents

The highest-priority items were duplicate error handling patterns scattered across 8 API files. Each file had its own slightly different version of the same try/catch logic.

This is where Claude Code's subagent capability with --headless and git worktrees becomes genuinely powerful. You can experiment without touching your main branch at all:

# Create an isolated working environment
git worktree add /tmp/refactor-api-errors -b refactor/api-error-handling
 
claude --headless "
Working directory: /tmp/refactor-api-errors
Task: Consolidate the duplicated error handling logic found in these 8 files:
src/api/users.ts, src/api/products.ts, src/api/orders.ts, ... (etc.)
 
Steps:
1. Analyze the error handling patterns across all 8 files
2. Identify what can be shared vs. what must stay per-file
3. Create src/utils/apiErrorHandler.ts as a shared utility
4. Refactor all 8 files to use the new module
5. Verify no TypeScript errors remain
6. Output a final diff of all changes
"

The result: 8 patterns collapsed into one shared utility plus thin per-file wrappers. ~340 lines became ~95 lines.

Important caveat: I never merged the output directly. I always reviewed the diff, checked that type definitions were accurate and error messages hadn't changed, then decided whether to merge. The worktree approach means your main branch is never at risk while you're exploring.

Resolving Circular Dependencies: Understand Before You Fix

Circular dependencies took nearly a month — the longest stretch. That's because they're not really a code problem; they're a design problem. Module A importing module B which imports module A means the original separation of concerns was unclear.

Asking Claude to "just fix it" here would have been a mistake. Resolving circular dependencies requires redesigning module responsibilities — a judgment call that belongs to the developer, not the AI.

Instead, I asked Claude to analyze why the dependency existed:

claude "There's a circular dependency between src/store/userStore.ts and src/components/UserProfile.tsx.
Analyze why this pattern emerged, explain the design flaw, and suggest three approaches to resolve it.
Include trade-offs for each approach."

The three options it produced (event bus, context separation, dependency injection) gave me the vocabulary to make an informed decision. I chose, then asked Claude to implement. That "analyze → decide → implement" flow is the right one for structural problems.

Adding Tests to Untested Code: The Incremental Approach

With 67% of files having zero test coverage, trying to test everything at once is a trap. I used a narrowly scoped approach:

claude "Write tests for src/utils/priceCalculator.ts.
Don't try to cover everything — instead, identify the 3 functions in this file where a bug would most impact users, and write focused tests for those 3 functions using vitest."

"The 3 most impactful functions" rather than "100% coverage" was the prompt that made this sustainable. Over three months, coverage went from 0% to 38%. Not perfect — but the core user-facing paths are now protected.

Three Months Later: The Numbers

At the end of month three, I ran the same analysis that generated the original debt map. Results:

MetricStartMonth 3Change
TODO/HACK comments4719−60%
Duplicate code patterns82−75%
Circular dependencies30−100%
Test coverage0%38%+38pt
Maximum function complexity187−61%

The numbers look good. But the most meaningful change wasn't quantitative — it was that adding new features stopped feeling scary. The "works but untouchable" state became "imperfect but workable."

What I Learned About Claude Code and Technical Debt

A few things that shaped my approach, worth keeping in mind:

Don't ask Claude to "just fix everything." Debt reduction requires design decisions. Claude is excellent at generating options, implementing a chosen approach, and writing tests — but which approach to take is yours to decide.

The worktree pattern is your safety net. Running subagents in isolated worktrees means zero risk to your production code while you experiment. This alone makes Claude Code worth using for refactoring work.

Run the health check weekly. Re-running the same debt analysis once a week takes minutes and tells you immediately if you're sliding backward. I've since automated this via a Claude Code hook.

Done is better than perfect. Technical debt never reaches zero. The goal is moving from "works but untouchable" to "touchable and improving." Once you reach that state, the velocity gains compound on their own.

The next step is automating ongoing quality monitoring — a hook that runs on every PR, flags any metrics that are worsening, and leaves a comment. Building that system is the logical continuation of this three-month effort.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-07-07
I Could Detect Failures — Then the Alerts Grew So Loud I Stopped Noticing
The moment I could detect silent job failures, my phone started buzzing too often to be useful. Here is how I collapsed alerts by action rather than event, added hysteresis and quiet hours, and built a three-step escalation so only the pages worth waking me survive.
Claude Code2026-06-30
Fixing Blurry Wallpapers on New iPhones with Claude Code: Safely Growing a Per-Device Resolution Map
Why wallpapers go blurry or letterboxed on brand-new iPhones, and how to collapse scattered device branches into a single source of truth you can extend in one line — walked through as a real Claude Code refactor with before/after code.
Claude Code2026-06-20
Handing Claude Design Mockups Straight to Claude Code: Folding the Design-to-Code Loop
The June 17 Claude Design update added codebase-aware generation. Here's how to make your tokens the single source of truth, hand mockups to Claude Code, and collapse the design-to-code round trip — with code you can copy.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →