code-reduction · git:20260909.9164540 · 2026-09-09 · sha256 5a6ac53b1f1d945a
code-reduction git:20260909.9164540B
Immutable. This exact content never changes and is served at /api/v1/blob/5a6ac53b1f1d945a.
--- argument-hint: "[path or scope]" context: fork allowed-tools: - Read - Grep - Glob - Bash - Write description: 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. --- 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`