agentsclimarketplace

Writing docstrings

Skill gg-mo/repo-hygiene/skills/writing-docstrings

Hygiene skills for Claude Code, Codex, Cursor, OpenCode, Gemini, and Copilot — orient, docstring, test, gate commits

Install
npx -y skills add gg-mo/repo-hygiene --skill writing-docstrings

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when writing or modifying any function, method, class, or source file in a repo using repo-hygiene — public API, internal helpers, and new files all require docstrings; only one-line lambdas and trivial accessors are excluded

SKILL.md

4.3 KB, as published. Nobody here has run it

Writing Docstrings

Overview

In a repo using repo-hygiene, docstrings on functions/classes and headers on source files are required. This OVERRIDES the default "no comments unless WHY is non-obvious" stance. The override exists because docstrings ARE the API contract — a future reader (human or agent) shouldn't have to read the body to know what to expect.

Core principle: A docstring earns its place by telling the reader something the signature does NOT tell them.

When To Use

  • Writing a new function, method, or class
  • Modifying a function's signature, return type, or contract
  • Creating a new source file (write a header)
  • Reviewing your own code before commit

What Earns a Docstring Its Place

A good docstring covers what the signature CAN'T:

  1. Contract — one-sentence promise, present tense
  2. Parameters — only those whose meaning isn't obvious from type/name
  3. Returns — only if non-obvious from the return type
  4. Raises / errors — failure modes the caller must handle
  5. Caveats — non-obvious behavior, side effects, performance, thread-safety

Skip anything the signature already conveys. The goal is information, not ceremony.

Before / After

Restates the signature (worthless):

def parse_date(raw: str) -> datetime:
    """Parse a string and return a datetime."""
    return datetime.strptime(raw, "%Y-%m-%d")

Empty ceremony:

def parse_date(raw: str) -> datetime:
    """
    :param raw: the raw string
    :returns: the parsed datetime
    """

Pins what the signature can't:

def parse_date(raw: str) -> datetime:
    """Parse a YYYY-MM-DD date. Raises ValueError on any other format."""
    return datetime.strptime(raw, "%Y-%m-%d")

File Headers

Every source file gets a header explaining its role. A header that just paraphrases the filename is worse than no header.

Paraphrases filename:

"""user_repository.py — the user repository."""

Explains role + boundary:

"""Persistence layer for User aggregates.

Owns reads/writes to the `users` table. Callers should never use raw SQL
against this table — go through this module so audit logs stay consistent.
Domain type lives in domain/user.py.
"""

A good header answers: what does this file own, what's the boundary, who calls it, what's a closely related file?

Narrow Exceptions

These don't need a docstring (the signature IS the spec):

  • One-line lambdas / arrow functions
  • Trivial accessors: def name(self): return self._name
  • Single-expression private helpers under 3 lines

For everything else: if you can't think of a useful one-liner, the function probably does too much or is misnamed. Fix the function before skipping the docstring.

Quick Reference

LanguagePattern
Python"""...""" after def/class; module header at top of file
TypeScript / JavaScriptJSDoc /** ... */ above function/class; top-of-file block
Go// FuncName ... above declaration; // Package x ... at top
Rust/// for items, //! for module-level
JavaJavadoc /** ... */

Mirror the repo's existing convention. If unclear, copy a well-documented file in the same language.

Common Mistakes

MistakeFix
Restating the signature in proseCut. If the signature says it, the docstring is noise.
Documenting every param regardless of clarityOnly the ones whose meaning isn't obvious
File header paraphrases filenameExplain role + boundary + collaborators
"My default is no-comments"This skill OVERRIDES that default. Intentional.
Skipping docs on "internal" helpersInternal becomes public. Document the contract anyway.

Red Flags — STOP

  • "My default is no comments unless WHY is non-obvious" — that default does not apply in repo-hygiene repos
  • About to ship a function with no docstring (outside the narrow exceptions)
  • About to create a new file with no header
  • Writing a docstring that just rephrases the function name — rewrite or you're adding noise

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.