
Code Refactoring
Apply disciplined refactor patterns—guard clauses, extract method, kill smells—while keeping behavior unchanged under tests.
Overview
Code Refactoring is an agent skill most often used in Ship (also Build/backend) that applies smell-driven refactoring techniques without changing behavior.
Install
npx skills add https://github.com/skillcreatorai/ai-agent-skills --skill code-refactoringWhat is this skill?
- Explicit when-to-refactor vs when-NOT rules (needs tests, avoid throwaway code and deadline risk)
- Worked smell fixes: long methods, arrow nesting → early returns, and extract-function patterns
- TypeScript-oriented before/after examples for validation and discount logic
- Aligns with red-green-refactor and pre-feature cleanup (“make change easy, then make easy change”)
- MIT-sourced patterns from wshobson/agents for agent-guided incremental improvement
Adoption & trust: 593 installs on skills.sh; 1.1k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent keeps rewriting working code—or you inherit tangled methods—and you lack a shared rule set for safe, incremental cleanup.
Who is it for?
Solo devs with passing tests or tight scopes who want smell-named edits during review or the refactor step of TDD.
Skip if: Greenfield modules with zero tests, code slated for imminent replacement, or crunch weeks where behavior regression cannot be absorbed.
When should I use this skill?
Cleaning up legacy code, reducing complexity, improving maintainability, or when code review surfaces structural smells.
What do I get? / Deliverables
You get concrete refactor steps—extract method, guard clauses, smaller units—applied only when tests and context make change safe.
- Smaller focused functions and reduced nesting
- Refactor plan aligned with when-NOT guardrails
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Canonical shelf is Ship/review because refactors are safest when framed as quality passes before merge or release, even if edits happen during Build. Review subphase matches code-review feedback, red-green-refactor, and complexity reduction without changing outward behavior.
Where it fits
Turn review comment ‘nested if hell’ into early-return guard clauses with unchanged tests.
Split a 100-line order processor into validate, calculate, save, and notify before adding tax rules.
Run refactor only after red-green-refactor’s green step so CI still passes.
How it compares
Use as procedural refactoring guidance, not a static analyzer or automated codemod runner.
Common Questions / FAQ
Who is code-refactoring for?
Indie builders and small teams who want their coding agent to follow Martin Fowler–style discipline instead of speculative rewrites.
When should I use code-refactoring?
During Ship/review after feedback, in Build when extending a module you just green-tested, or before adding a feature to a messy function—never when SKILL.md says you lack tests or understanding.
Is code-refactoring safe to install?
It is documentation-only patterns with no bundled executables; still review the Security Audits panel on this page before trusting any fork of the skill package.
SKILL.md
READMESKILL.md - Code Refactoring
# Code Refactoring ## Refactoring Principles ### When to Refactor - Before adding new features (make change easy, then make easy change) - After getting tests passing (red-green-refactor) - When you see code smells - During code review feedback ### When NOT to Refactor - Without tests covering the code - Under tight deadlines with no safety net - Code that will be replaced soon - When you don't understand what the code does ## Common Code Smells ### Long Methods ```typescript // BEFORE: Method doing too much function processOrder(order: Order) { // 100 lines of validation, calculation, notification, logging... } // AFTER: Extract into focused methods function processOrder(order: Order) { validateOrder(order); const total = calculateTotal(order); saveOrder(order, total); notifyCustomer(order); } ``` ### Deeply Nested Conditionals ```typescript // BEFORE: Arrow code function getDiscount(user: User, order: Order) { if (user) { if (user.isPremium) { if (order.total > 100) { if (order.items.length > 5) { return 0.2; } } } } return 0; } // AFTER: Early returns (guard clauses) function getDiscount(user: User, order: Order) { if (!user) return 0; if (!user.isPremium) return 0; if (order.total <= 100) return 0; if (order.items.length <= 5) return 0; return 0.2; } ``` ### Primitive Obsession ```typescript // BEFORE: Primitives everywhere function createUser(name: string, email: string, phone: string) { if (!email.includes('@')) throw new Error('Invalid email'); // more validation... } // AFTER: Value objects class Email { constructor(private value: string) { if (!value.includes('@')) throw new Error('Invalid email'); } toString() { return this.value; } } function createUser(name: string, email: Email, phone: Phone) { // Email is already validated } ``` ### Feature Envy ```typescript // BEFORE: Method uses another object's data extensively function calculateShipping(order: Order) { const address = order.customer.address; const weight = order.items.reduce((sum, i) => sum + i.weight, 0); const distance = calculateDistance(address.zip); return weight * distance * 0.01; } // AFTER: Move method to where the data is class Order { calculateShipping() { return this.totalWeight * this.customer.shippingDistance * 0.01; } } ``` ## Refactoring Techniques ### Extract Method ```typescript // Identify a code block that does one thing // Move it to a new method with a descriptive name // Replace original code with method call function printReport(data: ReportData) { // Extract this block... const header = `Report: ${data.title}\nDate: ${data.date}\n${'='.repeat(40)}`; console.log(header); // ...into a method printHeader(data); } ``` ### Replace Conditional with Polymorphism ```typescript // BEFORE: Switch on type function getArea(shape: Shape) { switch (shape.type) { case 'circle': return Math.PI * shape.radius ** 2; case 'rectangle': return shape.width * shape.height; case 'triangle': return shape.base * shape.height / 2; } } // AFTER: Polymorphic classes interface Shape { getArea(): number; } class Circle implements Shape { constructor(private radius: number) {} getArea() { return Math.PI * this.radius ** 2; } } class Rectangle implements Shape { constructor(private width: number, private height: number) {} getArea() { return this.width * this.height; } } ``` ### Introduce Parameter Object ```typescript // BEFORE: Too many parameters function searchProducts( query: string, minPrice: number, maxPrice: number, category: string, inStock: boolean, sortBy: string, sortOrder: string ) { ... } // AFTER: Parameter object interfac