plugins/claude-code-hermit/skills/simplify/SKILL.md
Parallel code review and cleanup of recent changes. Replicates the original bundled /simplify command that was removed in CC v2.1.146.
npx skillsauth add gtapps/claude-code-hermit simplifyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Spawns three focused review subagents in parallel, each returning a list of suggested edits. The main agent then applies them sequentially, resolving conflicts deterministically using the Principles below. The skill is non-interactive: it never stops to ask the user. When the Principles don't pick a clear winner, the finding is logged as "not applied" rather than surfaced as a question — the user reads the final report and re-engages if they want one of the rejected proposals.
Why review-then-apply and not apply-in-parallel: if three subagents Edit the same files concurrently, they race. Late writers either fail loudly (Edit's old_string mismatch) or — worse — see "my change is already there" and silently skip, so most findings get dropped. Parallelizing the slow part (analysis) while serializing writes gives both speed and correctness.
If $ARGUMENTS contains a focus hint (e.g. "memory efficiency"), pass it through to all three subagents so they weight that dimension.
These are cross-cutting — they apply to every finding regardless of reviewer category. The main agent passes them into each reviewer's prompt.
Preserve behavior. Any change to return values, exceptions, edge-case handling, or observable side effects is a behavior change, not a simplification. If a refactor alters output for any input — even malformed or "invalid" input the original happened to accept — it's not a cleanup, it's a redesign. Don't propose those as simplifications; if you spot one and think it's worth doing, label it explicitly so the user can decide.
Clarity over brevity. Fewer lines is not the goal; a reader understanding the code at a glance is. Avoid nested ternaries when if/elif/else reads clearer. Don't wrap trivial operations in named helpers just to "reuse" something — multiplyTwoNumbers(n, n) is worse than n * n, not better. A short dense one-liner is worse than a two-line form a reader can follow on first pass.
Respect house conventions. If the session's CLAUDE.md documents style rules or idiom preferences, they win over generic idioms — a reviewer suggesting f-strings is wrong if CLAUDE.md says use .format(). CLAUDE.md is the canonical place for project rules; subagents already see it in context, so no manual passthrough is needed.
git status --short to surface untracked new files (no diff command shows these).git diff HEAD to capture unstaged + staged changes to tracked files.git diff against the merge-base. If still empty, fall back to recently modified or mentioned files in the current session.+++ block so the subagents see new files as additions.Dispatch three Agent tool calls in a single message. All use:
subagent_type: "general-purpose"model: "sonnet" — pin so cost stays predictable across parent session modelsEach reviewer receives the full diff and the focus hint (if any), and returns proposed edits as JSON. Reviewers do NOT call Edit. They report; the main agent applies.
Each reviewer must end its response with a fenced JSON block:
{
"findings": [
{
"file": "absolute/path/to/file",
"old_string": "exact text to replace (must be unique in the file or include enough context to be unique)",
"new_string": "replacement text",
"rationale": "one short sentence — what was wrong, why this is better",
"confidence": "high" | "medium" | "low"
}
]
}
Empty findings → {"findings": []}. Don't pad.
Review the following diff for missed reuse opportunities. Search the WIDER codebase (not just the diff) using Grep to find:
- New functions that duplicate existing utilities or helpers
- Inline logic that should use existing utilities: hand-rolled string manipulation, manual path handling, custom env checks, ad-hoc type guards
- Similar patterns in utility directories, shared modules, and adjacent files
Principles (apply to every finding):
- Preserve behavior. If your proposed change alters return values, exceptions, side effects, or edge-case handling for any input — including malformed input — it's a redesign, not a simplification. Don't propose it as a cleanup; if worth doing, flag it as a behavior change. Treat the diff's deleted (
-) lines as the behavior baseline — restoring the behavior of a deleted line (e.g. reverting an added== Trueto a plain truthiness check) is not a behavior change.- Clarity > brevity. Wrapping
n * ninmultiplyTwoNumbers(n, n)is not reuse, it's worse code. Only propose reuse when the existing helper genuinely captures a non-trivial pattern.- Respect house conventions. Project conventions (below) override generic idioms.
Do NOT use Edit, Write, or any file-modification tool. Your job is to propose edits, not apply them. Return findings as a JSON block per the schema above. Skip false positives silently.
FOCUS HINT: {hint or "none"}
DIFF: {paste full diff here}
Review the following diff for quality issues. Look for:
- Redundant state: state duplicating existing state, cached values that could be derived, observers/effects that could be direct calls
- Parameter sprawl: new parameters added instead of generalizing or restructuring
- Copy-paste with slight variation: near-duplicate blocks that should share an abstraction
- Leaky abstractions: exposing internals, breaking existing abstraction boundaries
- Stringly-typed code: raw strings where constants, enums, or branded types already exist
- Verbose patterns: unnecessary intermediate variables,
== true/== false, redundant else after return, multi-check null guards that collapse to one expression- Unnecessary JSX nesting: wrapper Boxes/elements that add no layout value — check if inner component props (flexShrink, alignItems, etc.) already provide the needed behavior
- Nested conditionals: ternary chains (
a ? x : b ? y : ...), nested if/else, or nested switch 3+ levels deep — flatten with early returns, guard clauses, a lookup table, or an if/else-if cascade- Unnecessary comments: comments explaining WHAT the code does (well-named identifiers already do that), narrating the change, or referencing the task/caller — delete; keep only non-obvious WHY (hidden constraints, subtle invariants, workarounds)
Principles (apply to every finding):
- Preserve behavior. If your refactor alters return values, exceptions, side effects, or edge-case handling for any input, it's a behavior change — flag it as such, don't dress it up as a cleanup. Treat the diff's deleted (
-) lines as the behavior baseline — restoring the behavior of a deleted line (e.g. reverting an added== Trueto a plain truthiness check) is not a behavior change.- Clarity > brevity. Don't trade readability for fewer lines. Nested ternaries, dense one-liners, chained mystery operators are not improvements over clear
if/elseblocks. A reader should grok the rewrite faster than the original.- Respect house conventions. Project conventions (below) override generic idioms.
Do NOT use Edit, Write, or any file-modification tool. Your job is to propose edits, not apply them. Return findings as a JSON block per the schema above.
FOCUS HINT: {hint or "none"}
DIFF: {paste full diff here}
Review the following diff for efficiency issues. NO premature optimization. Look for:
- Unnecessary work: redundant computations, repeated file reads, duplicate API calls, N+1 patterns
- Missed concurrency: independent operations run sequentially
- Hot-path bloat: blocking work on startup or per-request paths
- Recurring no-op updates: state/store updates inside polling loops, intervals, or event handlers that fire unconditionally — add a change-detection guard so downstream consumers aren't notified when nothing changed. Also: if a wrapper function takes an updater/reducer callback, verify it honors same-reference returns (or whatever the "no change" signal is) — otherwise callers' early-return no-ops are silently defeated
- TOCTOU anti-patterns: pre-checking existence before operating instead of operating and handling errors
- Memory: unbounded data structures, missing cleanup, event listener leaks
- Overly broad operations: reading entire files when only portions needed
Principles (apply to every finding):
- Preserve behavior. A faster algorithm that handles edge cases differently is a behavior change, not an optimization. Flag it as such. Treat the diff's deleted (
-) lines as the behavior baseline — restoring the behavior of a deleted line (e.g. reverting an added== Trueto a plain truthiness check) is not a behavior change.- Clarity > brevity. A single-pass loop is only better than two-pass if it stays readable. If merging passes makes the control flow harder to follow, the two-pass version was fine.
- Respect house conventions. Project conventions (below) override generic idioms.
Do NOT use Edit, Write, or any file-modification tool. Your job is to propose edits, not apply them. Return findings as a JSON block per the schema above.
FOCUS HINT: {hint or "none"}
DIFF: {paste full diff here}
Once all three reviewers return:
Parse the JSON blocks. If one reviewer's block fails to parse, log it and continue with the others — don't abort the whole run. If a finding is malformed (e.g. unescaped quotes inside old_string/new_string), repair it from the obvious intent and use it rather than dropping it — a repaired finding does not increment the parse-failure counter; only an unrecoverable finding counts as a parse failure. Group findings by (file, old_string). For each group with more than one finding, compare the new_string values:
Byte-identical or semantically equivalent new_string (e.g., trivial renames like u for u in ... vs user for user in ...) → silent dedupe. Keep the one with higher confidence; if tied, Code Quality > Code Reuse > Efficiency (Quality fixes tend to be the most local and least risky). If you're unsure whether two rewrites are equivalent, treat them as different and escalate.
Meaningfully different new_string (different algorithm, different control flow, different intermediates) → check the Principles against each variant:
If the principles don't discriminate — both options preserve behavior identically, both are equally clear, both respect conventions — apply neither. Log them under "Noticed but not applied: principles couldn't decide" so the user can pick if they care.
Never stop to ask. Surfacing a style call to the user mid-run defeats the point of having principles. The user invoked /simplify to clean code, not to answer a quiz.
For each file, read it once and locate each finding's old_string. Sort findings by their offset so edits happen top-to-bottom (helps the user follow the diff in review).
Two findings on the same file overlap if their old_string regions intersect. For each overlap group:
For each non-conflicting finding, in file order:
old_string still appears verbatim. Earlier edits or external changes can shift content; checking proactively is cheaper than recovering from an Edit failure.Edit with the old_string and new_string.Edit fails for any other reason, surface the error and stop on that file.Print a concise per-file summary, then "noticed but not applied", then totals:
path/to/file.ts
✓ [Quality] removed `=== true` comparison on line 31
✓ [Reuse] replaced manual loop with `.reduce(...)` on line 53
⊘ [Efficiency] skipped — old_string no longer matches (subsumed)
Noticed but not applied:
⚠ [Quality] proposed compound rewrite of parse_user_input (lines 70-74) —
rejected on principle "clarity > brevity" (denser, calls strip() twice).
To apply: ask explicitly.
⚠ [Reuse] proposed `email.partition("@")` with None return for no-@ inputs
(lines 95-99) — behavior change vs original (`""`). To apply: ask explicitly.
Totals: applied N · deduped M · principle-rejected K · stale-anchor skips L · parse failures P
The "Noticed but not applied" section is how the user discovers rejected proposals and can opt in. The skill never blocks waiting for an answer.
No essays. Just what changed, what didn't, and why.
data-ai
Initializes or resumes a work session. Loads context from OPERATOR.md and SHELL.md, orients the agent, and establishes what to work on. Use at the beginning of every work session.
tools
Evolves hermit configuration and templates after a plugin update. Detects version gaps, presents new features, walks through new settings. Run after updating the plugin.
testing
Initializes the autonomous agent in the current project. Creates the state directory, templates, OPERATOR.md, and config.json. Appends session discipline to CLAUDE.md. Detects installed hermits. Run once per project, like git init.
tools
Generates Docker scaffolding and walks the operator through the full deployment — token setup, build, start, MCP plugin configuration, workspace trust, and verification. Offers to back up and overwrite existing Docker files. Run after /hatch.