Skip to content

/refactor

Improve code structure, readability, or performance without changing external behavior. Applies proven refactoring patterns to make code more maintainable, testable, and efficient.

Terminal window
/refactor [file or function] [goal: clean | extract | simplify | optimize]
  • [file or function] - Target code to refactor
  • [goal] - Optional refactoring objective:
    • clean - Remove dead code, improve naming
    • extract - Extract reusable functions/components
    • simplify - Reduce complexity and nesting
    • optimize - Improve performance

The /refactor command follows a safe, incremental approach:

  1. Read Thoroughly

    • Analyzes what the code does
    • Identifies its purpose and responsibilities
    • Maps inputs, outputs, and side effects
  2. Note Existing Tests

    • Finds test coverage for the code
    • Ensures tests exist before refactoring
    • If no tests exist, generates them first
  3. Identify Patterns

    • Recognizes code smells
    • Finds refactoring opportunities
    • Notes dependencies and coupling
  1. Identify Improvements

    • Code smells to address
    • Patterns to apply
    • Metrics to improve
  2. Ensure Test Safety

    • Verifies tests exist
    • Adds missing tests if needed
    • Ensures tests are comprehensive
  3. Plan Incremental Changes

    • Breaks into small, safe steps
    • Orders changes by dependencies
    • Plans verification after each step
  1. Make Small Changes

    • One refactoring at a time
    • Maintains behavior at each step
    • Keeps code working continuously
  2. Run Tests After Each Change

    Terminal window
    # Python
    pytest -v
    # TypeScript
    pnpm test
  3. Commit Incrementally

    • Commits after each successful refactoring
    • Makes rollback easy if needed
    • Documents what changed and why

When: Code duplication or long methods

// Before
function processUser(user: User) {
if (!user.email || !user.email.includes('@')) {
throw new Error('Invalid email');
}
if (user.name.length < 2) {
throw new Error('Name too short');
}
// ... more logic
}
// After
function processUser(user: User) {
validateUser(user);
// ... more logic
}
function validateUser(user: User) {
validateEmail(user.email);
validateName(user.name);
}
function validateEmail(email: string) {
if (!email || !email.includes('@')) {
throw new Error('Invalid email');
}
}
function validateName(name: string) {
if (name.length < 2) {
throw new Error('Name too short');
}
}

When: Complex nested if statements

// Before
if (user) {
if (user.isActive) {
if (user.subscription) {
if (user.subscription.isPaid) {
return true;
}
}
}
}
return false;
// After
return user?.isActive
&& user?.subscription?.isPaid
?? false;

When: Unexplained numeric literals

# Before
def calculate_discount(price):
if price > 100:
return price * 0.9
return price
# After
DISCOUNT_THRESHOLD = 100
DISCOUNT_RATE = 0.1
def calculate_discount(price):
if price > DISCOUNT_THRESHOLD:
return price * (1 - DISCOUNT_RATE)
return price

When: Unclear variable/function names

// Before
function calc(x: number, y: number): number {
const z = x * y * 0.2;
return z;
}
// After
function calculateTax(subtotal: number, quantity: number): number {
const TAX_RATE = 0.2;
const totalBeforeTax = subtotal * quantity;
return totalBeforeTax * TAX_RATE;
}

When: Unused functions, commented code

# Before
def old_function(): # Not called anywhere
pass
def current_function():
# result = old_way() # Old implementation
result = new_way()
return result
# After
def current_function():
result = new_way()
return result

When: Too many responsibilities in one class

// Before
class User {
name: string;
email: string;
validateEmail() { /* ... */ }
sendEmail(subject: string, body: string) { /* ... */ }
formatEmailTemplate(template: string) { /* ... */ }
}
// After
class User {
name: string;
email: string;
validateEmail() { /* ... */ }
}
class EmailService {
sendEmail(to: string, subject: string, body: string) { /* ... */ }
formatTemplate(template: string, data: any) { /* ... */ }
}
FlagDescriptionExample
--goal=[goal]Refactoring objective--goal=simplify
--safeExtra cautious, more test verification--safe
--aggressiveLarger refactoring steps--aggressive
--format=[fmt]Output format (concise/detailed)--format=concise
--test-firstGenerate tests before refactoring--test-first
GoalFocus
cleanRemove clutter, improve naming
extractPull out reusable code
simplifyReduce complexity
optimizeImprove performance
patternsApply design patterns
Terminal window
# Simplify complex function
/refactor --goal=simplify src/utils/validation.ts
# Extract with extra safety checks
/refactor --safe --goal=extract src/services/user.ts
# Performance optimization
/refactor --goal=optimize src/api/heavy-query.ts
# Clean up with tests first
/refactor --test-first --goal=clean src/legacy/

Input:

Terminal window
/refactor --goal=simplify src/services/auth.ts

Output:

## Refactoring Complete: src/services/auth.ts
### Changes Made
1. Extracted `validateCredentials()` function
2. Simplified nested conditionals using early returns
3. Replaced magic numbers with named constants
4. Improved variable names for clarity
### Before
```typescript
function login(email, pwd) {
if (email) {
if (pwd) {
if (pwd.length >= 8) {
const u = db.find(email);
if (u) {
if (bcrypt.compare(pwd, u.pwd)) {
return generateToken(u);
}
}
}
}
}
throw new Error('Invalid');
}
const MIN_PASSWORD_LENGTH = 8;
function login(email: string, password: string): string {
validateCredentials(email, password);
const user = db.findByEmail(email);
if (!user) {
throw new AuthError('Invalid credentials');
}
const passwordMatches = bcrypt.compare(password, user.hashedPassword);
if (!passwordMatches) {
throw new AuthError('Invalid credentials');
}
return generateToken(user);
}
function validateCredentials(email: string, password: string) {
if (!email) {
throw new ValidationError('Email required');
}
if (!password || password.length < MIN_PASSWORD_LENGTH) {
throw new ValidationError(`Password must be at least ${MIN_PASSWORD_LENGTH} characters`);
}
}
  • Cyclomatic complexity: 8 → 3
  • Function length: 18 lines → 12 lines
  • Nesting depth: 5 → 2
  • All 12 existing tests passing
  • No behavior changes
### Extract Reusable Code
**Input:**
```bash
/refactor --goal=extract src/components/UserList.tsx

Output:

  1. Identifies repeated patterns
  2. Extracts into reusable hooks/components
  3. Updates all usage sites
  4. Verifies tests still pass

After running /refactor, you receive:

  1. Refactored Code - Improved implementation
  2. Before/After Comparison - Clear visual diff
  3. Metrics - Complexity, length, nesting improvements
  4. Test Results - Confirmation of unchanged behavior
  5. Commit Message - Describing the refactoring
  1. Always Have Tests First - Never refactor untested code
  2. Small Steps - Make one change at a time
  3. Run Tests Frequently - After each change
  4. Commit Often - Easy rollback if something breaks
  5. Preserve Behavior - Never change what the code does, only how
  • /test - Generate tests before refactoring
  • /review - Review code quality
  • /feature - Build features with good structure
  • /fix - Fix bugs, then refactor