Share a directory with humans
The private session directory, the fixed workspace root that humans and agents share, the private root rule, and the shared pack cache.
By default an MCP server keeps its notebook to itself. That is the right setting for a fleet of agents and the wrong one for a person who wants to open the files. This guide covers the switch between the two, and the caching decision that follows it.
The default: a private session directory
serve with neither root configured takes a per-process session
directory and puts both roots inside it:
<tmp>/slivingdoc-<random>/notebook the workspace root
<tmp>/slivingdoc-<random>/private the private root
Nothing has to be configured or coordinated: every server gets its own
notebook directory and its own private state, so concurrent agents never
contend for one operation lock. The tools then need no path, and both
the server instructions and every tool result name the directory.
The whole session directory is removed at shutdown. Nothing of value is in it — the durable notebook is the bucket. A process killed outright leaves the directory for the operating system to reap; no later process reuses it.
The switch: a fixed workspace root
Configuring either root turns the default off, and neither root is removed at shutdown:
export SLIVINGDOC_BUCKET=my-notes
slivingdoc serve --workspace-root /srv/notes
Use that when humans and agents share one directory, or when you want the notebook to survive a server restart on disk. In an MCP host configuration it is two more arguments:
{
"mcpServers": {
"slivingdoc": {
"command": "npx",
"args": ["-y", "slivingdoc", "serve", "--workspace-root", "/srv/notes"],
"env": {
"SLIVINGDOC_BUCKET": "my-notes",
"AWS_PROFILE": "notes"
}
}
}
}
--workspace-root is the root below which request paths may live, and it
is also the notebook directory an omitted path resolves to. With it set,
path can address any directory below it.
pull and commit never take a session directory. They default to the
working directory, which you can still open after the process exits.
Working in the shared directory
The host and the server share the visible directory. Agents and people edit files there with whatever tools they already have, and the server scans them at each call. There is no protocol between calls:
- A person edits
/srv/notes/today.mdin an editor. The nextnotes_commitfor that path publishes the change, and so doesslivingdoc commit /srv/notes -m "..."run by hand. - An agent commits. The person’s next
slivingdoc pull /srv/notesbrings the change down. - Both edit different lines of one file. The merge takes both.
- Both edit the same lines. The commit returns a conflict with markers in the file, instead of losing either side.
Files must be valid UTF-8 text without the NUL character. Empty files are valid, and bytes and line endings are preserved. Symbolic links, devices, sockets, and named pipes are rejected.
Note: Sharing needs
--workspace-root. A session directory is private to the server process, and it is deleted when that process stops.
The private root
The private root holds the internal Git repository, the state record, and the operation locks. It is not the notebook, and nothing edits it by hand.
slivingdoc serve \
--workspace-root /srv/notes --private-root /var/lib/slivingdoc/private
Warning: The private root must not sit at or below the workspace root, and the two must never be the same directory. Startup refuses otherwise. Both roots become absolute before startup.
When only --workspace-root is set, the private root falls back to the
user cache directory rather than to the workspace; the rule above is
about what you may configure, not about a default you can trip over.
The shared pack cache
By default every workspace keeps its own cache of downloaded pack bytes
inside its private state. Several agents on one machine therefore each
download the same packs, and an ephemeral session throws its cache away
at shutdown. --shared-pack-cache moves that cache to one durable
directory per notebook:
<user-cache-dir>/slivingdoc/pack-cache/<bucket>-<prefix>-<digest>/
Every server addressing the same endpoint, bucket, and prefix computes the same directory from its own configuration, so agents share downloads with no coordination: the first cold pull populates the directory, and later pulls by any agent read from it. Entries are keyed by SHA-256 and re-verified against the authoritative manifest on every read, so a corrupt or foreign entry is discarded and downloaded again, never trusted.
Only pack bytes are shared. Each workspace keeps its own private repository, baseline, and locks.
Note: Writing into the cache is best-effort. A read-only or full cache directory logs a warning and the operation continues, which is what makes a pre-populated read-only cache — baked into a container image, for example — work as it is.
The directory names make manual cleanup easy: remove a notebook’s directory when you are done with it, and the next pull downloads again.
Next
- Restrict agents with path policies — which parts of a shared notebook one process may change.
- Resolve conflicts — what happens when two writers change the same lines.
- Configuration — the three flags on this page beside every other setting.