code-comment-generator
Code Comment Generator
Good comments explain why, not what. The code already says what. If you're narrating the code, delete the comment and make the code clearer instead.
What deserves a comment
| Worth commenting | Why |
|---|---|
| A non-obvious constraint the code depends on | "x is sorted here because caller guarantees it" |
| A tradeoff that was made deliberately | "O(n²) is fine — n ≤ 20 by construction" |
| Why the obvious approach is wrong | "Can't use .sort() — caller holds references into this list" |
| A workaround for an external bug | "libfoo 2.3 returns NULL here; remove when we upgrade" |
| Magic numbers with a source | "15s — AWS Lambda cold start p99 + margin" |
| Coupling to something far away | "Must match the regex in nginx.conf" |
| A subtle correctness argument | "Safe to read without lock: only written at startup" |
What does NOT deserve a comment
| Skip | Why |
|---|---|
i++ // increment i |
The code says that. Noise. |
// loop over items above for item in items: |
Same. |
| Restating the function name in a docstring | def save_user(): """Saves user.""" — waste. |
| Commented-out code | That's what git is for. Delete it. |
// TODO: fix this later |
Unactionable. TODO: what and why not now? |
| Comments that will rot | "Called from foo.py:42" — until foo.py changes. |
The test: does this survive a rename?
If you rename all the variables and the comment still makes sense, it's a good comment (explains intent). If the comment is now wrong, it was restating the code.
# BEFORE rename
x = compute_total(items)
# Store the total ← restating. Bad.
# AFTER rename test
q = compute_total(items)
# Store the total ← now the comment is confusing. It was bad.
vs.
# Compute total before filtering — downstream needs the pre-filter sum for the audit log.
x = compute_total(items)
items = [i for i in items if i.active]
Rename x → comment still explains why the ordering matters. Good.
Worked example
Uncommented code:
def reconnect(self):
delay = 0.1
for attempt in range(8):
try:
self._connect()
return
except ConnectionError:
time.sleep(delay + random.uniform(0, delay))
delay = min(delay * 2, 5.0)
raise ConnectionError("exhausted retries")
What the code already says: retries 8 times, exponential backoff, cap at 5s, jitter. Don't comment any of that.
What's not obvious:
def reconnect(self):
# Full jitter would be random.uniform(0, delay), but that occasionally
# produces near-zero sleeps that hammer the server. Half-jitter (delay + uniform(0, delay))
# guarantees at least `delay` between attempts — gentler on the remote.
delay = 0.1
for attempt in range(8): # 8 attempts × max 10s each ≈ 80s worst case — under the 90s LB timeout
try:
self._connect()
return
except ConnectionError:
time.sleep(delay + random.uniform(0, delay))
delay = min(delay * 2, 5.0)
raise ConnectionError("exhausted retries")
Two comments. The first explains a non-obvious design choice (why half-jitter, not full-jitter). The second explains a magic number in terms of an external constraint (LB timeout).
Docstrings — the API contract
Docstrings are a different animal: they're for callers, not maintainers. They should state:
- What the function does (one line)
- Parameter constraints (types, ranges, nullability)
- Return value meaning (including sentinel values)
- Exceptions raised and when
- Side effects (mutation, I/O)
They should NOT describe the implementation. If the implementation changes but the contract doesn't, the docstring shouldn't need updating.
Do not
- Do not write
// increment counterabovecounter++. Ever. - Do not explain what a standard idiom does.
# list comprehensionabove a list comprehension — the reader knows Python or they don't; the comment won't help either way. - Do not leave
TODOwithout a what and a why-not-now.TODO(#1234): remove this shim once libfoo 3.0 ships (expected Q2)is actionable.TODO: fixis not. - Do not write comments that reference line numbers or file paths elsewhere. They rot immediately. Reference concepts, not locations.
- Do not add a comment when the fix is to rename a variable.
x = get_total() # x is the total→ justtotal = get_total().
Output format
For each comment proposed:
## <file:line>
### Current code
<snippet>
### Proposed comment
<the comment>
### Why this comment
<what non-obvious thing it explains — constraint, tradeoff, coupling, workaround>
### Not commenting
<things in this snippet that looked comment-worthy but aren't — the code says it>
More from santosomar/general-secure-coding-agent-skills
code-review-assistant
Performs structured code review on a diff or file set, producing inline comments with severity levels and a summary. Checks correctness, error handling, security, and maintainability — in that priority order. Use when reviewing a pull request, when the user asks for a code review, when preparing code for merge, or when a second opinion is needed on a change.
15dependency-resolver
Diagnoses and resolves package dependency conflicts — version mismatches, diamond dependencies, cycles — across npm, pip, Maven, Cargo, and similar ecosystems. Use when install fails with a resolution error, when two packages require incompatible versions of a third, or when upgrading one dependency breaks another.
4configuration-generator
Generates configuration files for services and tools (app config, logging config, linter config, database config) from a brief description of desired behavior, matching the target format's idioms. Use when bootstrapping a new service, when the user asks for a config file for a specific tool, or when translating config intent between formats.
3ci-pipeline-synthesizer
Generates CI pipeline configs by analyzing a repo's structure, language, and build needs — GitHub Actions, GitLab CI, or other platforms. Use when bootstrapping CI for a new repo, when porting from one CI to another, when the user asks for a pipeline that builds and tests their project, or when wiring in security gates.
3api-design-assistant
Reviews and designs API contracts — function signatures, REST endpoints, library interfaces — for usability, evolvability, and the principle of least surprise. Use when designing a new public interface, when reviewing an API PR, when the user asks whether a signature is well-designed, or when planning a breaking change.
2code-refactoring-assistant
Executes refactorings — extract method, inline, rename, move — in small, behavior-preserving steps with a test between each. Use when the user wants to restructure working code, when cleaning up after a feature lands, or when a smell has been identified and needs fixing.
2