Keep documentation anchored to the code it describes.
docref is a plain-text convention plus a small tool. Markdown documents reference code by symbol or by marked region, and every reference carries a content hash of what the author last saw. When the code changes, the reference goes stale loudly: in the editor, in CI, and in a machine-readable report that an AI agent can act on. Divergence stops being silent.
The convention is renderer-neutral. Documents using docref render normally on GitHub, in the VSCode preview, and in any static site generator; the metadata hides in fence info strings and HTML comments. No tool needs to be installed to read or write the format.
A doc embeds a snippet that the tool keeps current:
```ts docref=src/lib/server/markdown.ts#applyFootnotes:4fa2b1c9
export function applyFootnotes(content: string): string {
...
}
```A claim ties a paragraph to code in another repository:
<!-- docref: begin src=open-secret:src/api/handler.go#VerifySignature:9c2f1ab3 -->
The handler rejects any request whose signature does not cover the
exact field set, including the target id.
<!-- docref: end -->When VerifySignature changes, the snippet refreshes mechanically and
the claim is flagged for review until a reader confirms the prose is
still true and approves it.
A reference names a piece of code: a symbol (a declaration, found by
parsing — no marker needed; functions, types, and also class/struct fields and
interface properties as Type.field) or a region (a span named in the
source with docref: begin <name> / docref: end <name>, for sub-symbol slices
and languages without addressable symbols, such as CSS). The code side has its
own loud signal, not just the docs:
docref anchors inventories every region marker and what references it, and a
marker that nothing references is flagged not used — which fails docref check unless [anchors] allow-unused = true. A stranded marker, like a broken
reference, never passes silently.
- Plain text first. Every artifact (references, markers, claims, config, lockfile) is readable and editable without the tool, and documents degrade to ordinary markdown everywhere.
- Fail closed. A reference that does not resolve is an error, not a warning. Ambiguity is an error. Silence is never an option.
- Mechanical work is automated, judgment never is. Snippet bodies refresh automatically. A claim is only re-approved by a reader who looked at the prose.
- Usable without AI, useful for AI. One CLI contract serves humans, editors, CI, and agents alike. Agents get JSON; humans get the same answers in the editor.
- Renderer-neutral. Site generators may opt into rendering badges and source links from the metadata, but nothing requires them to.
The CLI is a single standalone binary — no Node, no npm, no registry account. The installer downloads the build for your platform from the latest release:
curl -fsSL https://raw.githubusercontent.com/manchtools/open-docref/main/install.sh | shIt lands in ~/.local/bin/docref (override with DOCREF_INSTALL_DIR) and
updates itself in place with docref self-update. On Windows, download
docref-windows-x64.exe from the releases page. Building from source is in
CONTRIBUTING.md.
The VS Code extension: download the .vsix from the
GitHub releases and
install it — in the editor run Extensions: Install from VSIX…, or:
code --install-extension open-docref-vscode-<version>.vsixIt is intentionally not on the VS Code Marketplace; the .vsix is the
distribution.
docref check is the gate: by default it exits 1 on stale references and 2
on broken ones, so a red job blocks merging drift. The level is configurable
([check] level, or a --strict/--lenient/--advisory flag): lenient
fails only on broken references, so a repo can adopt docref before every
reference is approved, and advisory reports without failing.
A purpose-built image (ghcr.io/manchtools/open-docref) carries the binary and
git on a small Alpine base. Check out the repo and run docref against it with
docker run (the image is musl with no Node, so it runs over the checkout, not
as a container: job, where JS actions like checkout could not run inside it):
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: docker run --rm -v "$PWD:/repo" ghcr.io/manchtools/open-docref checkThe same docker run works anywhere locally, or copy just the binary into your
own image:
COPY --from=ghcr.io/manchtools/open-docref /usr/local/bin/docref /usr/local/bin/.
- name: Install docref
run: |
curl -fsSL https://raw.githubusercontent.com/manchtools/open-docref/main/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- run: docref checkWhile this repository is private, the image and the release assets need a token
with access: authenticate the pull (or the install step) with
${{ secrets.GITHUB_TOKEN }}. Once it is public, neither needs one.
The core library, the CLI, and a first cut of the VSCode extension are
implemented and tested (milestones 1 through 5 of the plan): same-repo
and cross-repo resolution, symbols and regions, check, refresh,
approve, update, affected, suggest, ls, anchors,
and in the editor: create-anchor from a selection, reference autocomplete
(path → symbol/region, with the hash attached), the references
sidebar with live states, drift diagnostics, referenced-by CodeLens,
and a status-bar counter.
Structural (tree-sitter) symbol resolution covers:
TypeScript, JavaScript, Go, Python, Rust, Java, C, C++, C#, Ruby, PHP, Swift, Kotlin, Scala, Bash, and Protocol Buffers. Any other file type still works with a region marker.
Building from source and running the extension in a development host are covered in CONTRIBUTING.md.
The full documentation is published as a site under docs/ — a
content tree served by open-docs.
Spin it up with cd docs && docker compose up (see
docs/docker-compose.yml). The source pages:
- docs/02-format/: the normative format specification
- docs/03-tooling/: CLI surface, CI patterns, the VS Code extension, and the agent contract
- docs/04-internals/: how docref works inside
- CONTRIBUTING.md: layout, the build/test loop, and the bar for changes
- CHANGELOG.md: notable changes per version