Claude Code /simplify cleans up your diff with four parallel agents — and /code-review checks it after

The Claude Code /simplify skill runs four parallel cleanup reviews on a diff and applies the fixes, then /code-review checks the result for bugs.

The Claude starburst logo in terracotta and the Claude wordmark in black on a white card
On this page

Introduction

I had been running /simplify, a skill bundled with Claude Code, for weeks without knowing what it did. I only knew it had a twin, /code-review, and that many people recommend using the two together. The two looked alike to me, and I could not have said how they split the work.

/simplify is a cleanup-only review. Four agents read the diff in parallel, each from one angle: reuse, simplification, efficiency, and altitude, meaning whether a change sits at the right layer. Their fixes go straight into the working tree, with no list of proposed changes for you to pick from first.

/simplify never looks for correctness bugs, so /code-review runs after it, on the code /simplify leaves behind. I ran both on a real commit from this blog to see what each one catches.

What /simplify runs

/simplify is a bundled skill, a prompt built into Claude Code that tells the model how to carry out the review and the fixes with its own tools. The commands reference describes it in one entry:

Review the changed code for cleanup opportunities and apply the fixes. Four review agents run in parallel, covering reuse of existing helpers, simplification, efficiency, and whether the change is at the right level of abstraction. The review doesn’t look for correctness bugs. Use /code-review to find bugs.

The prompt /simplify loads runs in three phases:

  1. Gather the diff. git diff against the upstream branch, plus uncommitted changes, or the path or pull request passed as an argument.
  2. Review. Four agents start at the same time, each handed the diff from step 1 and the angle it reviews from.
  3. Apply. Findings that point at the same line are merged into one, then each is fixed in the working tree.

Each agent gets one brief from the prompt:

AgentWhat the prompt tells it to look forExample from the run below
ReuseNew code that re-implements a helper the codebase already has, found by searching shared and nearby modulesnew URL(SITE) is also built in scripts/indexnow.ts, but nothing exports a parsed copy the new code could import
SimplificationRedundant or derivable state, copy-paste with small variations, deep nesting, dead code left behindresolveMark built an object that its only caller immediately took apart
EfficiencyRepeated computation or I/O, independent steps run one after another, work added to a hot pathluminance(DARK_BACKGROUND) is recomputed for every icon on every page, when it could be computed once at module load
AltitudeA symptom patched in place when the root cause sits one layer deeper, or a special case layered on shared codeThe blog’s old hostname was hardcoded in the marks table instead of living in site.ts

The apply phase, run by the main agent rather than the four reviewers, has one escape hatch, quoted from the prompt:

Skip any finding whose fix would change intended behavior, require changes well outside the reviewed diff, or that you judge to be a false positive — note the skip rather than arguing with it.

Finding bugs is the job of the other bundled skill, /code-review:

/simplify/code-review
Looks forReuse, simplification, efficiency, altitudeCorrectness bugs, plus cleanups depending on model and effort level
Edits filesAlways applies its fixesReports only, unless --fix is passed
Runs asFour review agents in parallelA background subagent with its own context window
TakesA path or pull request referenceAn effort level from low to max or ultra, --fix, --comment, --max-findings, and a pull request, branch, or path

That March write-up is by Bozhidar Batsov, the author of RuboCop, a static code analyzer and formatter for Ruby, who calls /simplify “the skill I use most often” and runs it “right after a larger refactoring or after accepting a batch of AI-generated code.”

/simplify on a real diff

The diff I picked had already shipped. It taught rehype-link-icons.ts, this blog’s rehype plugin (a step that edits the HTML at build time) that draws a brand mark beside a link, four new marks: Qiita, Zenn, DevelopersIO, and this blog’s own seal for links back here.

I replayed the past commit as uncommitted changes in a separate worktree, so /simplify could edit freely without touching the real checkout or work in progress:

Terminal window
git worktree add --detach ../simplify-trial <commit>^
git -C ../simplify-trial cherry-pick -n <commit>

Then, from inside that worktree, on Claude Code 2.1.310:

/simplify src/lib/rehype-link-icons.ts

The four agents returned nine findings, and /simplify applied three of them:

AgentFindingsApplied
Reuse00
Simplification32
Efficiency00
Altitude61

Reuse and efficiency show 0 because both agents reported only observations, like the examples in the earlier table, and nothing the diff needed to change.

The three fixes it applied

The largest one is the simplification example from the table: it removed MarkSymbol, a type whose only job was to carry the id field from resolveMark to its single caller. That caller, the code that builds the sprite (one hidden <svg> holding every mark), took the result apart the moment it arrived:

