Code Comments skill for Codex
Keep the why, delete the what. Codex comments only what the code cannot say for itself: rejected alternatives, hidden constraints, workarounds with links, and API contracts covering errors and side effects. During cleanup it checks each comment against the code and git history, deletes narration and commented-out code, fixes comments that lie, and keeps comment-only changes in their own commit.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- code-comments Installs to ~/.agents/skills/code-comments/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install code-comments The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project code-comments Installs to .agents/skills/code-comments/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/code-comments.zipunzip -o code-comments.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) code-comments PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $code-comments, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Decides when a comment earns its place and writes the ones that do - why-comments for non-obvious decisions, constraints and workarounds with links, API contracts in docstrings or JSDoc, tagged TODOs with an owner and ticket - while deleting comments that restate code, contradict it, or hold commented-out code. Use when asked to comment or document a function, clean up or review comments, explain tricky code inline, add JSDoc or docstrings to a public API, remove stale or misleading comments, or set a team policy for TODO and FIXME.
Use it when
- Code has noisy, outdated or misleading comments
- Public functions need documented contracts
- A tricky decision or workaround needs explaining inline
- The team wants a TODO and FIXME policy that can be enforced
Use something else when
- You are writing a full docstring style guide for a Python package: use docstrings
- You need prose documentation outside the code: use technical-writing
How to check the result
Every remaining comment matches the current code, doc lint or docs build passes if the project has one, and the comment-only commit has no behaviour change.
The mistake it prevents
Changing code but leaving the old comment above it, so readers trust a description of behaviour that no longer exists.
A comment is worth keeping when it tells the reader something the code cannot: why this approach, what constraint forced it, what will break if you change it, or how to use an API without reading its body. Comments that narrate the code are noise and rot into lies. After your pass, every remaining comment is true, necessary and local to what it explains.
Before writing or deleting
- Read
AGENTS.mdand the linter config for the project’s rules (docstring style, JSDoc requirements, TODO format, language of comments). - Match the existing docstring convention: Google, NumPy or reST style in Python; TSDoc or
JSDoc in TypeScript; godoc sentences in Go;
///doc comments in Rust. - Check whether docs are generated from comments (Sphinx, TypeDoc, rustdoc, godoc). Then doc comments are public documentation and need the same care as a README.
What to write, by kind
| Kind | Write it when | Form |
|---|---|---|
| Why-comment | The obvious approach was rejected, or a constraint is invisible in the code | 1-3 lines above the code, ending with a link if one exists |
| Warning | Changing this has a non-local effect (ordering, locking, performance cliff, external contract) | Start with the consequence |
| Workaround | Code exists only because of a bug elsewhere | Name the bug, link the issue, say when to remove it |
| API doc (docstring / JSDoc) | Public or widely used function, class, module | Contract: purpose, params, return, errors, side effects, example |
| Intent summary | A block of 15+ lines does one conceptual step that cannot be extracted yet | One line naming the step |
| TODO / FIXME | Known gap you are deliberately leaving | Tagged with owner or ticket, never bare |
| Legal / license header | Project or license requires it | Exactly the required text |
What not to write:
- Restating the code:
i += 1 # increment i. - Change history or authorship: that is what
git logandgit blameare for. - Commented-out code: delete it; git keeps it.
- Explanations that a better name or an extracted function would make unnecessary. Rename first (see naming-conventions), comment only what remains non-obvious.
- Section banners in short files (
// ======== HELPERS ========).
Examples
Why-comment and workaround:
# Sort before deduplicating: the upstream API returns the newest record last, and we
# must keep the newest. A set() would keep an arbitrary one.
records.sort(key=lambda r: r.updated_at)
# Workaround for psycopg issue #712: server-side cursors leak when the generator is
# not exhausted. Remove once we are on psycopg >= 3.3.
with conn.cursor(name="export") as cur:
...
Warning that leads with the consequence:
// Do not reorder: Close must run after Flush, or the last partial block is lost
// and the file fails checksum verification on read.
defer w.Close()
defer w.Flush()
(Deferred calls run last-in, first-out, so Flush runs before Close here; the comment
saves the next reader from “fixing” the order.)
API contract in TSDoc:
/**
* Reserves stock for an order. Idempotent per `orderId`: repeated calls return the
* existing reservation instead of reserving twice.
*
* @param orderId - Order to reserve for; must already exist.
* @param lines - Items and quantities; quantities must be positive integers.
* @returns The reservation, including expiry (15 minutes from first call).
* @throws {@link InsufficientStockError} if any line cannot be fully reserved;
* nothing is reserved in that case.
*/
export async function reserveStock(orderId: string, lines: OrderLine[]): Promise<Reservation>
Python docstring (Google style) for the same kind of contract:
def reserve_stock(order_id: str, lines: list[OrderLine]) -> Reservation:
"""Reserve stock for an order, idempotently per order_id.
Args:
order_id: Order to reserve for; must already exist.
lines: Items and positive integer quantities.
Returns:
The reservation, expiring 15 minutes after the first call.
Raises:
InsufficientStockError: If any line cannot be fully reserved. Nothing is
reserved in that case.
"""
Document the contract (inputs, outputs, errors, side effects, idempotency, thread safety), not the implementation. Do not repeat type information the signature already carries.
TODO policy
Bare TODOs are never done. Require a format the team can search and lint:
TODO(#4821): remove legacy CSV path after all tenants migrate (target 2026-Q2)
FIXME(@dana): race when two workers claim the same job; see #4790
rg -n "\b(TODO|FIXME|HACK|XXX)\b" --glob '!vendor/**' # inventory
rg -n "\b(TODO|FIXME)\b(?!\()" -P # untagged ones
Do not add a TODO for work you could finish in this change. Do not invent ticket numbers; ask the user for one, or write the TODO with an owner only.
Cleanup workflow
- [ ] 1. Inventory: TODOs, commented-out code, long comment blocks in the target files
- [ ] 2. For each comment: is it true? Check against the code and git history
- [ ] 3. Delete restating comments and commented-out code
- [ ] 4. Fix comments that are wrong; if unsure what is right, ask instead of guessing
- [ ] 5. Replace "what" comments with better names or extracted functions where cheap
- [ ] 6. Add missing why-comments and API docs on public surfaces
- [ ] 7. Keep comment-only changes in their own commit, separate from behaviour changes
Find commented-out code candidates:
rg -n "^\s*(//|#)\s*(if|for|return|const|let|var|def|import|from|func|print|console\.)\b"
Use git log -L <start>,<end>:<file> or git blame to learn why a puzzling block exists
before writing the why-comment; the commit message often contains the answer.
Gotchas
- A wrong comment is worse than none: readers trust it over the code. When you change code, update or delete every comment that describes it in the same commit.
- Docstrings that describe parameters that no longer exist fail silently; enable the
checker if one exists (ruff
Drules pluspydoclint,eslint-plugin-jsdoc,cargo docwarnings). Go has no built-in checker for doc comment content, so review godoc by hand. - Comments explaining a regex or bit manipulation are often warranted; one example input and output is worth a paragraph.
- Generated files carry
DO NOT EDITheaders; never “clean up” their comments. - Comments in a language other than the codebase’s convention fragment the team; follow
AGENTS.md.
Output
When asked to clean up or add comments, report:
**Files:** src/orders/*.ts (6)
**Removed:** 23 restating comments, 4 blocks of commented-out code (git has them)
**Corrected:** 2 comments that contradicted code (pricing.ts:88 described old rounding)
**Added:** TSDoc on 5 exported functions; 3 why-comments (links to #4790, #4821)
**Untagged TODOs:** 6 - need owners or tickets from you
Verification
- Every remaining comment was checked against current code.
- Docs build or doc lint passes (TypeDoc, Sphinx,
cargo doc, ruffDrules) if the project uses one. - The diff contains no behaviour change: tests pass and, for a comment-only commit, the non-comment diff is empty.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Code Comments"
short_description: "Keep the why, delete the what"
default_prompt: "$code-comments Clean up the comments in src/orders - remove noise and fix anything that is wrong" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.