Repository context. Gather first
Collect these with individual Bash calls, one command per call, never combined into a single
invocation:
- Current branch,
git branch --show-current
Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as
separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute
block as one shell invocation, and a worktree-isolated session refuses a compound command that
contains git. The dated record for that composition claim is the source-control plugin's
worktree/reference/gather-block.md,
"The pre-compute block runs as one shell invocation".
Pre-computed context
Uncommitted code files (empty = none matched or the probe returned nothing): !${CLAUDE_SKILL_DIR}/scripts/changed-code-files.sh 10 2>/dev/null || echo "(git status unavailable)"
Residue findings (sample): !${CLAUDE_SKILL_DIR}/scripts/detect.sh 2>/dev/null | grep -E '^(Summary total:|Finding shape:)' | head -20 || echo "none"
Purpose
Code comments accumulate RESIDUE. Text that only makes sense outside the code's present state:
narration of what the code used to be, references to the plan/session/changeset that produced it,
asides addressed to the requester, and back-references to a ticket, PR, or branch no future reader
will ever open. Version control owns history; the comment describes the present. A comment that only
makes sense inside the chat thread that produced it is dead. This skill is a read-only classifier: it
surfaces candidates with treatment guidance.
It detects residue on the COMMENT portion of a line only, so a residue-shaped word sitting in an
identifier or string literal is never flagged. The positive question, does this comment capture
something the code cannot (a non-obvious why, a constraint, an interface/design-intent contract)?, is left to the author; the shapes below are the comments that fail it.
Residue shapes and treatments
| Shape |
What it looks like |
Default tier |
Treatment |
history-narration |
The comment narrates the code's past: "used to…", "no longer…", "previously", "renamed from X", "we switched from…", "now returns…" |
1 |
Delete. Version control owns history. Keep only if the reason for the change is a load-bearing constraint, rewritten as present-tense rationale ("must stay ordered because…") |
plan-reference |
References a work plan, session, or changeset rather than the code: "Task 2 replaces the old…", "as planned", "in this PR/commit/refactor" |
1 |
Delete, the plan is not part of the code's meaning. Fold any surviving intent into a present-tense why-comment |
conversational-antecedent |
Addresses the requester or the producing conversation: "per your request", "as you asked", "like you said", "per our discussion" |
1 |
Delete, the conversation is invisible to every future reader |
ticket-pr-residue |
Back-reference to a tracker/PR/branch a reader can't follow: "see PR #45", "from the feature branch", "JIRA-123" |
2 |
Review. Delete a bare provenance reference; a TODO(#issue) tracking real outstanding work is the sanctioned exception and is NOT flagged |
Consumers with their own comment conventions can refine these defaults in their repo's CLAUDE.md /
rules; the classifier's shapes and tiers above are the skill's built-in baseline.
Action router
| Action |
Args |
Behavior |
<target> (default, no action keyword) |
empty → uncommitted code files from git; file path → single-file; dir path → batch |
run ${CLAUDE_SKILL_DIR}/scripts/detect.sh on targets; map the emitted facts to the per-file tier table using the treatments above |
audit [target] |
same target rules |
explicit form of the default; same behavior |
Auto-detect default
- Empty arg AND no uncommitted code files → friendly no-op exit 0 ("No uncommitted code files. Pass a file/dir target.")
- Empty arg AND uncommitted code files → batch audit over those files
- Single file path → single-file audit
- Directory path → batch audit (filenames sorted lexically for deterministic output)
- First positional ==
audit → audit on rest (explicit form)
Hard rules
- Read-only. No
Edit, no Write, no mutating Bash ops. The author owns every deletion.
- Tier semantics. Tier 1 = residue to remove; Tier 2 = review needed (a ticket reference may be a legitimate
TODO).
- Code files only. Markdown is
/docs-hygiene:audit-noise's territory and is skipped; a .md target yields no findings here.
- Comment-scoped detection. Only the comment portion of a line is classified. Residue-shaped words in code (identifiers, string literals) are not flagged.
TODO(#issue) is sanctioned. A TODO / FIXME marker tracking real work is never flagged as ticket residue.
- Opt-out markers respected.
comment-residue-ignore on a line (or the line before it) skips it.
- Output deterministic. Filenames sort lexically; findings sort by line number; no timestamps.
Output schema
Per target file:
<file>: N finding(s) — T1=<n>, T2=<n>
| Tier | Shape | Line | Excerpt | Treatment |
|------|-------|------|---------|-----------|
| 1 | history-narration | 42 | "// used to buffer; now flushes" | Delete — version control owns history |
| 1 | conversational-antecedent | 12 | "# as you asked, retry three times" | Delete — invisible to future readers |
| 2 | ticket-pr-residue | 88 | "// see PR #45 for rationale" | Review — delete bare provenance; keep TODO(#issue) |
Batch aggregate at end:
Total: <N> file(s) audited, <T1> Tier 1, <T2> Tier 2 findings.
shape values: history-narration, plan-reference, conversational-antecedent, ticket-pr-residue.
What this skill is NOT
- Not "delete all comments." It targets residue, not comments that carry a non-obvious why or an interface/design-intent contract. Those stay.
- Not
/code-tidying:tidy. tidy APPLIES structural tidyings (including Beck's "Delete Redundant Comment" for comments that restate the code); audit-comment-residue is a read-only CLASSIFIER for the out-of-context residue class. Different concern, different mode.
- Not
/docs-hygiene:audit-noise. /docs-hygiene:audit-noise owns markdown noise; this owns code-comment residue. Neither touches the other's surface.
Next
- The findings are agreed and ready to apply:
/code-tidying:dissolve-comments.
- The surviving comments restate the code rather than narrate its past:
/code-tidying:tidy.
Sources
1---2name: audit-comment-residue3description: Classify code comments for four residue shapes. History narration ("used to… now…"), plan/session references ("Task 2 replaces the old…", "in this PR"), conversational antecedents ("per your request", "as you asked"), and ticket/PR/branch back-references a future reader will never see. Emitting Tier 1 (remove) and Tier 2 (review) findings with treatment guidance; read-only, no edits applied. Use when: 'comment residue', 'audit code comments', 'find stale/narrative comments', 'strip conversational comments', or before committing agent-written code, not for removing ALL comments, restating-the-code redundancy (that is /code-tidying:tidy's Beck tidyings), or markdown noise (use /audit-noise).4---56## Repository context. Gather first78Collect these with **individual** Bash calls, one command per call, never combined into a single9invocation:1011- Current branch, `git branch --show-current`1213Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as14separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute15block as one shell invocation, and a worktree-isolated session refuses a compound command that16contains git. The dated record for that composition claim is the `source-control` plugin's17[worktree/reference/gather-block.md](https://raw.githubusercontent.com/melodic-software/claude-code-plugins/main/plugins/source-control/skills/worktree/reference/gather-block.md),18"The pre-compute block runs as one shell invocation".1920## Pre-computed context2122Uncommitted code files (empty = none matched or the probe returned nothing): !`${CLAUDE_SKILL_DIR}/scripts/changed-code-files.sh 10 2>/dev/null || echo "(git status unavailable)"`23Residue findings (sample): !`${CLAUDE_SKILL_DIR}/scripts/detect.sh 2>/dev/null | grep -E '^(Summary total:|Finding shape:)' | head -20 || echo "none"`2425## Purpose2627Code comments accumulate RESIDUE. Text that only makes sense outside the code's present state:28narration of what the code used to be, references to the plan/session/changeset that produced it,29asides addressed to the requester, and back-references to a ticket, PR, or branch no future reader30will ever open. Version control owns history; the comment describes the present. A comment that only31makes sense inside the chat thread that produced it is dead. This skill is a read-only classifier: it32surfaces candidates with treatment guidance.3334It detects residue on the COMMENT portion of a line only, so a residue-shaped word sitting in an35identifier or string literal is never flagged. The positive question, *does this comment capture36something the code cannot (a non-obvious why, a constraint, an interface/design-intent contract)?*, is left to the author; the shapes below are the comments that fail it.3738## Residue shapes and treatments3940| Shape | What it looks like | Default tier | Treatment |41|---|---|---|---|42| `history-narration` | The comment narrates the code's past: "used to…", "no longer…", "previously", "renamed from X", "we switched from…", "now returns…" | 1 | Delete. Version control owns history. Keep only if the *reason* for the change is a load-bearing constraint, rewritten as present-tense rationale ("must stay ordered because…") |43| `plan-reference` | References a work plan, session, or changeset rather than the code: `"Task 2 replaces the old…"`, `"as planned"`, `"in this PR/commit/refactor"` | 1 | Delete, the plan is not part of the code's meaning. Fold any surviving intent into a present-tense why-comment |44| `conversational-antecedent` | Addresses the requester or the producing conversation: `"per your request"`, `"as you asked"`, `"like you said"`, `"per our discussion"` | 1 | Delete, the conversation is invisible to every future reader |45| `ticket-pr-residue` | Back-reference to a tracker/PR/branch a reader can't follow: `"see PR #45"`, `"from the feature branch"`, `"JIRA-123"` | 2 | Review. Delete a bare provenance reference; a `TODO(#issue)` tracking real outstanding work is the sanctioned exception and is NOT flagged |4647Consumers with their own comment conventions can refine these defaults in their repo's `CLAUDE.md` /48rules; the classifier's shapes and tiers above are the skill's built-in baseline.4950## Action router5152| Action | Args | Behavior |53|---|---|---|54| `<target>` (default, no action keyword) | empty → uncommitted code files from git; file path → single-file; dir path → batch | run `${CLAUDE_SKILL_DIR}/scripts/detect.sh` on targets; map the emitted facts to the per-file tier table using the treatments above |55| `audit [target]` | same target rules | explicit form of the default; same behavior |5657## Auto-detect default58591. Empty arg AND no uncommitted code files → friendly no-op exit 0 ("No uncommitted code files. Pass a file/dir target.")602. Empty arg AND uncommitted code files → batch audit over those files613. Single file path → single-file audit624. Directory path → batch audit (filenames sorted lexically for deterministic output)635. First positional == `audit` → audit on rest (explicit form)6465## Hard rules6667- **Read-only.** No `Edit`, no `Write`, no mutating `Bash` ops. The author owns every deletion.68- **Tier semantics.** Tier 1 = residue to remove; Tier 2 = review needed (a ticket reference may be a legitimate `TODO`).69- **Code files only.** Markdown is `/docs-hygiene:audit-noise`'s territory and is skipped; a `.md` target yields no findings here.70- **Comment-scoped detection.** Only the comment portion of a line is classified. Residue-shaped words in code (identifiers, string literals) are not flagged.71- **`TODO(#issue)` is sanctioned.** A `TODO` / `FIXME` marker tracking real work is never flagged as ticket residue.72- **Opt-out markers respected.** `comment-residue-ignore` on a line (or the line before it) skips it.73- **Output deterministic.** Filenames sort lexically; findings sort by line number; no timestamps.7475## Output schema7677Per target file:7879```text80<file>: N finding(s) — T1=<n>, T2=<n>8182| Tier | Shape | Line | Excerpt | Treatment |83|------|-------|------|---------|-----------|84| 1 | history-narration | 42 | "// used to buffer; now flushes" | Delete — version control owns history |85| 1 | conversational-antecedent | 12 | "# as you asked, retry three times" | Delete — invisible to future readers |86| 2 | ticket-pr-residue | 88 | "// see PR #45 for rationale" | Review — delete bare provenance; keep TODO(#issue) |87```8889Batch aggregate at end:9091```text92Total: <N> file(s) audited, <T1> Tier 1, <T2> Tier 2 findings.93```9495`shape` values: `history-narration`, `plan-reference`, `conversational-antecedent`, `ticket-pr-residue`.9697## What this skill is NOT9899- **Not "delete all comments."** It targets residue, not comments that carry a non-obvious why or an interface/design-intent contract. Those stay.100- **Not `/code-tidying:tidy`.** `tidy` APPLIES structural tidyings (including Beck's "Delete Redundant Comment" for comments that restate the code); `audit-comment-residue` is a read-only CLASSIFIER for the out-of-context residue class. Different concern, different mode.101- **Not `/docs-hygiene:audit-noise`.** `/docs-hygiene:audit-noise` owns markdown noise; this owns code-comment residue. Neither touches the other's surface.102103## Next104105- The findings are agreed and ready to apply: `/code-tidying:dissolve-comments`.106- The surviving comments restate the code rather than narrate its past: `/code-tidying:tidy`.107108## Sources109110- [Ousterhout ⇄ Clean Code debate](https://github.com/johnousterhout/aposd-vs-clean-code). Why the positive rule is "capture what code can't," not "comments are rare"111- [Beck, Delete Redundant Comment](https://newsletter.kentbeck.com/p/delete-redundant-comment), the boy-scout deletion tidying112- [Google eng-practices. Comments explain *why*, not *what*](https://google.github.io/eng-practices/review/reviewer/looking-for.html)113- [Abel, Comments are not Version Control](https://coding.abel.nu/2012/07/comments-are-not-version-control/), history/changelog residue belongs in VCS, not the code