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.

lairil/skills8 installsMITSynced Aug 22

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

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

← All Refactoring skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY