Simplify
Improve code readability and reduce cognitive load without altering behavior.
For deleting code that is verified-unreferenced (not simplifying it), use the
remove-deadcode skill.
Core rule
The code must do exactly the same thing after simplification. No behavior
changes, no "while I'm here" improvements, no API surface modifications. If a
test breaks after simplification, the simplification was wrong — revert it.
When to use me
- Code is "too clever" — over-abstracted, deeply nested, hard to follow
- After a feature lands and code has accumulated cruft
- Review feedback says "this is hard to understand"
- You spot unnecessary indirection: wrappers that don't add value, interfaces
with only one implementation, functions called exactly once
Simplification checklist
Apply each pattern only if it reduces complexity without changing behavior:
Reduce nesting
- Early returns — replace
if (x) { ... entire function ... } with
if (!x) return. Flattens 3+ levels of nesting into a straight line.
- Guard clauses — check preconditions at the top and bail early.
- Extract deeply nested blocks into well-named functions only when the
extraction clarifies intent (not reflexively).
Remove unnecessary abstraction
- Single-caller functions — inline them. A function called from exactly one
place is just an indirection tax.
- Single-implementation interfaces — remove the interface and use the
concrete type directly.
- Thin wrappers — if a function just calls another function with the same
arguments plus one default, ask: is this wrapper pulling its weight?
- Overly generic utilities — a
createMapWithDefaultValue(key, defaultVal, strategy, cachePolicy) called only as createMapWithDefaultValue(x, {}, 'lru', 'none') should just be the concrete code.
Reduce variable count
- Inline single-use variables — if a variable is used exactly once, inline
its value at the use site. This is the single highest-leverage simplification.
- Eliminate temporary "explanation" variables — if the variable name just
restates what the RHS already says, delete it.
- Bad:
const isActive = user.status === 'active'; if (isActive) ...
- Better:
if (user.status === 'active') ... (the condition is self-documenting)
Simplify conditionals
- Ternary over if/else for assignments —
const x = cond ? a : b beats
5 lines of if/else.
- Remove redundant else — after a return/throw/break, the
else is dead
weight.
- Boolean expressions over if/else returning booleans:
- Bad:
if (x > 0) { return true; } return false;
- Good:
return x > 0;
Reduce surface area
- Unexport what isn't used externally. If a symbol is only used within its
own module, don't export it. Smaller public API = less to understand.
- Remove dead parameters. If a function accepts a parameter it never uses
(and no caller passes it meaningfully), remove it.
Safety protocol
Before every simplification:
- Run existing tests — confirm they pass before you touch anything.
- Make one simplification at a time — never batch them. One edit, verify,
commit.
- Run tests after each simplification — if anything fails, revert
immediately.
- Use LSP "find all references" — confirm a function truly has one caller
before inlining; confirm a parameter is truly unused before removing.
What NOT to simplify
- Performance-critical code where the "cleverness" is intentional and benchmarked.
- Framework boilerplate (route definitions, DI registrations, schema
declarations) — these follow framework conventions, not logic.
- Error handling paths — never remove error checks to "simplify."
- Public API signatures — changing them is a breaking change, not a
simplification.
- Test code that intentionally exercises edge cases with verbose setup.
Report format
After simplifying, report:
## Simplified: <file>:<function or section>
- Before: <pattern that was complex, e.g. "4 levels of nested if">
- After: <what changed, e.g. "early returns, flattened to 1 level">
- Tests: <all passing / N tests unchanged>
If you examined code and found no valid simplifications, say so explicitly rather
than forcing changes.
1---2name: simplify3description: Behavior-preserving code simplification — reduce complexity without changing what the code does. Use when the task mentions "simplify", "reduce complexity", "too clever", "hard to read", "reduce nesting", or after a feature lands and the code needs polishing. Oracle analyzes (read-only), light-orchestrator applies the edits.4---56# Simplify78Improve code readability and reduce cognitive load without altering behavior.9For deleting code that is verified-unreferenced (not simplifying it), use the10`remove-deadcode` skill.1112## Core rule1314**The code must do exactly the same thing after simplification.** No behavior15changes, no "while I'm here" improvements, no API surface modifications. If a16test breaks after simplification, the simplification was wrong — revert it.1718## When to use me1920- Code is "too clever" — over-abstracted, deeply nested, hard to follow21- After a feature lands and code has accumulated cruft22- Review feedback says "this is hard to understand"23- You spot unnecessary indirection: wrappers that don't add value, interfaces24 with only one implementation, functions called exactly once2526## Simplification checklist2728Apply each pattern only if it reduces complexity without changing behavior:2930### Reduce nesting3132- **Early returns** — replace `if (x) { ... entire function ... }` with33 `if (!x) return`. Flattens 3+ levels of nesting into a straight line.34- **Guard clauses** — check preconditions at the top and bail early.35- **Extract deeply nested blocks** into well-named functions only when the36 extraction clarifies intent (not reflexively).3738### Remove unnecessary abstraction3940- **Single-caller functions** — inline them. A function called from exactly one41 place is just an indirection tax.42- **Single-implementation interfaces** — remove the interface and use the43 concrete type directly.44- **Thin wrappers** — if a function just calls another function with the same45 arguments plus one default, ask: is this wrapper pulling its weight?46- **Overly generic utilities** — a `createMapWithDefaultValue(key, defaultVal,47 strategy, cachePolicy)` called only as `createMapWithDefaultValue(x, {}, 'lru',48 'none')` should just be the concrete code.4950### Reduce variable count5152- **Inline single-use variables** — if a variable is used exactly once, inline53 its value at the use site. This is the single highest-leverage simplification.54- **Eliminate temporary "explanation" variables** — if the variable name just55 restates what the RHS already says, delete it.56 - Bad: `const isActive = user.status === 'active'; if (isActive) ...`57 - Better: `if (user.status === 'active') ...` (the condition is self-documenting)5859### Simplify conditionals6061- **Ternary over if/else for assignments** — `const x = cond ? a : b` beats62 5 lines of if/else.63- **Remove redundant else** — after a return/throw/break, the `else` is dead64 weight.65- **Boolean expressions over if/else returning booleans**:66 - Bad: `if (x > 0) { return true; } return false;`67 - Good: `return x > 0;`6869### Reduce surface area7071- **Unexport what isn't used externally.** If a symbol is only used within its72 own module, don't export it. Smaller public API = less to understand.73- **Remove dead parameters.** If a function accepts a parameter it never uses74 (and no caller passes it meaningfully), remove it.7576## Safety protocol7778Before every simplification:79801. **Run existing tests** — confirm they pass before you touch anything.812. **Make one simplification at a time** — never batch them. One edit, verify,82 commit.833. **Run tests after each simplification** — if anything fails, revert84 immediately.854. **Use LSP "find all references"** — confirm a function truly has one caller86 before inlining; confirm a parameter is truly unused before removing.8788## What NOT to simplify8990- Performance-critical code where the "cleverness" is intentional and benchmarked.91- Framework boilerplate (route definitions, DI registrations, schema92 declarations) — these follow framework conventions, not logic.93- Error handling paths — never remove error checks to "simplify."94- Public API signatures — changing them is a breaking change, not a95 simplification.96- Test code that intentionally exercises edge cases with verbose setup.9798## Report format99100After simplifying, report:101102```103## Simplified: <file>:<function or section>104- Before: <pattern that was complex, e.g. "4 levels of nested if">105- After: <what changed, e.g. "early returns, flattened to 1 level">106- Tests: <all passing / N tests unchanged>107```108109If you examined code and found no valid simplifications, say so explicitly rather110than forcing changes.