Code Quality

Simplify & Refactor

Reduce accidental complexity in changed code without changing behavior -- reuse, flatten, and remove, never redesign.

When to use this

  • After a feature lands and the diff works but reads harder than it should.
  • When asked to "clean this up" or "simplify" a specific file or function -- not a request to review for bugs.
  • Not for changing public APIs, data models, or behavior -- that's a redesign, a different and riskier task.

The skill file

Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.

SKILL.md
---
name: simplify-refactor
description: Simplify recently changed code -- reduce duplication, remove unneeded abstraction, flatten nesting -- without changing behavior. Use for explicit "simplify" or "clean up" requests, not general code review.
---

# Simplify & Refactor

Behavior-preserving only. If a change would alter output, error behavior, or
performance characteristics, it's not in scope here -- flag it instead of
making it.

## What counts as a simplification

- Replacing a hand-rolled loop with an existing standard-library or
  in-repo helper that does the same thing.
- Collapsing a wrapper function/class that adds no behavior over what it
  wraps.
- Flattening nested conditionals when an early return says the same thing
  more plainly.
- Deleting dead code: unused parameters, unreachable branches, exports
  nothing imports.
- Merging near-duplicate blocks into one, but only when the duplication is
  real (same logic) -- three similar-looking blocks with different
  invariants are not duplication, they're coincidence.

## What is NOT in scope

- Renaming for "better" naming alone, unless the current name is actively
  misleading.
- Introducing a new abstraction "for future flexibility" -- that's the
  opposite of simplifying.
- Reformatting untouched code just because you're in the file.

## Process

1. Read the target code and everything that calls it.
2. List candidate simplifications with a one-line reason each.
3. Apply only the ones that shrink the diff's cognitive load -- if a
   "simplification" needs its own paragraph to justify, it's not one.
4. Run the existing test suite (or the closest available check) after each
   change; a simplification that breaks a test is a bug, not a simplification.

## Output

A short list of what changed and why, plus confirmation that behavior is
unchanged (tests still pass, or a note on what you couldn't verify).

Installing it elsewhere

The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:

Claude Code
.claude/skills/simplify-refactor/SKILL.md

Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /simplify-refactor.

Cursor
.cursor/rules/simplify-refactor.mdc

Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.

Codex CLI / Copilot
AGENTS.md

Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.

Windsurf
.windsurfrules

Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.

Where this goes wrong
  • "Simplifying" by introducing a generic abstraction over two call sites -- that's added complexity wearing a disguise.
  • Touching code outside the requested scope because it was "right there" -- keep the diff to what was asked.
  • Skipping the post-change test run -- an unverified refactor is a bet, not a cleanup.