Living Docs
Run a project's documentation as a living system — not a write-once artifact that rots.
Living Docs is an AI agent skill for documentation-as-code that keeps a codebase's docs in sync with its code. It works with Claude Code, Cursor, GitHub Copilot, OpenCode, Codex, and Pi — any agent that loads markdown "skills" / instruction files. It is stack-agnostic: it governs how docs are organized and maintained (Architecture Decision Records, Behavior Decision Records, PRDs, a constitution, a glossary, living Mermaid diagrams), never what technology a project uses.
The mechanical half of that discipline is owned end-to-end by the bundled
living-docs CLI — one self-contained Rust binary that scaffolds records
(new, brief), drives their lifecycle (status, describe, supersede),
rebuilds indexes (index, fmt), validates the invariants (check), and
serves ranked full-text search (search) over a derived read-model — embedded
SQLite + FTS5 or ParadeDB. There is no LLM inside the tool: the agent writes only
the judgment prose; everything mechanical is deterministic and reproducible.
The whole discipline collapses to one spine:
Every piece of knowledge has exactly one home, that home is indexed, and nothing structural ships without its doc.
Everything else — the constitution, ADRs, BDRs, PRDs, issues, research notes, architecture diagrams, and the semantic context index — hangs off that spine.
Why this exists
Most documentation rots because there is no contract keeping it honest. Living Docs adds five governance invariants that an agent (or a human) can re-derive every action from:
- Docs-first. Author the body in the repo (
docs/…) before publishing to any tracker or wiki. The repo file is the source of truth; the external copy is a mirror. - One home per fact. Each concept, decision, or requirement lives in exactly one file. Cross-reference instead of copying — duplicated prose is drift waiting to happen.
- Indexed or it doesn't exist. Every doc is reachable from an
index.md. No orphan files. - Supersede, never rewrite history. Decisions and requirements are append-only. When something changes, mark the old record superseded and write a new one — never silently edit the past.
- No structural change without its doc. New module, moved files, schema change, new data flow → update the relevant doc and its diagram in the same change. No "I'll document it later."
These invariants are carried in YAML frontmatter as a fact contract and wired
to a deterministic CLI (living-docs) that both authors the mechanical parts and
checks them. The pitch is not novelty —
arc42 + ADR + C4 + docs-as-code is a well-trodden stack — it is the explicit,
agent-enforceable packaging of it. See Provenance.
The doc trail
Every change follows one chain, from the foundational source of truth down to code:
flowchart LR
C[constitution] --> P[PRD]
P --> A[ADR]
P --> B[BDR]
A --> I[issues]
B --> I
I --> K[code]
| Artifact | Role |
|---|---|
| constitution | Foundational source of truth: what the product is, core data model, non-negotiables. |
| PRD | What the system must do and why — feature/product requirement spec. |
| ADR | How the system is structured — architectural/implementation decision and rationale. |
| BDR | What the system must observably do — inputs, outputs, side effects, Given/When/Then scenarios. |
| issues | Execution slices — discrete units of work that trace back to ADRs/BDRs. |
| code | Implementation — every behavior, structure, and interface specified above, realized. |
What's in the box
This repo bundles the Living Docs skill together with its composition dependencies and the prior-art research that backs its honesty claims:
| Path | What it is |
|---|---|
skills/living-docs/ |
The skill: the five invariants, the doc trail, per-doc-type conventions (rules/) and starter templates (templates/). |
skills/okf-knowledge-format/ |
The format standard the docs use — Open Knowledge Format (OKF): markdown + YAML frontmatter, required type, reserved index.md/log.md, bundle-relative links. The OKF spec is vendored verbatim from Google Cloud Platform. |
skills/research-artifacts/ |
The research-note format and source discipline that feeds ADRs/PRDs (the docs/research/ half of the trail). |
skills/public-export/ |
Publish a clean public build of a private living-docs project without leaking the private "why": a default-deny allowlist export driven by document visibility, a deterministic leak gate (living-docs export + living-docs leak-gate), and a human-gated clean-history publish. |
cli/ (authoring verbs) |
Deterministic authoring: new / brief scaffold a record with CLI-owned numbering and frontmatter — and new --json '{...}' authors the whole body in one call, its keys validated against the type template's own section headings (ADR 0038). status / describe set the lifecycle fields, supersede wires both link directions, index rebuilds every index, fmt canonicalizes frontmatter. Architecture is a first-class doc type: new view "<name>" --kind <context|container|component|flow|sequence|state|data-model|deployment> scaffolds one view per concern in docs/architecture/, and the generated index sorts them in C4/arc42 zoom order (ADR 0036). The agent writes only the judgment body below the frontmatter; write-time hooks block hand-edits to the rest. |
cli/ (living-docs migrate [--apply]) |
Adaptation advisor: scans a bundle (or detects its absence) and prints one ordered plan — RUN steps are exact mechanical commands, AUTHOR steps are judgment work naming the record and its governing ADR, ADOPT steps bootstrap a project with no bundle at all (ADR 0037). --apply executes the mechanical subset transactionally: snapshot, index + fmt, byte-for-byte rollback on any failure or check regression (ADR 0040). |
cli/ (living-docs seal init) |
Provenance sealing: baselines a per-clone HMAC key + ledger under .git/living-docs/ (never committed); every CLI write re-seals automatically, and check then fails any record created or owned-frontmatter-edited outside the CLI — including shell edits (sed, cat >) that write-time hooks never see. Fail-open until initialized; friction, not cryptography, by declared design (ADR 0039). |
cli/ (living-docs search / db) |
Ranked full-text search over a derived read-model — the embedded SQLite + FTS5 file (--engine sqlite) or ParadeDB via $DATABASE_URL (ADR 0004) — with an explicit db sync step that (re)builds the projection from the .md records. Exactly one backend is authoritative per deployment (ADR 0003): no bidirectional sync, no source-of-truth conflict. |
references/prior-art-landscape.md |
The sourced prior-art analysis — every part of Living Docs (the doc trail, the OKF format, the diagrams, the governance invariants) mapped to its established originator, so every "credit, not invention" claim has a checkable citation. |
cli/ (living-docs check) |
The deterministic checker for the mechanical invariants — frontmatter/type, indexing + reachability, link resolution, supersede integrity, requirement traceability (every FR-N/NFR-N a non-Draft PRD defines must be cited by a BDR that links it — advisory at Accepted, violation at Implemented, ADR 0035), and provenance seals once seal init has baselined the clone (ADR 0039). A single self-contained Rust binary: native serde_yaml frontmatter parsing and native pulldown-cmark link extraction/resolution — no host tools (no lychee/yq/jq) needed. A constraint without an instrument is a vibe; this is the instrument. Wire it into CI. Install with ./install.sh cli or make cli-install. |
cli/ (living-docs check --mermaid-only) |
Validates every fenced ```mermaid block in-process via the pure-Rust merman-core parser — the real Mermaid grammar, not a hand-rolled check — and fails with a file:line pointer at the first broken diagram. No Docker, no daemon, no Chromium (ADR 0013): the same self-contained binary does it. With no path argument it sweeps every git-tracked .md file in the repo. |
examples/linkly/ |
A worked, lint-clean end-to-end corpus (constitution → PRD → ADR + BDR → issue) for a fictional URL shortener — the discipline shown, not just described, and the fixture CI runs living-docs check against. |
Each skill is self-describing — open its SKILL.md for the full operational
detail. Living Docs and OKF compose but do not overlap: Living Docs governs
which docs exist and the no-drift discipline; OKF governs how a knowledge
bundle's markdown and frontmatter are shaped.
Installation
The skill is plain markdown instruction files — nothing to compile or install to use it. The optional living-docs CLI — deterministic authoring, checking, and full-text search — is a single self-contained Rust binary with no host-tool dependencies at all: native frontmatter and link parsing (no lychee/yq/jq) and — since v0.6.0 — in-process Mermaid validation via the pure-Rust merman-core parser, so --mermaid-only no longer needs Docker. Install it with ./install.sh cli or make cli-install.
Installing Living Docs always means the same thing: put the three skills/
directories (or a generated rule file) where your tool discovers instructions,
then start a fresh session. A cross-platform installer and a Makefile do this
for every supported tool. Clone once:
git clone https://github.com/ejklock/living-docs-skill.git
cd living-docs-skill
Quick start — install.sh / make
./install.sh # Claude Code, global (~/.claude/skills) — the default
./install.sh cursor # Cursor rule in the current project
./install.sh copilot # GitHub Copilot instruction in the current project
./install.sh opencode # OpenCode (~/.config/opencode/skills)
./install.sh codex # Codex (~/.codex/skills)
./install.sh pi # Pi (~/.pi/agent/skills + AGENTS.md)
./install.sh all # every supported harness at once
Useful flags: --project (install into the current repo instead of the global
user dir), --dir <path> (custom skills directory), --uninstall, --dry-run,
--help. The same targets are available via make:
make help # list every target
make install # Claude Code, global
make install-cursor # or install-copilot / install-opencode / install-codex / install-pi / install-all
make project-claude # install into the current project
make uninstall-all # remove from every harness
make check # full gate: version sync · living-docs check the example ·
# validate mermaid · hostile parser fixtures · bash -n all
# scripts · dry-run every harness
make build # build the living-docs binary natively -> target/release/living-docs
make cli-install # install the living-docs binary onto PATH (fetches the latest GitHub release; LIVING_DOCS_VERSION pins a tag)
make test-fixtures # run the hostile/negative fixtures guarding the parsers
Where each tool loads from
| Tool | Mechanism | Default location (global · --project) |
Enforcement |
|---|---|---|---|
| Claude Code | native SKILL.md skills |
~/.claude/skills · .claude/skills |
Plugin or living-docs hooks install — write-gate + session teaching + pre-commit |
| OpenCode | native SKILL.md skills (also reads .claude/skills) |
~/.config/opencode/skills · .opencode/skills |
living-docs hooks install — pre-commit doc-gate only |
| Codex | native SKILL.md skills |
~/.codex/skills · .codex/skills |
living-docs hooks install — pre-commit doc-gate only |
| Cursor | project rule | .cursor/rules/living-docs.mdc (project-scoped) |
None — pre-commit + CI only |
| GitHub Copilot | path-scoped instruction | .github/instructions/living-docs.instructions.md (project-scoped) |
None — pre-commit + CI only |
| Pi | skills dir + AGENTS.md pointer |
~/.pi/agent/skills · .pi/skills |
living-docs hooks install — pre-commit doc-gate only |
Claude Code, OpenCode, and Codex share the same model: they
auto-discover folders of SKILL.md files from their skills directory, so the
installer just copies the three skills there (OpenCode additionally reads
.claude/skills, so a Claude install already covers it). For Cursor and
Copilot the installer generates the rule/instruction file with the right
frontmatter header (globs / applyTo scoped to docs/** and **/*.md) from
living-docs/SKILL.md. Pi has no native skills directory — after the skills
are copied, reference them once from your AGENTS.md:
## Living Docs
Follow the documentation discipline in skills/living-docs/SKILL.md,
skills/okf-knowledge-format/SKILL.md, and skills/research-artifacts/SKILL.md.
Then restart the session so the tool picks up the skills.
Enforcement — write-time gates, not just instructions
./install.sh ships skills only — it copies markdown instructions and never
touches a hook script or wires any settings file (ADR 0023).
The write-gate, the session-teaching hook, and the pre-commit doc-gate are
distributed through two separate, deterministic channels:
- Claude Code plugin (Claude Code only):
/plugin marketplace add ejklock/living-docs-skillthen/plugin install living-docs@living-docs(add--scope projectto commit the choice to the repo). Installs the write-gate (PreToolUseonWrite|Edit|MultiEdit, blocking hand-written docs before they land) and the session-teaching hook (SessionStart), both resolved through${CLAUDE_PLUGIN_ROOT}so no checkout of this bundle is required. living-docs hooks install [--dir <project>] [--docs-dir <bundle>] [--dry-run](every harness): materializes the two hook scripts into.living-docs/hooks/, wires.claude/settings.jsonwith the resolved bundle pinned asLIVING_DOCS_BUNDLE=, and installs the pre-commit doc-gate at.githooks/pre-commit(pointingcore.hooksPathat it). The pre-commit gate is git-level and catches every harness at commit time; the.claude/settings.jsonwiring is what gives Claude Code its write-time gate. Remove everything it wrote with the siblingliving-docs hooks uninstall [--dir <project>] [--dry-run]—installanduninstallare separate subcommands, not a flag.
Cursor and GitHub Copilot have no write-time hook surface at all — neither tool exposes a pre-write hook, so they rely entirely on the pre-commit gate and CI to catch a hand-written doc after the fact.
One caveat worth knowing: plugin hooks and .claude/settings.json hooks fire
independently, with no deduplication. Installing both channels in the same
Claude Code project duplicates the SessionStart notice and the (still
correct) block — an accepted trade-off recorded in
ADR 0023.
Skill content — served by the CLI, not copied to disk
Native harnesses (Claude Code, OpenCode, Codex, Pi) only get each skill's slim
SKILL.md stub (plus okf-knowledge-format/reference/, the vendored spec) — the
full per-doc-type conventions (rules/) and starter templates (templates/)
travel inside the living-docs binary (ADR 0014)
and are reached with living-docs skill, not by reading files off disk:
living-docs skill --list # every embedded skill and its topics
living-docs skill living-docs # the full living-docs/SKILL.md body
living-docs skill living-docs --topic adr # just the adr topic's rules (+ template)
Output is context-aware: piped or otherwise non-TTY output defaults to minified
single-line JSON (the machine-friendly shape another agent parses); a real terminal
gets human-readable plain text. --json and --plain override the autodetection in
either direction and are mutually exclusive. This is why a native harness install is
a small, stable footprint on disk while the authoritative detail stays centralized in
one versioned binary — see ADR 0014.
Any other tool
Copy skills/living-docs/, skills/okf-knowledge-format/, and
skills/research-artifacts/ into wherever that tool loads instructions from, or
just read the SKILL.md files — they are plain markdown meant to be read by
humans and agents alike.
Companion skills (Matt Pocock) — recommended, not bundled
Living Docs composes with but does not bundle Matt Pocock's skills. His
grill-me (design interview before a load-bearing decision) pairs directly with
Living Docs, and his to-prd / to-issues are kindred to the PRD/issues
workflow here. They are best installed straight from the source so they stay
canonical and up to date — his repo is MIT-licensed, so cloning and using it is
permitted (keep his LICENSE notice if you copy files):
./install.sh pocock # git clones his repo (default ~/.matt-pocock-skills)
# or by hand:
git clone https://github.com/mattpocock/skills.git
# his repo ships a `setup-matt-pocock-skills` skill that wires them up
See ATTRIBUTION.md for how Living Docs relates to his work.
When to invoke
- Standing up documentation for a project (
docs/structure, the docs index, ADR/issue/BDR/constitution directories). - Writing or editing an ADR, PRD, BDR, constitution, or
issue → load the matching
rules/+templates/file. - Recording research → the
research-artifactsskill. - Drawing or updating an architecture / data-flow / sequence diagram (living Mermaid, in-repo text that must match the code).
- Defining a term or acronym → the glossary, one home per term.
- A doc grew too large or mixes concerns → split into a semantic index.
- Enforcing the no-drift maintenance rule after any structural change.
Composition with other skills
Living Docs is deliberately small and composes with the rest of your toolchain
rather than absorbing it: design grilling before a load-bearing ADR, an
architecture-improvement pass that reads the context index and ADRs, a
deep-research step that gathers the evidence research-artifacts then formats,
and an implementation-review step that checks code honors the ADRs/BDRs. See the
"Composition with other skills" section in
skills/living-docs/SKILL.md for the full map.
The design-grilling step composes with
grill-meby Matt Pocock (github.com/mattpocock/skills) — referenced, not bundled here. SeeATTRIBUTION.md.
Provenance — honest attribution
This work instrumentalizes established practices; it does not invent them. "Living documentation" is Cyrille Martraire's named methodology; ADRs are Michael Nygard's (supersede-don't-delete is the adr-tools convention); BDRs wrap Specification by Example / BDD (Adzic; North); the file format is Google Cloud Platform's OKF, vendored verbatim; the architecture diagrams are Mermaid (Knut Sveidqvist & the mermaid-js community). None of the doc types are invented here. What is original is modest and concrete: the composition + the governance invariants carried in frontmatter as a fact contract and enforced by a checker — the enforcement, not the invention.
Full credits and the per-source links are in
ATTRIBUTION.md and
references/prior-art-landscape.md.
Contributing
Issues and PRs welcome — the project dogfoods its own rules. See
CONTRIBUTING.md for the repo layout, the invariants it holds
itself to, how to refresh the vendored OKF spec, and how to validate a change —
make check runs the full gate: version sync, the docs linter, the hostile parser
fixtures, bash -n on every script, and a dry-run of every installer.
FAQ
What is an "agent skill"?
A skill is a folder of markdown instructions (a SKILL.md plus optional rules/
and templates/) that an AI coding agent loads and follows. Living Docs is a
skill that teaches the agent how to keep documentation in sync with code.
Which tools does Living Docs work with?
Claude Code, OpenCode, and Codex (native SKILL.md skills), Cursor
(.cursor/rules), GitHub Copilot (.github/instructions), and Pi (AGENTS.md).
Because the skill is plain markdown, any agent that reads instruction files can
use it. See Installation.
How is this different from a documentation generator or a wiki?
Living Docs is not a generator and not a hosting tool. It is a discipline — five
no-drift governance invariants plus a doc trail (constitution → PRD → ADR + BDR →
issues → code). The agent follows the discipline as it works; a deterministic
CLI authors the mechanical half (living-docs new / status / supersede /
index) and verifies it (living-docs check) when you wire it into
CI or the agent's loop. Prompt-level guidance plus a machine check — not one
pretending to be the other. Your docs live in the repo, in Git, next to the code.
What is an ADR / BDR / PRD?
An ADR (Architecture Decision Record) captures how the system is structured
and why. A BDR (Behavior Decision Record) captures what the system must
observably do (Given/When/Then). A PRD captures the product/feature
requirements. Each has a convention file and a starter template under
skills/living-docs/.
What is OKF (Open Knowledge Format)?
A vendor-neutral format from Google Cloud Platform — markdown with YAML
frontmatter, a required type, reserved index.md/log.md, and bundle-relative
links. Living Docs stores every doc as an OKF concept so the corpus stays
portable and agent-parseable. The spec is vendored under
skills/okf-knowledge-format/.
What does the living-docs check checker catch — and not catch?
It is a deterministic checker over a documented input shape, not a general markdown/YAML validator, and its three fragile parsers (link extraction, link resolution, frontmatter reading) are guarded by hostile/negative fixtures (make test-fixtures). One known limit: the structural-graph checks — directory-index membership and index reachability — read only inline links in index.md, so a file indexed solely via a reference-style link ([x][ref]) is not yet detected there and would be reported as a false-positive orphan. Link validity itself is checked natively by pulldown-cmark, which parses every link form (inline, titled, angle-bracket, reference-style, and images).
Is it tied to a specific language or framework? No. Living Docs is stack-agnostic — it governs documentation organization and lifecycle, not your tech stack.
Did you invent this?
No, and the repo says so. Living Docs composes established practices (Martraire's
living documentation, Nygard's ADRs, Specification by Example for BDRs, Google's
OKF). Full, sourced credits in ATTRIBUTION.md and
references/prior-art-landscape.md.
License
MIT © 2026 Evaldo Klock.
Vendored third-party content under reference/ directories remains subject to
its own upstream license — see ATTRIBUTION.md.
Keywords: living documentation · documentation as code · docs-as-code · AI agent skill · Claude Code skill · Cursor rules · GitHub Copilot instructions · OpenCode · Codex · Pi · Architecture Decision Records (ADR) · Behavior Decision Records (BDR) · PRD · project constitution · glossary · Mermaid architecture diagrams · semantic index · Open Knowledge Format (OKF) · deterministic docs CLI · full-text search · SQLite FTS5 · public docs export · leak gate · knowledge management · technical writing · software architecture · markdown documentation · no-drift docs.
No comments yet
Be the first to share your take.