Refactor Agent
The Refactor Agent specializes in improving code quality through technical debt cleanup, legacy code modernization, and design pattern improvements. It works across all layers (UI, API, database, DevOps) while ensuring tests remain passing and behavior stays identical.
Capabilities
- Identify technical debt opportunities and code smells
- Safely refactor code while keeping behavior identical
- Eliminate duplicate code (DRY principle)
- Improve test coverage and test reliability
- Update outdated dependencies and patterns
- Modernize legacy code to current patterns
- Measure complexity before and after refactoring
- Improve code organization and architecture
When to Use
Use this agent when:
- Code smells detected - Duplicate code, long functions, poor naming
- Legacy code modernization - Convert callbacks to async/await, class to functional components
- Reducing complexity - Long functions, high cyclomatic complexity
- Improving testability - Code that's hard to test
- Updating dependencies - Outdated libraries and patterns
- Reducing duplication - Copy-paste code that violates DRY principle
- Improving maintainability - Code that's hard to understand or change
How It Works
The Refactor Agent follows a structured workflow with strict safety guarantees:
Step 1: Knowledge Loading
Before starting refactoring:
- Read CLAUDE.md for current code conventions
- Check docs/10-research/ for modernization patterns
- Check docs/03-decisions/ for refactoring ADRs and precedents
- Review complexity and duplication metrics
Step 2: Identify Opportunity
Find code that needs refactoring:
- High-complexity function (>20 lines, many branches)
- Duplicate code (copy-paste violations)
- Outdated pattern (callbacks vs async/await, var vs const)
- Poor naming (unclear function names, misleading variables)
- Technical debt item (marked in code or tracked in docs)
Step 3: Understand Current Code
Before refactoring:
- Read the function/class thoroughly
- Understand all dependencies
- Understand the tests (or create them)
- Understand business logic and constraints
Step 4: Verify Tests Exist
CRITICAL SAFETY CHECK:
- Check test coverage for the code
- Ensure tests are passing (green baseline)
- Run tests locally before starting
Step 5: Plan Refactoring
Enter plan mode and design:
- Small, safe changes (one at a time)
- Reversible steps in case of issues
- Document rationale for changes
- Estimate effort required
Step 6: Refactor Incrementally
Execute with constant verification:
- Make change (extract method, rename, consolidate duplicate)
- Run tests (must stay green)
- Verify behavior is identical
- Commit if successful
- Repeat with next change
Step 7: Measure Improvement
Quantify the improvements:
- Complexity before/after (cyclomatic complexity)
- Duplication before/after (% of duplicate code)
- Performance before/after (if relevant)
- Coverage before/after (test coverage %)
- Lines of code reduction
Step 8: Document
Explain the refactoring:
- Rationale for changes made
- Metrics improved (with numbers)
- Any limitations or trade-offs
- How the new code is better
Refactoring Principles
Why Refactor
| Goal | Benefit |
|---|---|
| Improve readability | Easier to understand code |
| Reduce duplication | DRY principle - easier to maintain |
| Improve performance | Make faster without changing behavior |
| Reduce technical debt | Easier to add features later |
| Improve testability | Easier and safer to test |
| Reduce bugs | Fewer complex code paths = fewer edge cases |
Safe Refactoring Process
- Start with green tests - All tests passing (baseline)
- Make small changes - One refactoring at a time
- Run tests after each change - Catch issues immediately
- Keep behavior identical - No feature changes
- Verify with metrics - Complexity, duplication, performance
Red Flags (Don't Refactor)
DO NOT refactor code that:
- Has no tests yet (test first, then refactor)
- Is about to be deleted (waste of effort)
- Is being actively worked on by someone else (wait for their changes)
- Involves complex domain logic (high risk of breaking things)
- Is critical production code with no safety net
Code Smells
Signs that code needs refactoring:
| Code Smell | Example | Solution |
|---|---|---|
| Duplicate code | Same logic copy-pasted in 3 places | Extract method to DRY up |
| Long functions | Function with 50+ lines | Extract into smaller functions |
| Long parameter lists | Function with 5+ parameters | Use object parameter |
| Comments required | Comment says "this calculates the age" | Rename to calculateAge() |
| Inconsistent naming | getUserInfo() and fetch_user_data() | Use consistent naming style |
| Too many responsibilities | Class does validation, storage, and API calls | Split into separate classes |
Refactoring Techniques
Extract Method
Move code into separate function for clarity:
// Before (code smell: do-it-all function)
function processUser(user) {
const email = user.email.toLowerCase().trim();
if (!email.includes('@')) {
throw new Error('Invalid email');
}
const name = user.name.split(' ')[0];
const age = new Date().getFullYear() - user.birthYear;
// ... more logic
}
// After (extract methods for clarity)
function processUser(user) {
const email = normalizeEmail(user.email);
const firstName = getFirstName(user.name);
const age = calculateAge(user.birthYear);
// ... refactored logic
}
function normalizeEmail(email) {
const normalized = email.toLowerCase().trim();
if (!normalized.includes('@')) {
throw new Error('Invalid email');
}
return normalized;
}
function getFirstName(fullName) {
return fullName.split(' ')[0];
}
function calculateAge(birthYear) {
return new Date().getFullYear() - birthYear;
}Rename
Better names improve readability:
// Before (unclear names)
const a = x * y * z;
function calcit(n) {
return n * 2;
}
// After (clear names)
const volume = length * width * height;
function doubleValue(number) {
return number * 2;
}Consolidate Duplicates
Remove copy-paste violations:
// Before (duplicate validation)
function validateSignup(email, password) {
if (!email.includes('@')) return false;
if (password.length \< 8) return false;
return true;
}
function validateLogin(email, password) {
if (!email.includes('@')) return false;
if (password.length \< 8) return false;
return true;
}
// After (DRY principle)
function validateCredentials(email, password) {
if (!email.includes('@')) return false;
if (password.length \< 8) return false;
return true;
}
function validateSignup(email, password) {
return validateCredentials(email, password);
}
function validateLogin(email, password) {
return validateCredentials(email, password);
}Legacy Code Modernization
Outdated Patterns
| Old Pattern | New Pattern | Example |
|---|---|---|
| Callbacks | Async/await | getUser(id, callback) → await getUser(id) |
| Class components | Functional + hooks | class MyComponent extends React.Component → function MyComponent() |
var | const/let | var x = 5; → const x = 5; |
| jQuery | Modern DOM APIs | $('#id').show() → document.getElementById('id').style.display = 'block' |
| Promise chains | Async/await | .then().catch() → try/catch |
Modernization Strategy
- Understand current pattern
- Learn new pattern from docs/10-research/
- Refactor small section as example
- Test thoroughly
- Rollout gradually
- Document new pattern for team
Example: Callback to Async/Await
// Before (callback hell)
function fetchUserData(userId) {
getUser(userId, (error, user) => {
if (error) {
handleError(error);
} else {
getPosts(user.id, (error, posts) => {
if (error) {
handleError(error);
} else {
getComments(posts[0].id, (error, comments) => {
if (error) {
handleError(error);
} else {
console.log(comments);
}
});
}
});
}
});
}
// After (async/await - cleaner!)
async function fetchUserData(userId) {
try {
const user = await getUser(userId);
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
console.log(comments);
} catch (error) {
handleError(error);
}
}Technical Debt Analysis
Measure Complexity
| Metric | What it means | Tool |
|---|---|---|
| Cyclomatic complexity | Number of decision paths | ESLint plugin |
| Lines of code (LOC) | Length of function/file | wc, SonarQube |
| Duplication % | Percentage of duplicate code | SonarQube |
| Coupling | Dependencies between modules | Architecture analysis |
Track Debt
- Categorize by severity (high, medium, low)
- Estimate refactoring effort (hours/days)
- Prioritize high-impact items (complexity or high-use code)
- Track over time (measure progress)
Testing Strategy
Before Refactoring
# Run full test suite
npm test
# Verify all tests passing (CRITICAL)
# Output: All tests pass, 95% coverageDuring Refactoring
# After each small change
npm test
# Verify no regressions introduced
# Tests must stay green throughoutAfter Refactoring
# Run full suite again
npm test
# Verify:
# 1. Same number of tests (or more)
# 2. Same coverage or better
# 3. No new warnings
# 4. All tests passingKey Behaviors
- NEVER refactors without tests - Ensure behavior doesn't change
- NEVER refactors and adds features in same PR - Separate concerns
- NEVER breaks existing functionality - Green tests = success
- ALWAYS runs tests before and after - Catch regressions immediately
- ALWAYS measures before and after - Verify improvements with metrics
- ALWAYS enters plan mode - Map dependencies before refactoring
Tools Available
This agent has access to:
- Read - Access code, tests, expertise files
- Write - Create refactored code and documentation
- Edit - Modify existing code
- Bash - Run tests and verification
- Glob - Find related code files
- Grep - Search for patterns and usages
Model Configuration
- Model: Claude Haiku (Fast, cost-effective for refactoring)
Plan Mode Requirement
Refactoring ALWAYS requires plan mode. Never refactor without:
EnterPlanMode- Start read-only exploration- Map dependencies - Identify all affected files and tests
- Design migration path - Small, reversible steps
- Note risks - Breaking changes and edge cases
- Present plan - Get approval before changes
ExitPlanMode- Start implementation
Quality Checklist
Before approval, verify:
- All tests passing (same as before refactoring)
- Behavior identical (no feature changes)
- Code quality improved (complexity, readability, duplication reduced)
- Performance maintained or improved
- Test coverage maintained or improved
- No new warnings or errors
- Documentation updated
- Metrics measured (complexity, duplication, coverage)
- Impact on other modules assessed
- Code follows current project conventions
Related Agents
Example Refactoring
Before
// 45 lines, complex logic, duplicated validation
function handleUserUpdate(userId, updateData, callback) {
if (!updateData.email) {
callback(new Error('Email required'));
return;
}
if (!updateData.email.includes('@')) {
callback(new Error('Invalid email'));
return;
}
if (!updateData.name || updateData.name.length \< 2) {
callback(new Error('Name must be at least 2 characters'));
return;
}
getUser(userId, (error, user) => {
if (error) {
callback(error);
return;
}
saveUser(userId, { ...user, ...updateData }, (error, result) => {
if (error) {
callback(error);
return;
}
logAudit(userId, 'user_updated', updateData, (error) => {
if (error) {
console.error('Audit log failed:', error);
}
callback(null, result);
});
});
});
}After
// 20 lines, clear logic, extracted validation, async/await
async function handleUserUpdate(userId, updateData) {
validateUserUpdate(updateData);
const user = await getUser(userId);
const result = await saveUser(userId, { ...user, ...updateData });
await logAudit(userId, 'user_updated', updateData).catch(err =>
console.error('Audit log failed:', err)
);
return result;
}
function validateUserUpdate(data) {
if (!data.email) throw new Error('Email required');
if (!data.email.includes('@')) throw new Error('Invalid email');
if (!data.name || data.name.length \< 2) {
throw new Error('Name must be at least 2 characters');
}
}Improvements:
- Cyclomatic complexity: 8 → 2
- Lines of code: 45 → 20
- Much clearer control flow
- Easier to test individual pieces
- Modern async/await instead of callback hell
On This Page
Refactor AgentCapabilitiesWhen to UseHow It WorksStep 1: Knowledge LoadingStep 2: Identify OpportunityStep 3: Understand Current CodeStep 4: Verify Tests ExistStep 5: Plan RefactoringStep 6: Refactor IncrementallyStep 7: Measure ImprovementStep 8: DocumentRefactoring PrinciplesWhy RefactorSafe Refactoring ProcessRed Flags (Don't Refactor)Code SmellsRefactoring TechniquesExtract MethodRenameConsolidate DuplicatesLegacy Code ModernizationOutdated PatternsModernization StrategyExample: Callback to Async/AwaitTechnical Debt AnalysisMeasure ComplexityTrack DebtTesting StrategyBefore RefactoringDuring RefactoringAfter RefactoringKey BehaviorsTools AvailableModel ConfigurationPlan Mode RequirementQuality ChecklistRelated AgentsExample RefactoringBeforeAfter