Documents
A rich-text document with version history, comments, workspace links and media — editable by a person in the app and by an agent through the same surface, at the same time.
8 min
Creating one
Choose the format at creation; you cannot rename it later.
beehaven call document-create '{"title":"Pricing","markdown":"# Pricing\n\nOne line."}'
beehaven doc add ./notes.md # a local file, indexed for searchmarkdown and html are the explicit fields, and they are worth preferring because they state the format. content, body and text are also accepted and are treated as markdown.explain before guessing a name; it reads the schema the server validates against, so it cannot go stale the way this page nearly did.Every document gets a key (CLR-42) you can use as its address anywhere a document id is accepted, and its filename is that key plus its title.
Editing
Two verbs, and only one of them is safe by default.
document-edit | document-update | |
|---|---|---|
| Changes | One passage — find and replace | The ENTIRE body |
| You supply | The text to find, and its replacement | Every character you want to keep |
| If someone edited it meanwhile | Refuses — the passage no longer matches | Overwrites their change |
| Use it | Almost always | Only to replace a document wholesale |
beehaven call document-edit '{
"id": "CLR-42",
"find": "pennies each",
"replace": "a few cents each"
}'find must match exactly once. Ambiguity is refused with a count rather than guessed, because an edit that lands on the first of three matches has changed something nobody looked at — and the document still reads plausibly afterwards. Pass all: true to opt in deliberately.If the text is not found but its opening words are present, the refusal says so — that is the common cause, and it means the document changed since you read it.
document-insert— Place a passage after / before a match, at a line, or at the top — exactly-once, like editdocument-append— Add to the end. Also how you build a document larger than one write allowsdocument-outline— The headings, with line numbers that feed straight back into get and insertdocument-stats— Words, characters, reading time, and what the document containsdocument-rename— The title alone — no body argument, so it cannot destroy one
Working alongside a person
See what moved, then re-read only that.
beehaven call document-status '{}' # what changed, and who changed it
beehaven call document-diff '{"id":"CLR-42"}'An agent sees diffs of its own edits automatically — every mutating action returns one. What it could not see was yours, so it would answer from a body it read ten minutes ago with no way to know the document had moved underneath it.
document-status closes that. The useful field is not the timestamp but who: “four documents changed” is not actionable, “you changed three of these” says which one to re-read.
History
Every write is a restore point.
history-list— The restore points on a documentdocument-diff— What changed between two of themdocument-restore— Put a previous version back, at the original id
A snapshot is taken before the write it protects, so a restore point holds the document as it stood beforehand. Writes close together are coalesced, so a typing session is one restore point rather than a hundred.
Comments
Anchored to the words, not to a position.
beehaven call document-comments '{"id":"CLR-42"}'A comment stores the passage it refers to rather than a character range. A range into a document anyone can edit is wrong the moment a paragraph above it changes — silently, and now attached to different words. Storing the passage makes a stale anchor detectable: the read re-checks the body and reports which comments still find their text, and how many are orphaned.
Links between documents
A link stores an id, never a title.
beehaven call document-links '{"id":"CLR-42"}'A workspace link holds the kind and the id of its target. A link that stores the title is a screenshot — rename the target and the document goes on saying the old name with nothing to notice. Links resolve by key first, because a key is what a person or an agent actually types.
document-links reports which targets are missing, which is what lets you answer “is this document still accurate” without opening every one.
Media, pages and export
Documents hold images, video, audio and YouTube embeds, and support explicit page breaks. Two view modes: the paged sheet, which shows where a page will break, and pageless, which drops the simulated sheet for reading on a screen. Pageless is a viewing preference stored per browser — it changes nothing about the document, so page breaks still break the page in print.
| Export | How |
|---|---|
| HTML · Markdown · Plain text | File → Download |
| File → Download as PDF (via Print → Save as PDF) — honours page setup and page breaks | |
| Programmatic | document-get, paged — 60k characters per call |
Size
A document can be much larger than a single write.
One write is capped at around 768KB; a document is not. Build a large one by creating it and then appending — a 2MB document is reachable that way and works end to end. The refusal on an oversized write names that route rather than only saying “too large”, which would read as documents cannot be this big.
Reads are capped too, on both lines and characters, and a truncated read reports which bound it hit and hands back a range to continue from.