Claude-starter cleanup-slop
Strip AI slop, narration comments, restated-code comments, in-motion notes, and stub markers. Preserves comments that explain WHY (workarounds, invariants, surprising behavior). Comment-only changes — never touches code logic. Use when the user asks to remove AI slop, clean up comments, strip narration, or remove unhelpful comments.
git clone https://github.com/raintree-technology/claude-starter
T=$(mktemp -d) && git clone --depth=1 https://github.com/raintree-technology/claude-starter "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/code-quality/cleanup-slop" ~/.claude/skills/raintree-technology-claude-starter-cleanup-slop && rm -rf "$T"
skills/code-quality/cleanup-slop/SKILL.mdSurgically remove unhelpful comments without touching code. The good comments — workarounds, invariants, citations, non-obvious WHYs — stay. The bad ones — restating code, narrating in-motion edits, AI-generated platitudes — go.
Core rule: a useful comment tells a future reader something they couldn't get by reading the code itself. Everything else is noise.
Preflight
- Language detect — comment syntax differs but the patterns are universal.
- Git state: refuse on dirty tree.
- Report dir: ensure exists.
- No code changes: this skill ONLY edits comments. If a "comment fix" requires changing code, surface to user instead.
Detect
Use grep + heuristics. There's no perfect tool — this is mostly pattern matching.
Patterns to find (HIGH-confidence slop)
A. Restated-code comments — comment says what the code already says.
# Look for comments immediately above a line where the comment is essentially the function/variable name in English grep -rn --include="*.ts" --include="*.tsx" --include="*.py" --include="*.js" \ -B0 -A1 -E "^\s*(//|#) (Returns|Sets|Gets|Creates|Updates|Deletes|Removes|Adds|Imports|Exports|Initializes|Initialize|Render|Renders) " . > /tmp/restated.txt
B. In-motion narration — comments describing the edit, not the code.
grep -rn --include="*.ts" --include="*.tsx" --include="*.py" --include="*.js" --include="*.go" --include="*.rs" \ -E "(// |# )(removed|replaced|new approach|updated to|previously|was using|no longer|TODO\(?from claude|TODO\(?ai\)|generated by claude)" \ --exclude-dir=node_modules . > /tmp/narration.txt
C. Stub markers without TODO
grep -rn --include="*.ts" --include="*.tsx" --include="*.py" --include="*.js" \ -E "^\s*(//|#) (implementation here|your code here|fill in|replace this|placeholder)" . > /tmp/stubs.txt
D. AI platitudes — generic preamble that adds nothing.
grep -rn -E "(// |# )(This (function|class|method) (is|will|does|provides|handles|manages|allows))" \ --include="*.ts" --include="*.tsx" --include="*.py" --include="*.js" \ --exclude-dir=node_modules . > /tmp/platitudes.txt
E. Empty docstrings / pass with no real TODO
grep -rn --include="*.py" -B1 -A2 'pass\s*#\s*TODO\s*$' . > /tmp/empty-todo.txt grep -rn --include="*.py" '"""\s*"""' . > /tmp/empty-docstring.txt
Patterns to PRESERVE
Even if they look formulaic, keep:
- Comments referencing issue/PR/ticket numbers (
,// see #1234
)// fixes JIRA-456 - Comments documenting workarounds with reason (
)// workaround for Safari bug, see ... - Comments stating invariants (
,// caller must hold lock
)// must run after middleware X - Comments warning about non-obvious behavior (
)// this MUST stay sync — async breaks ordering - Comments citing specs/RFCs/external docs
- License headers, copyright notices
- Type-system pragmas (
,// @ts-expect-error
,# type: ignore
)// eslint-disable-next-line - JSDoc/TSDoc on public APIs (even if formulaic — it generates docs)
Assess
Write
.claude/cleanup-reports/cleanup-slop-{YYYY-MM-DD}.md:
# Comment Slop Assessment — YYYY-MM-DD ## Summary - Comments scanned: N - HIGH (delete): X - Restated code: x1 - In-motion narration: x2 - Stub markers: x3 - AI platitudes: x4 - Empty docstrings: x5 - MEDIUM (review): Y — stale TODOs >6mo, generic JSDoc on internal funcs - PRESERVED: Z — comments with citations, invariants, warnings ## Findings ### HIGH — `lib/format.ts:12` ```ts // Returns the formatted string function format(s: string): string { ... }
Action: delete the comment line.
HIGH — services/user.ts:88
services/user.ts:88// removed the old caching logic, now uses redis async function getUser(id: string) { ... }
Action: delete (in-motion narration; the diff/git log records this).
HIGH — apps/api/middleware/auth.ts:5
apps/api/middleware/auth.ts:5// This middleware function handles authentication for incoming requests
Action: delete (AI platitude; the function name
auth.ts and signature say it).
MEDIUM — lib/parse.ts:34
lib/parse.ts:34// TODO: handle edge case
Stale 8 months. Either resolve or add detail. Flag for human triage.
PRESERVED — apps/api/middleware/auth.ts:42
apps/api/middleware/auth.ts:42// MUST run before db middleware — db middleware reads c.var.user. // Past incident: reordering crashed every authenticated request (see RUNBOOK.md).
Citation + invariant + war story. Exemplary comment, keep.
Critical Assessment
[2-3 paragraphs on the comment culture: heavy AI slop suggests recent AI-assisted code generation that wasn't reviewed. Lots of "removed X" suggests insufficient git-log discipline. Few useful WHY comments suggests engineers aren't capturing tribal knowledge.]
## Apply **Auto-delete HIGH only. NEVER touch code logic.** ### Confidence rubric **HIGH (delete the comment line):** - Pattern A-E above, AND - The comment is immediately above or beside code (not a section header) - Removing it doesn't leave a dangling reference (no other comment refers to it) **MEDIUM (report only):** - Stale TODO/FIXME with no detail (>6 months by git blame) - Generic JSDoc/docstring on internal functions (could be deleted but might satisfy a lint rule — let human decide) - Comments that summarize a complex algorithm — usually useful, but if the algorithm is named (e.g., `quickselect`), summary may be redundant **PRESERVE always:** - Citations (issues, PRs, RFCs, specs) - Invariants and load-bearing constraints - Workaround explanations with reason - License/copyright - Type pragmas / lint disables - JSDoc on public exports ### Execution 1. Use Edit to delete each HIGH comment line. Preserve indentation of surrounding code. 2. If a comment block is multi-line and ALL lines are slop, delete the whole block. 3. If a comment block has a slop preamble + a useful warning, delete only the slop preamble. 4. Single commit: `chore(cleanup): cleanup-slop — removed N unhelpful comments`. ## Verify Comment changes can't break logic, but they can break: - Doc generators (TypeDoc, Sphinx) if a JSDoc/docstring on a public API was removed - Markdown extraction tools ```bash # Lint catches some malformed-comment issues npx @biomejs/biome check . 2>&1 || npx eslint . 2>&1 ruff check . 2>&1 # If docs build script exists, run it npm run docs 2>/dev/null || true
If anything fails: revert that specific file and downgrade.
Output
- "Removed N unhelpful comments. M flagged for human review (stale TODOs, generic JSDoc)."
- Report path.
- Verify status.
NEVER
- Touch any code logic — comments only. If a "fix" needs code changes, escalate.
- Delete comments referencing issue/PR/ticket numbers, RFCs, or specs.
- Delete invariant warnings ("must run before X", "caller holds lock").
- Delete
,// @ts-...
,// eslint-...
,# type: ignore
pragmas.# noqa - Delete JSDoc/TSDoc on exported public APIs (they feed doc generation).
- Delete license headers or copyright notices.
- Delete comments inside strings or templates that look like comments but aren't.
- "Improve" comments by rewriting them — this skill removes, doesn't author.
- Delete comments in test files that explain test intent (those are often the only documentation of edge-case behavior).