Write documentation for a package
01A manual for a package is itself a package: it names what it documents, carries a title and a summary, and is read rather than installed. This page writes one, with examples that are run and rules quoted from the source they come from.
Create a documentation package org.acme/notes-flow-docs in the current VibeVM project, as an in-tree package under vibevm/vibepacks/, documenting the package org.acme/notes-flow. Give it a manifest with kind doc, a title and an abstract, and a [[documents]] entry for the subject. Write one page explaining what the flow does, with a rule quoted from the subject's protocol by address. Run vibe doc check on it.
the vibevm skill installed for your agent; a project with vibe.toml at the root and the subject package in it
vibevm/vibepacks/org.acme/notes-flow-docs/v0.1.0/vibe.toml declares kind = "doc", title, abstract and [[documents]]; the page under vibevm/vibespecs/ has a first paragraph without terms and a rule block whose address resolves; vibe doc check --citations reports no unresolved citation
grep -q "kind = \"doc\"" vibevm/vibepacks/org.acme/notes-flow-docs/v0.1.0/vibe.tomlvibe doc check --citations --path vibevm/vibepacks/org.acme/notes-flow-docs/v0.1.0
What happens
03The agent creates the package with the doc kind, fills the card, names the subject, and writes the first page in the XML dialect with the documentation vocabulary. vibe doc check --citations resolves every rule address against the subject's specification and fails on any that does not exist. The manual is published like any package; the site finds it through the [[documents]] edge and, because the subject's group published it under the -docs name, shows it as the subject's official documentation.
04 Default convention: when the subject declares no[documentation], the package<name>-docsin the same group counts as official and primary. A declared[documentation]replaces the convention entirely.
The manifest
05A doc package must name at least one subject and carry a title and an abstract; it may declare a skill, images and, for a translation, the documentation it adapts. It may not declare a boot snippet, a binary or a server: documentation is read, never executed, and never enters a session's reading list.
06 Adocpackage MUST declare at least one subject in[[documents]](§4) and MUST carrytitleandabstract(§7).
07 Adocpackage MUST NOT declare[boot_snippet],[[mcp_server]]or[[binary]];vibe checkrejects the manifest. Documentation never enters a boot lane (§14).
08The abstract answers four questions in three to six sentences: what the manual covers, for whom, what it assumes known, what it leaves out. The title is the display name on every shelf; the coordinate stays the identity, and the publisher is shown beside it. Images are optional source files in the package tree; when absent, the site draws a placeholder from the coordinate.
09descriptionstays the one-line subtitle for lists and the page's meta description;abstractanswers four questions — what it covers, for whom, what it assumes known, what it leaves out — and is bounded at about a thousand characters. The entry page does not restate the abstract; it inserts it throughderived kind="manifest-field".
10
Placeholders are generated, never stored: a gradient or pattern for the banner and a glyph for the icon are computed from the hash of the coordinate, so a package looks the same on the site and in the local reader and different packages are distinguishable; the glyph depends on the kind — a book for doc, its own sign for every other kind; inline SVG at render time, no files, no network.
11A documentation package may also declare a skill, a [translates] table and [media]. Its pages live under vibevm/vibespecs/ like the specs of any package, and only there is the documentation vocabulary open. The default name of a subject's documentation is the subject's name with -docs, in the same group.
12 Adocpackage MAY declare[[skill]],[translates](§5) and[media](§7).
13 Its pages live undervibevm/vibespecs/of its own tree like the specs of any package (PROP-052); a document belongs to the documentation genre by the kind of the package that contains it, and only there the documentation vocabulary of the dialect is open (PROP-045##DOC-VOCAB-BY-KIND).
14 The official-by-default documentation of a subject<group>/<name>is named<group>/<name>-docs, in the same group. The core documentation isorg.vibevm.core/vibevm-docs, the companion of the host coordinateorg.vibevm.core/vibevm.
15Two more declarations are for the reader rather than the site. authorship in [package] says who wrote the prose, human, ai or mixed; it is a property of the document a shelf can filter by, never an attribution of the commits, whose law is the repository's own. [navigation] pins the pages a newcomer should see first and names the sections of the page tree; every other page keeps the order the package declares.
16 Adocpackage MAY declareauthorshipin[package]:human,aiormixed— who wrote the prose the package carries. It is metadata of the document, kept for the reader who filters a shelf by it; it is never an attribution of the commits or of the repository, whose authorship law isspec://org.vibevm.core/vibevm/common/PROP-000#commits. Absent means unknown: the site shows no badge and a filter by authorship leaves the package out of both named groups.
17 A documentation package MAY declare[navigation]:pinned, the document paths the site and the local reader list first, in the order given; and[[navigation.section]], one row per top-level folder of the page tree with the title the navigation shows for it. Pinning changes only where the named pages stand; every other page keeps the manifest's order. A pinned path that names no page is an error ofvibe check.
The vocabulary of a page
18Pages are written in the project's XML dialect, extended for documentation with a small vocabulary that ordinary specifications do not have. Each element is checked by a tool, which is the point of having it.
| Element | What it does | What checks it |
|---|---|---|
example with run and expect |
a command and its expected output, run in a fixture | the runner: exact match after declared normalisation |
rule ref="spec://…#ANCHOR" |
quotes a rule from a specification, live, in the specification's language | the anchor exists |
derived kind="cli-help | jtd-schema | manifest-field" |
inserts a generated reference block | regenerated at build; a divergence is red |
note kind="note | tip | warning" |
a call-out | the schema |
figure src alt with caption |
an image from the package tree | the file exists and passes the media rules |
prompt with needs, outcome, assert |
the request a user gives an agent to do the task, and the commands that prove it was done | an agent runs it in a clean fixture, then the asserts |
when="os:…" on any block |
a platform variant | the condition vocabulary |
20 The vocabulary is a parameter of the reader, not of the document.Vocabulary::{Spec, Doc}(defaultSpec) selects the accepted element set through additive entry points (from_xml_with,load_spec_text_with,project_spec_text_with); the mapping «package kind → vocabulary» is the caller's, because the pivot knows noPackageKindby the separability law. A document declares nothing about its vocabulary.
21A page that quotes a normative value, a flag, a path, a field name, does so through rule; it never restates the value in prose, because a restated value is a second copy that drifts.
22 Documentation cites an anchor and never restates a normative value — a number, a flag, a path, a field name. Where the prose must mention a value, the same sentence carries the source address.
The shape of a page
23A concept page has a noun as its title and opens with a paragraph that uses no term of the glossary. It shows an example before it explains, explains as a ladder where each step uses only the steps before it, and ends with edge cases and questions. A task page has an imperative title, opens the same way, and then gives the request for an agent before anything else: what to ask, what the agent needs, what you will see, and the commands that prove it worked. Manual steps follow only when they are worth walking. No page ends with a conclusion.
24 The page skeleton. A concept page: a noun-phrase title; a first paragraph saying what this is and when it is needed with no glossary term at all (it is also the page's line inllms.txt; clarified 2026-09-12 at the first corpus check: a glossary word used in its ordinary English sense — package, project, kind, feature, workspace, translation — does not count, a word that means something only in vibe — lock file, manifest, registry, store, index, anchor, skill, contribution, fingerprint, receipt — does); anexamplewith itsexpect; the mechanism as a ladder; edge cases throughrule; questions only if real. A task page: an imperative title; the first paragraph without terms; then theprompt(§16##STYLE-PROMPT-FIRST); «what happens» in three to six sentences as a corridor; «by hand» as numbered STE steps only where the manual road is worth walking; edge cases and questions. No page ends with a conclusion, a summary or a «next steps» box.
25 Prompt first. Any action in VibeVM is done by an agent or by hand, and the agent is the main road. A scenario page opens with apromptblock: the plain request in the user's voice, self-contained (coordinates, paths and registry named, never implied), one prompt for one outcome, free of secrets, neutral to the agent (it works for any agent with thevibevmskill), at most sixty words; beside itneeds(what the agent must have) andoutcome(what the person sees when it worked), and at least oneassert— a shell command that must exit zero after the agent's work, because a prompt cannot be checked by its output the way a shell example can. A prompt without an assert on a scenario page is a style-linter error; an illustrative prompt on an explanation page is markedassert="none".vibe doc check --promptsruns every prompt through the configured agent runner ([doc.prompts] runner) in a clean temporary directory with the fixture and then runs the asserts; it is not part of the panel — it runs in the prose phase before acceptance, as a sample in the monthly loop, and in full at reconciliation. The skillvibevm-docstakes a page'spromptas the task when the user asks for what the page describes.
26The full writing rules, including the banned words and the limits on sentence length in technical passages, ship with this manual as AUTHORING.md; vibe doc check --style enforces the mechanical part.
27 The mechanical checkvibe doc check --stylegates a page: banned words and phrases by the page's language; sentence and paragraph length by block kind (errors in procedures and warnings, warnings in corridors); a glossary term used before its introduction; more than two glossary terms in one narrative sentence; deferral phrases («see the specification», «as described in») without an explanation on the same page; forbidden headings; exclamation marks, emoji, bold in prose; a readability score per page reported and not gated. A false positive is fixed in the linter's rule with a BACKLOG entry, never worked around in the text. A page is committed only after the author's self-edit against the norm and a green--style.
Checking and publishing
28vibe doc check --examples --citations --derived --media --style runs every check; the examples run against the real binary in a sandbox copied from the fixture the page names, and a page is committed only when the checks are green. Publishing is vibe registry publish like any package; a reader gets the manual with vibe cache add, and the site renders it when the index announces it.
29 The example runner (vibe doc check --examples) runs everyexampleagainst the built binary and compares exactly after the declared normalisation; there are no match templates — every non-deterministic line is closed by a namedreplacerule visible in review. A page carriesrun,expect(stdout) and an optionalstderr; the attributeexitdefaults to0; an absentstderrasserts «stderr is empty». A fixture is a directory with a tree and anexample.tomldeclaring the normalisation rules and the map «--jsondocument → JTD schema» by thecommandfield. The command's working directory is a fresh sandbox with a copy of the fixture, never the source tree; the command names no paths; isolation is one variableVIBE_SETTINGSin the native path spelling plusNO_COLOR; the behavioural variables (VIBE_OFFLINE,VIBE_UNATTENDED,VIBE_INVOKED_BY,VIBETERM,VIBEFRAME) are cleared and the flags stand in the example itself; a tripwire checks that the real~/.vibeand the source tree stayed unchanged; stdout and stderr are captured separately; examples document the non-TTY branch of the product and interactive prompts are described in prose; a--jsonstream is parsed document by document and each is validated by the fixture's schema map with a JTD validator written invibe-doc(none exists invibe-wire, whose schemas are codegen input); a document without a schema is reported as unchecked, never as passed. Normalisation:<TMP>,<HOME>,<REPO>, slashes, CRLF in expected files,vibe <VERSION>(package versions untouched), ANSI, block sorting by a declared line form, the fixture's localreplacerules; the order is path replacements before slash unification and sorting after all replacements. Loosening a comparison to turn a check green is forbidden: the normalisation or the product is fixed.
30Every rule is a live citation without a pin: the page shows the fact's current text at every render, and the citation check asks one thing, whether the anchor still exists. Facts a specification marks as obligations for an audience must be cited by a page for that audience, and vibe doc check --coverage is that gate.
31 Everyruleyields adocumentsedge without a pin: the citation is live, and the page shows the fact's current text by address at every render.vibe doc check --citationschecks one thing — that the anchor exists; a vanished anchor without a tombstone fails the build. There are no revisions, no text hashes and no «the spec moved ahead»: such checks would need a history the project does not keep by design.
32 The coverage gate. Spec facts markedactionstage="doc"with an audience are obligations;vibe doc check --coveragerequires every obligation to be cited by a page for the same audience — this is the ratchet PROP-047##DOC-COVERAGE-RATCHETnames, andvibe progress report --view doc --audience …is its listing of obligations, a source for the gate and not a navigation. Marking the obligations in the spec corpus is a campaign atom of its own. The site's navigation is derived from the page manifest, never from this report.
Edge cases and rules
33Any group may document any package; the site shows such a manual on the community shelf with its publisher, and the subject's own group can promote it to official by naming it in [documentation].
34 Official documentation is the one whose edges converge: the subject named the package and the package declared the subject. Community documentation has only the edge from the documentation. An edge from the subject alone reads «not published or an error», and the site shows a warning.
35Examples in a README of an ordinary package are not run: the vocabulary opens only in packages of kind doc.
36 Known limit: the README and specs of packages of other kinds cannot carry verifiable examples — the vocabulary opens by package kind. Their fences render at level 0 as they are, unverified.
37A manual describes a version range of its subject through [[documents]] version, and the site shows, for each subject version, the newest manual whose range admits it.
38
For a subject version V the site shows the documentation versions whose [[documents]] constraint admits V, choosing the newest.
39A package with no documentation at all is still shown: the site renders any published version from its own bytes, the manifest as a reference page, the README, the boot snippet, the specs with their anchors, and the declared skills, binaries and servers.
40 Level 0. The site renders any published version of any package from its own bytes: the manifest as a reference page, the README, the boot snippet marked «read by the session», the specs with anchors and fact highlighting by address, the declared skills, binaries and MCP servers, the dependants, «explained in», «translated into», and the images of[media]. Versions sit in the side navigation;latestis an alias.
41Such a rendering says so in its manifest, so a shelf marks it as generated, and the page of a bridge keeps the maintainer of the bridge apart from the author of what it wraps.
42
The manifest of a level-zero rendering says so: projection = true, so a shelf can tell a page the site derived from a package's own bytes from a page an author wrote, and mark the first as generated. A bridge's rendering carries the two authorships the bridge keeps apart.