docsgov
v0.1.3
Published
Config-driven documentation governance: checks that {{code:…}} and {{api:…}} references in your Markdown docs still resolve, that doc links exist, and (via dedup) flags near-duplicate concepts.
Readme
docsgov
Config-driven documentation governance. docsgov checks that the
references inside your Markdown docs still point at things that actually exist —
so docs rot loudly (a failing check) instead of silently.
It runs three independent guards over your docs/, plus a dedup analysis:
| Guard | Checks that… |
| --- | --- |
| code | every {{code:path#Symbol}} token resolves to a real symbol in your source tree (via tree-sitter) |
| doc | every Markdown link/image target exists |
| api | every {{api: METHOD /path}} token exists in your OpenAPI spec |
A fourth command, dedup, flags near-duplicate documentation concepts in
docs/ using sentence embeddings.
The package source lives at the repository root (a TypeScript/Node project).
Install
npm install -g docsgov # the npm package is "docsgov"
docsgov --version # the command it installs is "docsgov"Or run it without installing:
npx docsgov checkRequirements
- Node.js >= 22. docsgov uses the built-in
node:sqlitemodule (for thededupindex), which requires Node 22 or newer. - No system libraries needed. The tree-sitter grammars ship as bundled
WebAssembly, and the
dedupembedder runs through@huggingface/transformers(which bundlesonnxruntime-node). There is no CGo, no ONNX Runtime install, and no native toolchain to set up. dedupdownloads its embedding model to a local cache on first use.
Skills
Add the marketplace:
claude plugin marketplace add Marketplace name is docsgov-skills (from marketplace.json). Use @docsgov-skills when installing plugins.
In Claude Code, use /plugin ... slash commands. In your terminal, use claude plugin ....
Init Skill (recommended to setup for new repo):
claude plugin install docsgov-init@docsgov-skillsOperations Suite (the guide for agent to handle docsgov error codes):
claude plugin install docsgov@docsgov-skillsQuick start
Mark the repo root and declare what to govern by creating
.docsgov/docsgov.yaml:code: boundary: [docs/**] # .md files scanned for {{code:…}} tokens source: [internal/**, cmd/**] # where those symbols must live doc: boundary: [docs/**] # every link/image target must existRun the check from anywhere inside the repo:
docsgov checkExit
0= clean,1= violations found,2= config/usage error.
Commands
docsgov check [--format text|json]
Runs the code, doc, and api guards over their configured scopes and reports
every violation. --format json emits machine-readable output for CI;
--format text (the default) is styled for the terminal.
docsgov dedup
Refreshes the embedding index for docs/ and reports near-duplicate concepts.
Exits 1 if a high-confidence duplicate group is found.
docsgov update [--version vX.Y.Z] [--check]
docsgov is distributed via npm, so update does not self-replace the binary.
docsgov update --checkreports the current version and the latest version from the npm registry (best-effort; degrades gracefully when offline).docsgov update(or with--version vX.Y.Z) prints the install command to run, e.g.npm install -g docsgov@latest.
Exit codes
| Code | Meaning |
| --- | --- |
| 0 | success — no violations |
| 1 | check found violations (or dedup found duplicates) |
| 2 | usage or configuration error (e.g. no .docsgov/ found, bad --format) |
These are stable, so CI can gate on them directly.
Configuration
docsgov reads a single file: .docsgov/docsgov.yaml. The .docsgov/ directory
is also the repo-root marker — docsgov walks up from the working directory
until it finds one. A missing file makes check exit 2.
The file has three optional top-level sections. Each has a boundary (which
.md files to scan) and, for code/api, a source (where referenced
targets must live). doc takes only boundary.
code: # omit → code guard skipped
boundary: [docs/**] # .md files scanned for {{code:…}} tokens
source: [internal/**, cmd/**] # a token's path must be under source
doc: # omit → doc guard skipped
boundary: [docs/**] # every markdown link/image target is existence-checked
api: # omit → api guard skipped
boundary: [docs/api/contract/**] # .md files scanned for {{api:…}} tokens
source: [docs/api/openapi/**] # .json OpenAPI specs (union of all matched)Semantics
- Glob patterns use
**to match any depth. A trailing/is normalized to/**. - The three scopes are independent and overlapping: a file may be in more than one boundary, and each guard runs its own pass. There is no precedence.
- An omitted section skips that guard entirely. A present-but-empty section runs the guard with no files in scope (no violations).
Full reference: docs/config.md and
docs/guards.md.
Reference syntax
These tokens live in your Markdown prose. Tokens inside fenced code blocks or inline code spans are skipped.
Code references — {{code:path#Symbol}}
Loading is handled by {{code:internal/config/config.go#LoadConfig}}.pathmust be under one ofcode.source, else a violation.Symbolis resolved with tree-sitter: top-level types, functions, variables, and interface members resolve. Pointer-receiver methods do not resolve as#Member— cite the type instead.
API references — {{api: METHOD /path [qualifier]}}
Create a team: {{api: POST /teams}} with body field {{api: POST /teams body:name}}.Qualifiers: none (operation exists), param:name, header:name,
body:a.b.c, response:a.b.c. Path templates are normalized
({id} ≡ {teamId}).
Doc links — standard Markdown
The doc guard checks ordinary Markdown links and images:
See [the config reference](config.md) and .External URLs (http:, https:, mailto:), pure fragments (#heading), and
file.md#frag suffixes are handled for you; absolute paths and paths escaping
the repo root are rejected.
Folder structure
A governed repository looks like this — the only required piece is
.docsgov/docsgov.yaml; the docs/ layout is yours to choose:
your-repo/
├── .docsgov/
│ └── docsgov.yaml # the single config file + repo-root marker
├── docs/ # whatever structure you like
│ ├── README.md
│ ├── config.md
│ └── ...
├── internal/ # source referenced by {{code:…}} tokens
└── cmd/This repository governs its own docs/ with docsgov; see
docs/README.md for that layout as a worked example.
CI usage
check is exit-code driven, so gating a pipeline is one line:
docs-governance:
image: node:22
script:
- npm install -g docsgov
- docsgov check # exits 1 on violations → job failsDevelopment
The TypeScript source lives under src/:
npm ci
npm run typecheck # tsc --noEmit
npm test # vitest run
npm run build # tsc + copy bundled .wasm grammars into dist/npm run build compiles to dist/ and copies the vendored tree-sitter
.wasm grammars into dist/codeq/grammars/ so the published package resolves
them at runtime. The repo-root Makefile provides thin wrappers
(make build, make test, make typecheck, make self-check, make clean)
that delegate to these npm scripts.
Documentation
docs/README.md— documentation indexdocs/config.md— full config schemadocs/guards.md— what each guard checksdocs/command/— per-command referencedocs/architecture/— system design
