All posts
Jun 5, 2026 · 5 min read · Nadun

Documentation that updates itself: a practical guide to keeping docs in sync with code

Docs rot because nothing connects them to your code. This is the complete guide to closing that gap — the failure modes, the four levels of automation, and how to make docs a side effect of merging.

Every team has the same documentation graveyard. A README that describes a setup flow from two refactors ago. An API doc missing the three endpoints you shipped last quarter. A CHANGELOG that stops at version 1.2 even though you're on 2.8. Nobody decided to let the docs rot — it just happened, one merge at a time.

This guide is about why that happens with such depressing reliability, and the concrete ways to stop it. It's the hub for a series of deeper pieces; each section links to the full treatment.

Why docs rot (it's structural, not personal)

The instinct is to blame discipline: we should just update the docs. But discipline isn't the variable. The variable is feedback.

Look at what stays current in a healthy repo. Tests stay current because CI fails when they don't. Types stay current because the compiler refuses to build. Dependencies stay current-ish because a bot opens PRs. Every one of those has a forcing function — something automatic that makes the gap visible and annoying right now.

Documentation has none of that. You merge a PR, the docs don't change, and absolutely nothing happens. No red X, no failing check, no bot. The cost of stale docs is real but it's deferred and diffuse — a confused contributor next month, a support ticket next quarter — so it always loses to the thing that's due today.

That's the trap: docs are the one artifact in your repo with no feedback loop. We unpack this in depth in Why your README always lies.

The four levels of doc automation

Closing the gap is a spectrum, not a binary. Here's the ladder, from "still manual" to "fully automatic," with the honest trade-offs.

Level 0 — Hand-written. You edit the docs by hand on every change. Best quality when you do it; first thing skipped under deadline. Fine for a side project, fragile for anything shipping weekly.

Level 1 — Conventional commits. Adopt a commit convention (feat:, fix:) and let a tool parse it into a changelog. Deterministic, no AI — but only as good as your team's commit discipline, and a squash-merge of ten messy commits flattens that signal.

Level 2 — Release automation. Tools like release-please watch your conventional commits and open a release PR that bumps the version and updates the changelog. Excellent for disciplined teams — but it's changelog-and-version focused; it won't touch the README or API docs when the code they describe changes.

Level 3 — Generate from the diff. Stop depending on humans writing structured commit messages and instead read the diff itself — the actual code that changed — and draft the doc update from that. This is where it gets powerful, and where it gets dangerous if you're naive about it.

The full version of this ladder, with tooling for each rung, is in How to automate your changelog from pull requests.

The hard part: not hallucinating

The reason "just pipe the diff into an LLM" is dangerous is the confident hallucination — the doc that describes a --retry flag you never added, or an endpoint that doesn't exist. A general model pattern-matches to how code like yours is usually documented, not to what your code actually does.

The fix isn't to trust the model more. It's to constrain it to the diff: anything the draft says has to reference an identifier (function, file, flag) that's actually present in the change. If it mentions something that isn't in the diff, the draft is rejected, not published. That single grounding rule turns the model from a creative writer into a careful summarizer of something real — and it makes the scariest failure mode structurally impossible.

We go deep on this — and why "just review it" isn't enough on its own — in Can you trust AI to write your docs?.

The model that works: docs as a side effect of merging

Put it together and the pattern is simple: make the documentation update happen automatically when code merges, and show up where you already review things — a pull request.

  1. You merge a code PR.
  2. Something reads the diff and drafts the matching doc/CHANGELOG update.
  3. It runs through validation gates (grounding first).
  4. It opens that update as its own PR, which you review and merge.

Now docs have a forcing function. The gap is visible (there's a PR sitting there), the work is pre-done (you review, not write), and you keep full editorial control (nothing merges without you).

Where your docs host fits

None of this replaces a docs platform like Mintlify or ReadMe. Those host your docs and make them lovely to read — that's a different job from writing the update when the code changes. Auto-drafted PRs feed your existing site; they don't compete with it. The distinction is worth getting right, and we lay it out in docs-keeper vs Mintlify: hosting vs. auto-updating.

Try it on one repo

This is exactly what docs-keeper does: a GitHub App that opens a documentation PR every time you merge, grounded in your diff, validated through seven gates, and reviewed by you. It's free for public repos, costs about $0.004 per doc PR, and never touches your code — it just opens PRs you approve.

If your docs are perpetually one merge behind, the cheapest experiment is to install it on a single repo and merge one small change.

See a real docs PR it opened · Install free on GitHub

Try it on one repo.

Free for public repos · grounded in your diff · you review every PR.

Install free on GitHub

Keep reading

Liked this? Get the next one.

Occasional posts on docs, AI, and keeping documentation in sync with code. No spam, unsubscribe anytime.