# Code Reduction

> Reviews a codebase for what to delete, inline, and flatten — abstractions that don't earn their keep, ceremonial types, obscuring indirection, tests of language features. Use when code has accreted structure and needs shrinking. Writes findings to `.issues/`; recommends changes but does not apply them.

- Skill: `philoserf/code-reduction` (Agent Skill)
- Install (CLI): `npx skillmds@latest add philoserf/code-reduction`
- Raw SKILL.md: https://api.skillmd.com/api/skills/philoserf/code-reduction/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: philoserf (https://skillmd.com/u/philoserf)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/philoserf/code-reduction

---


Review this codebase and advise on refactoring to reduce, simplify, remove, and reorganize. The goal is less code and fewer concepts, not tidier code.

Scope the review to `$ARGUMENTS` if provided, otherwise review the whole project. Examples: `src/api/`, `the test suite`, `lib/parsers/`.

Skip vendored dependencies, build output, generated code, and lockfiles (`node_modules/`, `dist/`, `vendor/`, `*.min.js`, `go.sum`).

## First, establish the license to delete

This skill assumes **sole-owner code with no backward-compatibility constraints**. That assumption is what makes aggressive deletion the right call, so check it before leaning on it: look for a published package name, semver tags, a CHANGELOG, a documented public API, or `deprecated` markers that imply someone downstream. If you find signs of external consumers, say so explicitly and mark which recommendations the constraint blocks — don't silently soften the whole review.

## What to look for

**Abstractions that don't earn their keep.** An interface with one implementation. A factory that constructs one thing. A base class extended once. A strategy pattern over two branches that never grew to three. A config object for parameters that are always the same. Count the call sites — an abstraction with one caller is a function with extra steps.

**Types that add ceremony without safety.** Wrappers whose only behavior is to hold a value of the type they wrap. Enums that mirror a set of strings without constraining anything. Type gymnastics that encode a rule the runtime doesn't enforce anyway. Ask what invalid program the type actually rejects — if the answer is "none," it's documentation with a compile step.

**Indirection that obscures rather than clarifies.** Chains of thin delegating methods. Event buses and callback registries where a direct call would do. Dependency injection for dependencies that are never substituted. Files that exist only to re-export. Trace a real request end-to-end and count the hops that make a decision versus the ones that pass a value along.

**Tests that test the language, not the business.** Asserting that a constructor assigns its arguments. Asserting a getter returns the field. Round-tripping a serializer through itself. Testing that a mock was called with what the test just told it to call. These cost maintenance and pin down nothing. Delete them; they're worse than no coverage because they inflate the number.

Look also for **near-duplication that should collapse** and **shared helpers that should split**: two call sites diverging through a flag parameter usually want to be two functions, and one helper with a mode switch usually wants to be inlined into both.

## Priority order

When two fixes compete, prefer:

1. **Deletion over renaming.** Dead code, unused exports, commented-out blocks, and abandoned feature flags go first. A better name for code that shouldn't exist is wasted work.
2. **Inlining over extracting.** Collapse single-use helpers into their caller. Extraction is the reflex that created the problem.
3. **Flattening over restructuring.** Fewer layers beats better-organized layers. Moving files between directories rearranges the problem; removing a layer solves it.

Reorganization comes last, but do recommend it where it removes a concept or shortens the path through the code — not for tidiness. It is often most obvious after a deletion, when removing a layer leaves two files that plainly belong together.

## Before recommending a deletion

Verify it's actually unused, don't infer it from a quick grep. Check for dynamic dispatch, reflection, string-keyed lookup tables, config-driven wiring, framework conventions that call by name, and entry points invoked by CI or scripts rather than by code. Say which check you ran. A confident wrong deletion costs more than the code it removed.

Where a build or test command exists, note whether the change is verifiable — "removing this is covered by `task test`" is a materially stronger recommendation than one nothing checks.

## Output

Findings go to `.issues/` and the overview to `.issues/000-reduction.md`, following
[issues-protocol.md](../code-audit/references/issues-protocol.md) — the canonical copy
shared across the `code-*` review skills. Read it before writing anything. It defines the
file layout, the finding format, the dedup checks against `.issues/` and GitHub, and what
to do on a re-run.

One file per reduction, with `**Source:** code-reduction` and a `**Payoff:**` line giving
approximate lines removed and the risk of removing them. State the concrete move in
`## Suggested fix` — delete / inline into X / flatten Y and Z — and name the check that
would confirm it.

`code-audit` findings will land on the same code, and the collision is the useful part: an
abstraction you want deleted may be one it flagged a bug inside. Cross-reference it and say
which move comes first. Deleting the code closes both; fixing the bug in code that should
not exist is wasted work — but say so rather than assuming it.

Order the overview by payoff — most lines removed for least risk first — and give an
approximate line count for the whole set so the user can judge scale. The index table stays
severity-ordered, per the protocol, so it collates with the other skills'.

This skill is advisory and does not apply changes.

## Do not use when

- Reviewing a staged diff or recent changes rather than a whole codebase — use `/simplify`, which reviews changed code and applies the fixes
- Hunting for bugs, security issues, or missing error handling — use `code-audit` or `/code-review`
- Trying to understand why the system is shaped as it is before changing it — use `code-theory`; run it first if the design rationale is unclear, since an abstraction that looks unearned may be load-bearing for a reason the code doesn't state
- The ask is a target design or a migration plan, not a list of things to remove — use `code-refactor`

