A Claude Code PostToolUse hook that flags genuinely unnecessary code
comments — and, unlike blunt "flag every comment" checkers, spares the
justified ones so the warning is worth listening to.
Built in Rust on tree-sitter (37 grammars, statically linked — no runtime
network, no dynamic loading). A from-scratch, constitution-aligned rewrite of
code-yeongyu/go-claude-code-comment-checker.
A checker that flags every comment trains the AI to dismiss the warning ("this one's justified") — even when it isn't. This checker classifies each comment and only flags the unnecessary ones, with a specific reason the dismissal can't hand-wave:
restates what the code already saysa TODO with no tracked reference — file a ticket or delete itdead code left in a commentdescribes what changed, not why — git history already records this
It spares comments that earn their place: license/SPDX headers, linter and
type-checker directives (# noqa, // @ts-ignore, eslint-disable), BDD
steps (# given/when/then), public-API docstrings (@param/@returns/Args:),
non-obvious intent (// workaround:, // because, // to avoid), attribution,
shebangs, and generated-file notices.
npm install -g @systemfsoftware/claude-code-comment-checkerThe package fetches the prebuilt binary for your platform on install.
Grab the comment-checker-<triple>.tar.gz for your platform from
releases
and put the comment-checker binary on your PATH.
Add to ~/.claude/settings.json (or .claude/settings.json in your project):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{ "type": "command", "command": "comment-checker" }
]
}
]
}
}| code | meaning |
|---|---|
| 0 | pass — no unnecessary comments |
| 2 | block — unnecessary comments detected |
comment-checker --prompt "Your changes: {{comments}}"cargo test --all-targets # unit + property + composition + F1 gate
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo mutants --file src/classify.rs # mutation gate (100% on the core)The evaluation corpus (50 labeled code comments) lives in eval/corpus.json
and is gated by tests/f1.rs; the differential harness (tests/differential.rs)
asserts this checker beats the original by ≥ 10 F1 points (measured 1.000 vs
0.710). A wiki-grounded, position-swapped pairwise judge independently
confirmed the Rust checker is more correct on 18/18 disagreement cases.
The classifier is a pure, branch-free fold over ordered rule tables (CONST-P1,
CONST-P2) and is gated at a 100% mutation score on the core (CONST-T3). Two
CONST-G1 judgment calls are declared, not hidden: the hook boundary fails open
to a single None/empty result rather than tagged error variants (CONST-D2),
because no caller branches on why detection failed — every failure path is
the same deliberate "skip, never block the user"; and line_number is an
unbranded usize (CONST-D3) because it is only ever read for display, so the
transposition harm the rule exists to prevent cannot occur here.
- The hook receives JSON from Claude Code on stdin.
- It extracts the content written by
Write/Edit/MultiEdit. - It detects the language from the file extension and parses it with tree-sitter.
- It walks the tree for comment nodes and classifies each one — the pure core, a branch-free fold over ordered rule tables.
- Justified comments are spared; unnecessary ones are reported with a reason.
MIT.