taming-legacy-code
Decide what to do with legacy or unfamiliar code and then do it safely. Picks between a full rewrite, an incremental refactor, and the Strangler Fig pattern, then refactors behind characterization tests using a full catalog of code smells and refactoring techniques. Use when touching legacy/fragile/unfamiliar code, extending or bug-fixing a module nobody wants to own, deciding "rewrite or refactor?", naming a code smell, or applying a specific refactoring.
Works with
Agent Skills format with YAML frontmatter. Claude Code reads it as-is.
--- name: "taming-legacy-code" description: "Decide what to do with legacy or unfamiliar code and then do it safely. Picks between a full rewrite, an incremental refactor, and the Strangler Fig pattern, then refactors behind characterization tests using a full catalog of code smells and refactoring techniques. Use when touching legacy/fragile/unfamiliar code, extending or bug-fixing a module nobody wants to own, deciding \"rewrite or refactor?\", naming a code smell, or applying a specific refactoring." license: "MIT" --- # Taming Legacy Code > "Code becomes legacy as soon as it's been written." Legacy code is any code you're afraid to change — usually because there are no tests, the authors are gone, and you don't know what will break. This skill turns that fear into a disciplined procedure. It works in **two layers**: 1. **Decide** the strategy — rewrite, incremental refactor, or Strangler Fig. → [strategy.md](./strategy.md) 2. **Do** the work safely — pin behaviour with tests, then transform in tiny verified steps. → [smells.md](./smells.md) + [catalog/](./catalog/) You drive the work yourself, but **stop at the checkpoints** below — the strategy fork, and before any change that isn't covered by tests. --- ## The safety spine (non-negotiable) Everything in this skill hangs on one rule, from Michael Feathers and Martin Fowler: > **Never change code you haven't pinned with tests, and never change more than one thing per step.** Concretely, the **hard gate** before any refactor: 1. **Is this code covered by tests?** Run them. If there's no coverage of the behaviour you're about to touch — **STOP**. 2. **No coverage → write characterization tests first.** Find a *seam* (a place you can sense the code's behaviour without editing it), call the code, capture what it *currently* does (even if that behaviour looks wrong), and assert on it. These tests don't validate correctness — they freeze current behaviour so you'll know the instant a refactor changes it. (Mechanics: [strategy.md → Characterization tests](./strategy.md#characterization-tests).) 3. **One refactoring = one tiny commit.** Each step leaves the program working. Run the tests after every step. 4. **Never batch unrelated changes.** Behaviour-preserving refactors and behaviour-changing edits go in separate commits, never mixed. If you cannot get the code under test, your first job is making it testable — not refactoring it. Do not skip this gate because a change "looks trivial." --- ## Process ### 1. Understand the territory Read the target code. Identify what it does, who calls it, and where its seams are. Check for existing tests. Note the smell(s) you can see ([smells.md](./smells.md)) but don't fix anything yet. ### 2. Decide the path — **CHECKPOINT** Walk the four questions in [strategy.md](./strategy.md). They point you at one of three paths. **Confirm the chosen path with the user before committing to it** — this decision is expensive to reverse. - **Refactor** — improve in place, same language/framework. → go to step 3, then step 4a. - **Strangler Fig** — build the replacement alongside the old code and reroute call sites piece by piece. → [strategy.md → Strangler Fig playbook](./strategy.md#strangler-fig-playbook). - **Rewrite** — replace wholesale. Rarely the right call. → [strategy.md → Rewrite guardrails](./strategy.md#rewrite-guardrails). ### 3. Lay the safety net Apply the safety spine above. No tests covering the area → write characterization tests now. This is the gate; do not pass it without a green test you trust. ### 4. Execute **4a. Refactoring path** 1. Name the smell → [smells.md](./smells.md). 2. The smell entry points to the refactoring(s) that cure it → [catalog/](./catalog/). 3. Apply the refactoring by its mechanics, one tiny step at a time, running tests after each. Commit per refactoring. **4b. Strangler / Rewrite paths** Follow the matching playbook in [strategy.md](./strategy.md). Both still reuse the safety spine: the old system's tests are your parity check that the new component behaves identically before you cut over. ### 5. Verify and stop Tests green, commits small and self-described, behaviour unchanged (unless a behaviour change was the explicit, separate goal). Summarize what changed and what you deliberately left alone. --- ## Files | File | Use it for | |------|-----------| | [strategy.md](./strategy.md) | The rewrite/refactor/strangler decision, characterization-test mechanics, and the per-path playbooks. | | [smells.md](./smells.md) | The 23 code smells, grouped, each pointing at the refactorings that cure it. Start here when something feels wrong but you can't name it. | | [catalog/](./catalog/) | 66 refactoring techniques, one file each: intent, when (not) to use, step-by-step mechanics, a tiny before/after, and the payoff. | ## Sources This skill is informed by Martin Fowler, *Refactoring: Improving the Design of Existing Code*; Michael Feathers, *Working Effectively with Legacy Code*; the [refactoring.guru](https://refactoring.guru) catalog; and Martin Fowler's writing on [StranglerFigApplication](https://martinfowler.com/bliki/StranglerFigApplication.html). All wording, steps, and examples here are original — written from scratch, not copied from those sources.
More Refactoring skills
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
analyze-project
lllllllama/rigorpilot-skills
Rigor Analyze / Rigor Audit read-only skill for deep learning research repositories. Use when the user wants to read and understand a repository, inspect model structure and training or inference entrypoints, review configs and insertion points, or flag suspicious implementation patterns without modifying code or running heavy jobs. Do not use for active command execution, broad refactoring, speculative code adaptation, or automatic bug fixing.
request-refactor-plan
mattpocock/skills
Create a detailed refactor plan with tiny commits via user interview, then file it as a GitHub issue. Use when user wants to plan a refactor, create a refactoring RFC, or break a refactor into safe incremental steps.

