Why Comments
Flag comments that say what the code already says. Keep every comment that explains why. The user chooses which flagged comments to remove.
Definition
A comment is redundant if deleting it loses no information.
Test: remove the comment mentally. Could a reader still understand the code from the code alone? If yes, the comment is redundant.
A comment is valuable if it carries information the code cannot convey, such as a reason, a constraint, a history, or a warning.
When unsure, keep it.
Invocation
| Command | Behavior |
|---|---|
/why-comments | Find the 10 lowest-value comments. |
/why-comments <number> | Find that many lowest-value comments. |
/why-comments all | Find every low-value comment. |
Workflow checklist
Copy this checklist and track your progress:
Comment Prune Progress:
- 1. Resolve the limit (default 10)
- 2. Search source files for comment candidates
- 3. Rank from most to least redundant
- 4. Get each candidate's age with git blame
- 5. Present the table and ask for approval
- 6. Remove only approved comments
- 7. Run lint and typecheck
1. Search
- Resolve the limit from the invocation. Default is 10.
- Search source files. Skip generated output, vendored dependencies, lockfiles, and documentation.
- Rank candidates from most redundant to least.
- Get each candidate's age with
git blame(see Comment age).
If a subagent is available, delegate the read-only search: request at most the limit, each with exact path, line, comment text, and one to three adjacent code lines. If a subagent is unavailable, run grep yourself. Do not simulate delegation or invent search results.
2. Present findings
Use exactly these columns:
| Comment | Age | Why |
|---|---|---|
// increment the counter | 8 months ago | Remove. Restates count++ verbatim. |
/** Returns the user id. */ | 3 weeks ago | Remove. Describes the function word by word. |
// debounce avoids hammering the API on each keypress | 1 year ago | Keep. Explains intent, not mechanics. |
- Comment: include the exact comment text in backticks.
- Age: use the relative
git blameage. - Why: start with
*Remove.*or*Keep.*, then give one short reason.
Then ask:
Remove all recommended?
- Yes, remove all recommended
- No, I want to review each comment
3. Remove and verify
- Remove only the approved comments. If the user chose review mode, ask
RemoveorKeepfor each, naming it by its exact text, not its location. - Run the project's lint and typecheck. Fix anything the changes broke.
Never remove
Keep any comment that carries a why the code cannot convey:
- backports, compatibility, or version-specific behavior;
- infrastructure, deployment, or architecture;
- workarounds, gotchas, or non-obvious reasons;
- documentation, specifications, RFCs, or ADRs;
- bugs, issues, tickets, or contextual TODOs/FIXMEs;
- intent, trade-offs, or constraints;
- public API documentation comments, even when they seem obvious.
Edge cases
- Public API doc comments: keep them. They are contract documentation for consumers, even when they describe the obvious.
- Commented-out code: that is dead code, not a comment. Output a STOP
block and tell the user to invoke
/prune. Do not delete it here. Do not continue ranking comments until the user has routed or dismissed that finding. - License headers: keep. Removing them changes legal posture.
- Generated files: skip them entirely. Do not rank or report comments in generated output.
- A comment that is half-wrong: flag it as a Keep-with-fix row instead of removing it. Deleting a wrong comment loses the warning it half-carries.
Comment age
For each candidate, run:
git blame -L <line>,<line> --date=relative -- <file>
Use the relative date.
Mark uncommitted lines uncommitted.
See examples/findings-table.md for a worked table.