How I Write Software Docs

How I write software docs

The principles I keep reaching for whenever I write docs for a dev tool or an app. Written down so I don't have to rediscover them on every project.

The full canonical version lives in docs/guides/writing-docs.md in the Mxr repo. This page is the vault hub — the principles distilled, with links to atomic concept notes for each one.

The anti-goal

No reader should finish a doc and think "I get what this is, but I don't know how to make it useful."

That's it. Every other rule I keep is a tactic in service of this. See Operationally Useful Docs for the deletion test that catches violations.

The seven principles

1. Every section ends with something runnable

For a CLI: a real mxr invocation that produces real output. For an app: a screenshot of the actual UI flow, with the relevant button labelled. Description without action is the failure mode.

If a section still teaches something useful after deleting every code block, the section is mislabeled. See Operationally Useful Docs.

2. Document every shipped surface

If it ships, it has a doc page. Every command, every flag, every config key, every event type, every keybinding. The discipline only holds if it's mechanical — make CI enforce it. See Document Every Shipped Surface.

3. Recipes solve goals, not restate reference

Anything composable gets a recipe section. A real recipe = problem statement + smallest pipeline + output shape. Filler recipes restate --help; real ones solve a job. See A Recipe Solves a Goal.

4. One Diátaxis quadrant per page

Tutorial, how-to, reference, or explanation — pick one. Mode-mixing is a review-blocker. A quickstart that detours into architecture is broken; a reference page that opens with rationale is broken. See Diátaxis Quadrants.

5. Voice: command first, explanation second

Second person, imperative. Show before tell. No "click here," no "see above." Placeholders paired with real values. Inline code for code things. Tighter than article voice. See Command First, Explanation Second.

6. Generate reference from the source of truth

Hand-edited reference pages rot the moment a flag changes. Generate them from the code, snapshot them in CI, fail the build on drift. Authors keep the parts that take judgment (the "when to use it" line, the three to four examples); the generator handles the boring mechanical part. See Generated Docs as Drift Defense.

7. Mutations are documented dry-run first

Every mutating example shows --dry-run before --yes. Copy-paste habits absorb the discipline. The doc convention mirrors the runtime contract. See Mutations Documented Dry-Run First.

8. Lock the decisions that get relitigated

For docs aimed at maintainers and contributors, an explicit "locked decisions (do not relitigate)" section saves every reviewer the same conversation. Pair it with an "out of scope (do not implement)" list. Both are short, both are honest about why, both are revisitable when constraints actually change. See Locked Decisions in Docs.

How these apply to apps, not just CLIs

The principles port:

The principles aren't CLI-specific. They're a discipline about respecting the reader's time and the doc's accuracy. CLIs are just where I had to write them down first because the surface is so wide.

Reviewer checklist

When reviewing a doc PR — or my own draft before opening one — I scan for these:

A PR that fails any of these isn't ready. Send it back, don't merge it with "we'll fix it later."

Anti-patterns I keep watching for

How this connects to my broader thinking

See also