doc-comments
Skill1 starsChanged 57 days agoMITView on GitHub
Writes and audits in-source API doc comments — JSDoc, TSDoc, XML docs, docstrings, rustdoc, godoc, KDoc — so each one carries the contract the signature cannot. Use when documenting a public member, backfilling doc comments across a codebase, or reviewing existing ones, or when the user says "document this API", "add JSDoc", "add XML docs", "write docstrings", "review these doc comments".
2 other projects use a version of this.
Adopted by
Most recently taken up by
- microsoft/vscodetheir own version, first seen Nov 12, 2026
- biomejs/biometheir own version, first seen Oct 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- microsoft/vscode★ 195ksame name
- biomejs/biome★ 26ksame name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository47 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- bump-versionsSkill
- obsolete-skillSkill
- prefer-direct-statementsSkill
- prefer-official-docsSkill
- prefer-skillsSkill
- extract-llms-txtSkill
- init-agent-docsSkill
- maintain-agent-docsSkill
- retroSkill
- tanstack-data-loadingSkill
- customize-skillSkill
- writing-skillsSkill
- cte-modeSkill
- eli10-modeSkill
- example-drivenSkill
- plain-languageSkill
- simplified-technical-englishSkill
- ghost-writingSkill
- break-down-prdSkill
- draft-a-prdSkill
- from-first-principlesSkill
- round-tableSkill
- deep-researchSkill
- get-alignedSkill
- picking-modelsSkill
- todoSkill
- transcribe-videoSkill
- using-subagentsSkill
- using-teamsSkill
- visualiseSkill
- promptingSkill
- biome-pluginsSkill
- hardenSkill
- testing-principlesSkill
- devils-advocateSkill
- rubber-duckSkill
- steelmanSkill
- ddd-modular-monolithSkill
- module-designSkill
- ubiquitous-languageSkill
- wutSkill
- writing-for-agentsSkill
- writing-for-humansSkill
- design-calloutsSkill
- design-dashboardsSkill
- prune-local-branchesSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 31
No comment beats a restated one: When you cannot say more than the member's name already says, the member is either self-evident — leave it …
- Very specific: line 51
Keep the summary to that one sentence and push the rest below it — into the dialect's dedicated slot for extended detail where one exists, …
- Very specific: line 66
Never put true or false in code font or quotation marks in these slots.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
A doc comment earns its place only if it says something the signature does not. The reflex to fill every slot produces the dominant failure: @param userId The user ID. — a line that costs a read, satisfies the linter, blocks the "undocumented" warning that would have flagged the gap, and tells the caller nothing. The signature already carries names, types, arity, and nullability. The comment's job is the contract around them.
This holds identically when writing new comments and when auditing existing ones. Auditing is the same rules applied to text already on the page.
Match the codebase's dialect — tag vocabulary, tag ordering, whether it links members by reference or inherits docs from a base type. House convention outranks the wording and formatting rules below; it does not override the coverage rules, which decide what gets documented at all. Dialects also differ in what they enforce — one warns on a missing tag, another accepts any well-formed comment — so the bar for a finished comment is the rules below, not what the linter lets through. At low and mid, take the dialect from the comments already in the target file; at high, read neighbouring files in the same module.
Route by effort
--effort sets how far out from the member to read. Levels are cumulative — each includes every level below it. Absent, the level is mid.
| Level | Reading radius |
low | The member: its signature and its own body |
mid | Adds its dependencies: the helpers it calls, the types it constructs or mutates |
high | Adds its neighbourhood: sibling members, base types, call sites, neighbouring files |
Effort never narrows coverage: the whole public surface of the target is documented at every level. What changes is which contract items are knowable — each is tagged mid or high below where it needs a radius wider than the member itself — and how deeply an audit verifies a claim before passing it. A claim an audit could not check within its radius is reported as unverified, never as clean.
Coverage
Decide what gets a comment before deciding how to word one.
- Document the whole public surface — every exported or public type, method, property, constant, event, and enum member, along with its parameters, return value, and thrown errors. A public member is a promise to someone who cannot read the implementation.
- Leave internals alone. Private and internal members get no doc comment, and do not fall back to an ordinary implementation comment either. Code that needs prose to be understood should be renamed, split, or restructured until it does not, and an invariant worth stating is worth enforcing — in the type system, a guard clause, or a test.
- No comment beats a restated one. When you cannot say more than the member's name already says, the member is either self-evident — leave it bare — or badly named. Renaming is the better fix.
- Never bulk-generate doc comments to clear a linter. The result is uniform noise that hides the members which genuinely needed explaining.
The summary sentence
Documentation generators index the first sentence alone. It has to stand by itself.
Open with a verb in present tense, third person, and do not repeat the member's own name or lead with "This method". The verb form follows the member's kind:
| Member kind | Opening |
| Performs an action or returns data | Adds…, Sends…, Parses… |
| Getter returning a boolean | Checks whether… |
| Getter returning anything else | Gets the… |
| Returns nothing | Sets…, Updates…, Deletes…, Registers… |
| Constructor | Creates a… |
| Callback or handler | Called by… |
Keep the sentence free of anything that renders as a mid-sentence period — write "for example", not "e.g." — because generators truncate the summary at the first period. Put API names, members, and constants in code font; put string literals in code font with double quotation marks. Pluralise the noun, not the type name: "Intent objects", not "Intents".
Keep the summary to that one sentence and push the rest below it — into the dialect's dedicated slot for extended detail where one exists, such as <remarks>, and into following paragraphs or a usage example where it does not.
Deprecations name the replacement in the first sentence. Reasons and migration steps follow in later sentences.
Slots
Each tagged slot has a fixed shape. Capitalise the first word and end with a period.
- Non-boolean parameter — begin with "The" or "A", and say what the value does to the result rather than what it is:
The maximum number of retries before the call fails., neverThe retry count.The name and type already carry its identity; the description is the only slot its effect fits in. - Boolean parameter driving an action —
If true, retries the request. If false, fails immediately. - Boolean parameter describing a state —
True if the account is locked; false otherwise. - Return value — begin with "The" for non-booleans; use
True if…; false otherwise.for booleans. Keep it short and push the detail up to the type's own comment. - Defaults — state them explicitly as
Default: 30 seconds.A default that lives only in the code is invisible to the caller reading generated docs. - Thrown errors — begin with "If" where the generator inserts the word "Throws" itself; begin with "Thrown when" where it does not. Check which by looking at how the codebase's existing comments render. Errors the member raises itself are in play at
low; errors it only propagates from what it calls are mid.
Never put true or false in code font or quotation marks in these slots.
Cross-references
Point at another member through the dialect's reference form — <see cref>, {@link}, a rustdoc intra-doc link — rather than naming it in plain prose. The reference form renders as a working link and gives a later rename some chance of being caught.
Only some chance. A few linters fail the build on a reference that no longer resolves; the rest render the stale name as text and stay silent. Confirm every target resolves as you write it, and in an audit treat a cross-reference as a claim to check against the code like any other — never as something the linter already proved.
What the signature cannot say
This is the payload. A comment that covers the slots and stops has documented the shape and skipped the contract. Work through what the type system leaves unsaid and state whatever applies within the current radius.
- Units, ranges, and formats the type does not encode — milliseconds against seconds, inclusive against exclusive bounds, the accepted shape of a string.
- Side effects — mutated arguments, written files, emitted events, cleared caches. Those the member performs directly are in play at
low; those reached through what it calls are mid. - Failure behaviour (mid) — which errors surface, and whether a failed operation leaves partial work behind. Whether partial work survives a failure is a property of the whole call chain, not of the member's own body.
- Why a caller picks this member (high) over the similarly-named one beside it.
- Preconditions and call order (high) — what must already be true, what must be called first.
- Ownership and lifetime (high) — who disposes the result; whether a returned collection is a live view or a copy.
- Concurrency (high) — thread safety, reentrancy, whether the call blocks.
- Cost (high) — complexity or network round trips, where a caller would be surprised.
At high, add a short usage example on a type or on a member whose correct use is not obvious from its signature.
Register
writing-for-humans carries the register these comments are written in — literal never figurative, plain language outside exact identifiers, the dead-metaphor test, no throat-clearing. Apply it in full. It ships in the same plugin as this skill — /plugin install technical-writing-skills@draekien-skills, or npx skills add draekien/skills --skill "writing-for-humans".
Four things are specific to a doc comment and are not in that skill:
- The reader is inside a tooltip, often in a second language, mid-keystroke. Sentences run shorter here than in a guide, and a paragraph that would be fine in a README is already too long.
- Address the caller directly — "Call this after the connection opens", not "the user should call this".
- Define a domain term once, on the type that owns it, and use it unchanged on every member that touches it. A term redefined on each member drifts into two meanings.
- Cut throat-clearing to reach the verb. "This function is a helper that validates…" becomes "Validates…", because the generator indexes the first sentence and the verb has to be in it.
Audit failure modes
Name these on sight and replace each with a corrected comment rather than deleting it, unless the member is internal. Every mode is detectable from the member alone, so all are in play at every level; what widens with effort is how far a claim is traced before it passes.
- Stale — describes behaviour the code no longer has, documents a parameter that is gone, or promises an error the code stopped raising. The most damaging mode, because it is trusted. Verify every claim against the implementation, not against the comment's plausibility.
- Restated signature — the comment paraphrases names and types and adds nothing.
- Buried summary — the first sentence carries background, so the generated index shows nothing useful.
- Undocumented failure — the member throws, returns null, or partially succeeds, and the comment is silent.
- Copy-paste drift — cloned from a sibling member and still naming the sibling's arguments or behaviour.
- Throat-clearing — "This method is used to…" ahead of the actual verb.
- Figurative — metaphor, personification, or flourish standing where a literal statement of behaviour belongs.
- Dangling reference — points at a member that has been renamed or removed, and nothing flagged it.
- Documented internals — doc comments on private members, diluting the real surface.
Done
Every public member in the target is accounted for: documented against the rules in play, or explicitly judged outside the public surface. Every documented member's contract claims — errors, side effects, defaults, units — are checked against the implementation as far as the current radius reaches, and any claim that could not be checked within it is reported as unverified. In an audit, every finding is named with its failure mode and carries the replacement text.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

