Skip to content

Docs As Code

Section 11 · Lesson 1 · Level: beginner · ~15 min · Prereq: Rules files

Why this matters

An agent starts every session with no memory of the last one, and so do you three weeks later. Everything the code cannot say about itself — why a retry is capped at three attempts, which column is authoritative, what you must run before promoting to production — lives in someone's head until you write it down. Docs as code is the habit of keeping that knowledge in the repository, next to the code, so it survives the session.

Docs live in the repository

Docs as code means three things. The doc lives in the same repository as the code. It changes in the same pull request as the change. A reviewer sees both halves in one diff.

That buys you version history for free: git log docs/api.md shows when an endpoint changed, and checking out an old commit shows the docs as they were then. It buys review for free too, and review is the whole point — the diff is the only moment anyone still remembers why the change was made. It also means the tooling stays boring: markdown files, diagrams written as code (see Diagrams as code), and a link checker in CI. A separate documentation site is optional and usually becomes a second place the same fact has to be edited.

The doc map

The doc map answers one question: if I have question X, which file do I open? Write it down once, at the top of your docs entry point, and put the same list in your rules file so an agent finds it without being told.

Doc map: the question in your head and the file that answers it

flowchart TD
    Q1["What is this and how do I run it?"] --> F1["README.md"]
    Q2["How do I set up my machine?"] --> F2["docs/developer-guide.md"]
    Q3["How does the system fit together?"] --> F3["docs/architecture.md"]
    Q4["What does this table or column mean?"] --> F4["docs/database.md"]
    Q5["What does this endpoint return?"] --> F5["docs/api.md"]
    Q6["Why was it built this way?"] --> F6["docs/decisions/NNNN-title.md"]
    Q7["How do I deploy and promote?"] --> F7["docs/runbooks/deploy.md"]
    Q8["What has bitten people here before?"] --> F8["docs/gotchas.md"]

Eight files cover the questions that come up most days. A real map from a shipped project is a table with one row per file and one clause of purpose: README, developer guide, architecture, database schema, API reference, capability or admin docs, a gotchas file per component, the CI/CD runbook, a decisions folder with an index, and a changelog. Add a row every time you catch yourself searching for the same thing twice — the map grows from annoyance, not from imagination.

One source of truth per fact

Duplication is the defect to design out. If your endpoint list lives in the README, the API doc, and a saved HTTP-client collection, two of those are already wrong and a reader cannot tell which. Give every fact one home and link to it from everywhere else. Where a fact genuinely must repeat — a table of environments, the list of gates — decide which copy is authoritative and have the others say so out loud with a link.

When a section confuses you, do not append a clarification under the stale text. Delete and rewrite. A page carrying three generations of contradiction is worse than an empty page, because a reader acts on the oldest paragraph.

Docs are agent context

An agent's output quality is bounded by the context it can find. A docs tree that states "the wire format between the API and its clients is camelCase; never return raw database rows" improves every future session. The cheapest way to raise the floor on agent work is a good docs folder plus a short rules file that points into it (AGENTS.md that actually works) — kept thin, because it is paid for on every task.

Tooling discipline

Three habits keep the tree honest. Markdown only: plain-text diffs, greppable by you and by an agent. Diagrams as code: a mermaid block changes in the same PR as the design it describes. Link checking in CI: a workflow that fails on a dead relative path is about ten lines (GitHub Actions documentation).

Try it

  1. Create docs/ in a project you own and list every question a new contributor asks you in chat. Aim for eight.
  2. Write the map as a table: question, file, one clause of purpose. Create any file the table promises.
  3. Add the table to your rules file under a "where facts live" heading.
  4. Check links locally with grep -rn '](\\./' docs/ and open a few targets by hand; add the CI version when the tree grows past three files.
  5. Commit docs and code together in one PR. From now on, no doc-only PRs where a code change was the reason.

Common mistakes

  • A doc folder nobody reads — docs/ created during a burst of enthusiasm, never opened again. Fix: put the doc map in the README and the rules file, so both a human and an agent arrive through it.
  • The same fact in three files — environment URLs in the README, the runbook and a deployment script. Fix: one home, links elsewhere, and delete the copies rather than adding a fourth.
  • Appending contradictions — new text under old text instead of a rewrite. The page now disagrees with itself. Fix: delete and rewrite, or delete the section entirely.
  • Docs that describe the plan, not the system — a roadmap masquerading as architecture. Fix: label status (shipped, prototype, planned) separately from description.

Key takeaways

  • Docs live in the repo, change in the same PR as the code, and version with it.
  • Publish a doc map: question → file. Eight rows cover most days.
  • One source of truth per fact; duplication is a bug you will find by acting on the wrong copy.
  • A good docs tree is the cheapest context upgrade for every future agent session.
  • Keep tooling boring: markdown, diagrams as code, link checking in CI.

Further learning