Usage

Once connected, your agent sees the doc_* tools. You will not call them by hand, but when an agent behaves unexpectedly you need to know how they work to find out why.

What the agent is told every session

This is the string the server ships in its initialize response. It is what sets the order the tools get used in.

This project's docs live here. Never read one whole: doc_outline first, then doc_get(heading) for just the section you need. Re-reading? Pass the previous sha as if_none_match. Saw [stale]? Call doc_changes_since. Writing is doc_put — base_sha is the sha you last read, and to change one section pass heading plus that whole section.

It goes into the context every session, so it stays short — this guidance costs tokens too.

Reading: outline first, then one section

doc_outline                                   # which documents, which sections
doc_get(library:"cushion", path:"SPEC.md",
        heading:"6. Auth")                    # just that section
doc_get(…, if_none_match:"<previous sha>")    # unchanged if nothing moved

The point is never to read a whole document. doc_outline gives you the list of documents and their ## headings. If you do not know which document holds it, doc_search returns the top matching sections.

Pass the previous sha in if_none_match and an unchanged document comes back as unchanged instead of a body. That is the piece that stops you loading the same document twice.

Writing: nothing is merged

doc_put(library:"cushion", path:"SPEC.md",
        heading:"6. Auth",            # replace only this section
        content:"## 6. Auth\n…",
        base_sha:"<sha from the last doc_get>",
        note:"add the token rotation rule")

base_sha is the sha you got when reading. If someone edited in the meantime the write is rejected and the current sha comes back. Nothing is merged for you — read again, write again.

Give a heading and only that section is replaced. You never send the whole document, so the write side costs fewer tokens too.

When you are behind: [stale]

No polling, no standing connection. If a document changes mid-session, one [stale] line is appended to the next tool response. Call doc_changes_since then and you get a summary of everything after your cursor.

The summary is structural — path, sections and the line delta. No LLM is involved: a summarizing model only sees the prose, which turns “which code does this affect” into a guess.

History and restoring

The previous body is always kept before anything is overwritten — deletions included.

From History on a document you can read the change between two versions as hunks, open an old body in full, and restore it. Restoring is a new save rather than an overwrite, so “when, and back to what” stays on the record.

Backup

/api/export is the only backup. You can download everything from the admin screen. The source of truth living here means that if this goes away, so do the docs.

Tool reference

doc_outline

List of documents and their ## headings (specs, ADRs, runbooks, meeting notes). Call this first. Omit library for everything you can reach.

library
Library slug. Omit for all of them
depth
libraries = just the library list (name, GitHub repos, document count). Defaults to documents
doc_get

A whole document, or the single ## section named by heading. Pass the previous sha as if_none_match and an unchanged document comes back as just `unchanged`.

library*
path*
Path from the library root
heading
The ## section title
if_none_match
The sha you received last time
doc_search

Full-text search returning the top matching sections. Use it when you do not know which document holds it.

query*
library
doc_changes_since

A summary of everything changed after your cursor. Called with no arguments it also advances the cursor.

library
since
An event id. Passing it leaves the cursor where it is
doc_put

Create or update a document. A new path simply becomes a new document. For an existing one base_sha is required: if someone edited in the meantime the write is rejected and the current sha is returned. Pass heading to replace only that section.

library*
path*
Path ending in .md
content*
The whole document, or - if heading is given - that whole section including its ## line
heading
Replace only this ## section, so you never send the whole document
base_sha
The sha from your last doc_get. Omit for a new document
note
One line on what changed and why
doc_delete

Delete a document. base_sha is required. The previous body stays in the history.

library*
path*
base_sha*
note
library_create

Create a new library (a bundle of documents). Whoever owns the calling token becomes its first member. Only when there is nowhere to put the document.

slug*
Lowercase letters, digits and hyphens. It appears in the URL
name*
A human-readable name
github_repos
GitHub repos that use this library: 'org/repo', or 'org/*' for a whole organisation

* marks a required argument. This table is generated from the server's tools/list response.

Permissions

  • Permissions are never baked into a token. Library access is decided by looking up the member list at request time, so removing someone cuts them off immediately, with no token rotation
  • A library you cannot access returns 404, not 403 — a 403 would tell you that library exists
  • One token does both reading and writing. A leak means documents can be damaged, and the history is the only thing you can recover from