/doc-comments
How to write inline comments, rustdoc, and module documentation in the Biome codebase. The audience is Biome developers reading the source, not end users. Use whenever writing or editing `//` comments, `///` item docs, or `//!` module docs — including comments added incidentally
$ npx -y skills add biomejs/biome --skill doc-comments --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/doc-comments
Context preview
The summary Claude sees to decide when to auto-load this skill.
How to write inline comments, rustdoc, and module documentation in the Biome codebase. The audience is Biome developers reading the source, not end users. Use whenever writing or editing `//` comments, `///` item docs, or `//!` module docs — including comments added incidentally
SKILL.md
doc-comments.SKILL.mdname: doc-comments
description: How to write inline comments, rustdoc, and module documentation in the Biome codebase. The audience is Biome developers reading the source, not end users. Use whenever writing or editing `//` comments, `///` item docs, or `//!` module docs — including comments added incidentally while fixing bugs or implementing features.
compatibility: Designed for coding agents working on the Biome codebase (github.com/biomejs/biome).
Purpose
Comments and doc comments in this repository are read by contributors, months or years after they were written, with none of the context you have right now. This skill defines who that reader is, what each kind of comment is for, and which patterns are banned.
**Scope boundary:** rustdoc inside `declare_lint_rule!` / `declare_assist_rule!` blocks is end-user documentation — it is generated into the website. This skill does not apply there; see [lint-rule-development](../lint-rule-development/SKILL.md).
The Reader
Write for a Biome contributor who is competent in Rust but has **no access to your current context**: not this conversation, not the pull request, not the issue, not the diff. They see only the repository at HEAD.
Two consequences follow directly:
1. **Never narrate change history.** Words like "now", "previously", "no longer", "the new approach" are meaningless at HEAD, where only one approach exists. State how the code works, not how it came to be. 2. **Never address the reviewer.** A comment that argues your change is correct ("this properly handles X") belongs in the PR description, not in the source. The comment must justify the code as it stands, permanently.
Three Kinds of Documentation, Three Different Jobs
| Kind | Job | Contains | | ---- | --- | -------- | | `//!` module docs | Explanation | Why the module exists, core concepts and terminology, how the pieces relate, design rationale | | `///` item docs | Reference | The contract: behavior, inputs and outputs, invariants, panics, errors. Neutral and factual | | `//` inline comments | Rationale | Only what the code cannot say: constraints, workarounds (with issue links), non-obvious coupling, why the obvious alternative is wrong |
Do not mix the jobs. Implementation details do not belong in `///` docs — put them as `//` comments inside the body. The contract does not belong scattered across inline comments — put it on the item.
The Deletion Test
Before writing any comment, ask: **does this state something the reader cannot recover from the code itself?**
- If the information is already carried by names, types, or structure, do not
write the comment. If the name fails to carry it, improve the name.
- Information that legitimately needs a comment: an invariant, a rationale, a
coupling to code elsewhere, a workaround with a link, surprising behavior of a dependency, a term of art the module defines.
When editing later, the same test applies in reverse: a comment that no longer passes it should be deleted, not left to rot.
Behavior Documentation
Write documentation for a human reader, not as a translation of the implementation.
- Start with a plain-language description of what the function returns or
accomplishes.
- Use short or medium-length sentences. Keep one main idea per sentence.
- Avoid internal jargon. If a technical term is necessary, explain what it means
in the same paragraph.
- Describe business-logic caveats that can surprise callers. Examples include
fallback behavior, work limits, ambiguous results, overload ordering, and conditions that return `None`, `Unknown`, or an indeterminate result.
- Do not describe implementation details unless callers need them to understand
the behavior.
Add an example when the behavior depends on relationships that the function signature cannot show clearly. Common cases include:
- overload selection;
- mapping arguments to optional or rest parameters;
- following imports or re-exports across files;
- fallback behavior for ambiguous or incomplete information;
- a result whose meaning is not obvious from its type.
Introduce the example before the code block. State what the example demonstrates and what result is expected.
Keep snippets minimal and self-contained.
Module documentation should describe a durable concept or design reason. Do not list individual functions or queries merely to summarize the file. Such lists become stale as items are added or renamed. If the module has no durable concept to explain, use a brief one-line description.
Banned Patterns
**Narrating the next line.** Delete these on sight:
// Increment the generation counter
generation += 1;
**Change-history narration.** Rewrite as present-tense rationale:
// BAD: We now intern types instead of cloning them.
// GOOD: Interning avoids cloning these types on every lookup.
**Reviewer-addressed justification.** Move the argument to the PR:
// BAD: This correctly handles the overload case from the bug report.
// GOOD: Overloads are matched by arity before parameter types, so a
// partial-arity call cannot select the wrong candidate.
**Restated rustdoc.** A `///` doc that rewords the item name says nothing:
// BAD:
/// Handles the type inference.
fn infer_types(...)
// GOOD:
/// Infers the type of `expr` in the scope of `module`, returning
/// `TypeData::Unknown` when the expression references an unresolved import.
fn infer_types(...)
**Vague hedging.** "Some cases", "various reasons", "handles edge cases", "etc." — either name them or drop the sentence.
**Ad-hoc section banners** (`// ----- helpers -----`, `// ==== TYPES ====`). For grouping in long files, use the region comment pattern below instead.
Region Comments
Long files group related items with paired region markers:
// #region FILE-LEVEL METHODS
...
// #endregion
This is an established convention across the codebase (`biome_service`, `biome_mod
Read more
name: doc-comments description: How to write inline comments, rustdoc, and module documentation in the Biome codebase. The audience is Biome developers reading the source, not end users. Use whenever writing or editing `//` comments, `///` item docs, or `//!` module docs — including comments added incidentally while fixing bugs or implementing features. compatibility: Designed for coding agents working on the Biome codebase (github.com/biomejs/biome).
Purpose
Comments and doc comments in this repository are read by contributors, months or years after they were written, with none of the context you have right now. This skill defines who that reader is, what each kind of comment is for, and which patterns are banned.
**Scope boundary:** rustdoc inside `declare_lint_rule!` / `declare_assist_rule!` blocks is end-user documentation — it is generated into the website. This skill does not apply there; see [lint-rule-development](../lint-rule-development/SKILL.md).
The Reader
Write for a Biome contributor who is competent in Rust but has **no access to your current context**: not this conversation, not the pull request, not the issue, not the diff. They see only the repository at HEAD.
Two consequences follow directly:
1. **Never narrate change history.** Words like "now", "previously", "no longer", "the new approach" are meaningless at HEAD, where only one approach exists. State how the code works, not how it came to be. 2. **Never address the reviewer.** A comment that argues your change is correct ("this properly handles X") belongs in the PR description, not in the source. The comment must justify the code as it stands, permanently.
Three Kinds of Documentation, Three Different Jobs
| Kind | Job | Contains | | ---- | --- | -------- | | `//!` module docs | Explanation | Why the module exists, core concepts and terminology, how the pieces relate, design rationale | | `///` item docs | Reference | The contract: behavior, inputs and outputs, invariants, panics, errors. Neutral and factual | | `//` inline comments | Rationale | Only what the code cannot say: constraints, workarounds (with issue links), non-obvious coupling, why the obvious alternative is wrong |
Do not mix the jobs. Implementation details do not belong in `///` docs — put them as `//` comments inside the body. The contract does not belong scattered across inline comments — put it on the item.
The Deletion Test
Before writing any comment, ask: **does this state something the reader cannot recover from the code itself?**
- If the information is already carried by names, types, or structure, do not
write the comment. If the name fails to carry it, improve the name.
- Information that legitimately needs a comment: an invariant, a rationale, a
coupling to code elsewhere, a workaround with a link, surprising behavior of a dependency, a term of art the module defines.
When editing later, the same test applies in reverse: a comment that no longer passes it should be deleted, not left to rot.
Behavior Documentation
Write documentation for a human reader, not as a translation of the implementation.
- Start with a plain-language description of what the function returns or
accomplishes.
- Use short or medium-length sentences. Keep one main idea per sentence.
- Avoid internal jargon. If a technical term is necessary, explain what it means
in the same paragraph.
- Describe business-logic caveats that can surprise callers. Examples include
fallback behavior, work limits, ambiguous results, overload ordering, and conditions that return `None`, `Unknown`, or an indeterminate result.
- Do not describe implementation details unless callers need them to understand
the behavior.
Add an example when the behavior depends on relationships that the function signature cannot show clearly. Common cases include:
- overload selection;
- mapping arguments to optional or rest parameters;
- following imports or re-exports across files;
- fallback behavior for ambiguous or incomplete information;
- a result whose meaning is not obvious from its type.
Introduce the example before the code block. State what the example demonstrates and what result is expected.
Keep snippets minimal and self-contained.
Module documentation should describe a durable concept or design reason. Do not list individual functions or queries merely to summarize the file. Such lists become stale as items are added or renamed. If the module has no durable concept to explain, use a brief one-line description.
Banned Patterns
**Narrating the next line.** Delete these on sight:
// Increment the generation counter generation += 1;
**Change-history narration.** Rewrite as present-tense rationale:
// BAD: We now intern types instead of cloning them. // GOOD: Interning avoids cloning these types on every lookup.
**Reviewer-addressed justification.** Move the argument to the PR:
// BAD: This correctly handles the overload case from the bug report. // GOOD: Overloads are matched by arity before parameter types, so a // partial-arity call cannot select the wrong candidate.
**Restated rustdoc.** A `///` doc that rewords the item name says nothing:
// BAD: /// Handles the type inference. fn infer_types(...) // GOOD: /// Infers the type of `expr` in the scope of `module`, returning /// `TypeData::Unknown` when the expression references an unresolved import. fn infer_types(...)
**Vague hedging.** "Some cases", "various reasons", "handles edge cases", "etc." — either name them or drop the sentence.
**Ad-hoc section banners** (`// ----- helpers -----`, `// ==== TYPES ====`). For grouping in long files, use the region comment pattern below instead.
Region Comments
Long files group related items with paired region markers:
// #region FILE-LEVEL METHODS ... // #endregion
This is an established convention across the codebase (`biome_service`, `biome_mod
A toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.
Repo: biomejs/biome
Other skills on biome.
- /biome-code-review
Static, read-only code review of a Biome (github.com/biomejs/biome) pull request, local branch, commit range, diff, or working tree being prepared as a PR. Applies Biome's own conventions - nursery placement and naming for lint rules, diagnostics quality, allocation and borrow
Open skill - /biome-developer
General development best practices and common gotchas when working on Biome. Use for avoiding common mistakes, understanding Biome-specific patterns (AST, syntax nodes, string extraction, embedded languages), and learning technical tips.
Open skill - /changeset
Guide for creating and writing proper changesets for Biome PRs. Use when a PR introduces user-visible changes (bug fixes, new features, rule changes, formatter changes, parser changes) that need a changeset entry for the CHANGELOG. Trigger when creating changesets, writing
Open skill - /diagnostics-development
Guide for creating high-quality, user-friendly diagnostics in Biome. Use when creating diagnostics for lint rules, adding helpful advice to error messages, implementing code frame displays, or improving diagnostic quality.
Open skill - /eslint-migrate-options
Guide for implementing ESLint-to-Biome rule option migrators inside `biome migrate eslint`. Use whenever you add or update a Biome lint rule that has an ESLint source rule with configurable options, need to deserialize plugin-specific ESLint options, or need custom migration
Open skill - /formatter-development
Guide for implementing formatting rules using Biome's IR-based formatter infrastructure. Use when implementing formatting for new syntax nodes, handling comments in formatted output, writing or debugging formatter snapshot tests, diagnosing idempotency failures, or comparing
Open skill