src/lib/rehype-link-icons.ts (before)
function resolveMark(key: MarkKey): MarkSymbol {
if (isLocal(key)) return { id: symbolId(key), ...LOCAL_MARKS[key]() };
return { id: symbolId(key), viewBox: "0 0 24 24", children: [markPath(key)] };
}
// …
children: [...used].map((key) => {
const { id, viewBox, children } = resolveMark(key);
return element("symbol", { id, viewBox }, children);
}),

/simplify replaced resolveMark with symbol(), which returns the <symbol> node itself, and the MarkSymbol type went away:

src/lib/rehype-link-icons.ts (after)
function symbol(key: MarkKey): HastNode {
const { viewBox, children } = isLocal(key)
? LOCAL_MARKS[key]()
: { viewBox: "0 0 24 24", children: [markPath(key)] };
return element("symbol", { id: symbolId(key), viewBox }, children);
}
// …
children: [...used].map(symbol),

The other two were smaller:

  • How the favicon is read. The plugin reads the seal’s shape from the favicon. The <svg> tag was read on a line of its own while <circle>, <g> and <path> shared one .map; now all four go through the same .map, with the same result.
  • The old hostname. The blog’s old address, oharu-tech-blog.vercel.app, was typed straight into the marks table, though the site’s addresses belong in site.ts. This is the altitude example from the table. It now lives in site.ts as LEGACY_HOSTS, so a change of address means editing that one file.

The six it skipped

The six findings /simplify skipped, and why:

SuggestionWhy it was skipped
Run the contrast check over the self-drawn marks (DevelopersIO and the seal) tooWould change behavior: both marks would be recoloured in dark mode
Classify links after parsing them, so a ./other/ link also gets the sealWould change behavior: links with no icon today would gain the seal
Drop the 24×24 viewBox from each icon’s outer <svg>Would change behavior: the icons’ displayed size could change
Have the brand generator emit the seal geometry as a module instead of regex-parsing public/favicon.svgOutside the diff: the change belongs in the separate script that generates the favicon
Use the new element() helper in the older node buildersOutside the diff: it touches code this commit never changed
One uniform mark object in place of the isLocal branchPartly covered: the symbol() change already removed one place the branch appears

/simplify does not run the code it edits. So Claude Code checked separately that the three fixes changed nothing on the page. It fed six kinds of link (GitHub, root-relative, the old host, DevelopersIO, Zenn and a footnote) through the plugin before and after, and the outputs were identical.

Running /code-review on what /simplify left

/code-review on rehype-link-icons.ts and site.ts, the two files /simplify had edited, returned ten findings.

Nine of them were in the commit as it shipped. Three of them reproduce directly:

InputWhat the plugin doesWhy
href="/\github.com/x"Draws the GitHub markThe root-relative test excludes // but not /\, and URL parsing reads the backslash as a slash
href="http://constructor/"Throws TypeError: key.slice is not a function, failing the buildThe marks table is a plain object, so the hostname finds Object.prototype.constructor
DevelopersIO’s #cbd31e segmentRenders at 1.63:1 against the light theme’s white, under WCAG’s 3:1 floorSelf-drawn marks skip the contrast check

The altitude agent had read the root-relative regex in markFor too, but only said the check sat at the wrong layer. Whether the regex lets a malformed href through is a correctness question, outside its angle, so the backslash case waited for /code-review.

When do /simplify and /code-review run?

Run /simplify first and /code-review last. /simplify writes to the working tree, and a review only sees the code that exists when it runs, so in the other order /simplify’s edits get committed without any review.

/simplify first, /code-review lastFour cards from left to right. A diff goes into /simplify, where four agents review it in parallel for reuse, simplification, efficiency, and altitude and apply cleanup fixes to the working tree. The result goes into /code-review, which reports correctness bugs in the code /simplify left. Last, the author fixes the findings and checks git diff.Edits happen in /simplify, so the review comes after itYour diffChanged code,committed or not/simplifyApplies cleanup fixesto the working tree/code-reviewReports correctnessbugs in the code/simplify leftYouFix the findings,check git diffFour agents in parallelReuseSimplificationEfficiencyAltitude
/simplify edits the diff, so /code-review reads its output rather than the other way round.

Batsov’s March workflow ran the other way: “make changes, run /review to catch issues, fix anything it flags, then run /simplify to clean things up.”

Summary

/simplify sends a diff to four parallel agents for reuse, simplification, efficiency, and altitude, applies their fixes, and skips any fix that would change behavior or reach outside the diff. It never looks for bugs and never runs the code it edits.

Run /code-review after it, on the code /simplify leaves behind. To try both on a commit that has already shipped, replay it into a separate worktree with git cherry-pick -n and run them there.

References

Share this article