Use the CLI without a host
Pull and commit by hand, how a notebook path resolves, how to read the success and error reports, and how to drive both from scripts.
pull and commit are the human mirror of the two MCP tools. They take
the same flags as serve, run the same startup sequence, perform one
operation, print the result, and exit. Startup is the pinned engine check
and then the store check: the S3 compatibility probe (skipped when a
recent proof is on record, see Set up a bucket),
or an access check against hosted storage. No MCP host is involved, and no daemon is
left behind.
export SLIVINGDOC_BUCKET=my-notes
slivingdoc pull notes
# edit UTF-8 text files under notes/
slivingdoc commit notes -m "meeting summary"
That is the whole loop. pull writes the current notebook into the
directory. commit publishes what you changed there and merges in any
concurrent, non-conflicting changes other writers published meanwhile.
With hosted storage there are two ways to authenticate, and neither needs AWS settings:
# on your own machine: log in once through the browser
slivingdoc login
slivingdoc space notes # only needed to pick a default space
slivingdoc pull notes
# in CI or any environment without a browser
export SLIVINGDOC_TOKEN=<your-api-token>
slivingdoc pull notes
slivingdoc login stores an account login on this machine, and
slivingdoc logout revokes and removes it. slivingdoc space lists the
spaces the login reaches, and slivingdoc space <name> sets the default
one. A token reaches exactly one space, which it names itself; a stored
login uses --space, then SLIVINGDOC_SPACE, then the default space.
--storage auto|hosted|s3 (or SLIVINGDOC_STORAGE) forces the choice.
Under the default auto, a token beside --endpoint, AWS_ENDPOINT_URL
or AWS_ENDPOINT_URL_S3 is refused as ambiguous; pass --storage hosted
to say the endpoint is the hosted one. The token needs slivingdoc 0.2.2
or newer, and the stored login 0.2.4 or newer. See
Use hosted storage and
Configuration.
The first pull into a directory is guarded. If the directory already
holds files, each one must be in the notebook with identical bytes, or
the notebook must be empty (the files then seed it). Anything else is
refused as INVALID_REQUEST with the reason DIRECTORY_NOT_EMPTY, and
nothing is changed. Pull into a new or empty directory first.
The notebook path
Each subcommand takes at most one notebook path. It may come before or after the flags.
- Omitting it uses the workspace root, which is the working directory
unless
--workspace-rootsays otherwise. - A path that begins with
~/resolves against the current user’s home directory. - Any other relative path resolves against the working directory.
- The resolved path must stay at or below the workspace root.
commit also requires a message, -m or --message. A missing message,
or more than one path, exits nonzero before any native or network
dependency is touched — so a typo in a script fails fast and costs
nothing.
The success report
A subcommand that succeeds writes its report to standard output and exits zero:
OK generation 18 /home/me/notes
archive/old.md -3
notes/a.md +1 -1
notes/c.md +2
3 files changed, 3 insertions(+), 4 deletions(-)
Line by line:
OKis the status token,generation 18is the accepted remote generation the operation ended on, and the last field is the notebook directory the operation worked in.- One line per changed file, with its insertion and deletion counts. A
zero count is left out, so
-3means deletions only. - The totals trailer closes the report.
The per-file counts answer “what is new to check out”. For pull they
are the delta between the directory as it was and the materialized
result. For commit they are the increment your publication added over
the remote state it observed. A synchronization that changed nothing
reports an empty stat.
The error report
A domain error prints the same skeleton to standard output, prints
error: <CODE> on standard error, and exits 1:
CONTENT_CONFLICT · MERGE_CONFLICT
Resolve the conflict blocks before notes_commit.
notes/today.md conflict lines 12-18, 40-42
next: edit the files, then commit
retryable: false
- The status line is the error code, a middle dot, and the reason token.
- Then the message.
- Then one line per affected file: its reason in lower-case words, and its one-based inclusive line ranges when the reason has them.
next:names your next step, andretryable:says whether trying again unchanged can help.- A recovery report follows when the operation performed one.
Both reports end with the same path-policy trailers when the process is
configured with them: a writable: trailer naming the configured
writable set, then a read-only: trailer naming the configured read-only
set, and — when both are set — a path-rule: longest match decides
trailer, because the two sets can name the same region at different
depths. See
Restrict agents with path policies.
Errors lists every code, reason, and action.
CONTENT_CONFLICT has its own guide:
Resolve conflicts.
On a terminal
A terminal gets extra presentation; a script gets none of it.
- While
pullorcommitruns, standard error shows a progress line with a spinner, for examplePulling /home/me/notes · space notes · 1.2s. The verb isPullingorPublishing, then the resolved path, then the space or bucket. It is cleared when the operation ends. Standard output never carries it. - The report is coloured, and the status line gains a mark:
✓beforeOK,✗before an error, and→in place ofnext:. - A refusal at startup is one line on standard error,
error: <message>in a script and✗ <message>on a terminal.
Standard output and standard error are each judged on their own. Piped or
redirected output is plain text without marks or escape codes, so the
lines a script reads (OK generation 18 <dir>, next:) are stable.
Any non-empty NO_COLOR disables the colour even on a terminal.
From scripts and cron
Nothing about the two commands is interactive, so a script can drive them directly:
- Read the exit status. Zero is success. Every failure exits 1: a domain
error leaves its report on standard output, and a startup refusal
leaves standard output empty and one
error:line on standard error. - Redirected output is already plain text. Set
NO_COLORas well if the job may run attached to a terminal. - Standard output carries only the report. Logs go to standard error,
where
LOG_LEVELcontrols them. See Logging and profiling. - Configure the job through the environment (
SLIVINGDOC_BUCKET,AWS_REGION, and the rest) instead of a long flag list. Flags override environment variables, and the environment overrides the defaults. PreferSLIVINGDOC_TOKENfor hosted storage in a job; the stored login is meant for a person’s own machine.
Warning:
serveresolves the AWS credential chain once and holds the session, but everypullorcommitinvocation resolves it fresh. With short-lived STS or SSO credentials, each scheduled run needs a currently valid session. The recorded probe proof does not bind credentials, so an expired session is refused by the first request the run makes, not at startup.
Next
- Share a directory with humans — when an agent and a person work in the same directory.
- Configuration — every flag and environment variable.
- CLI — the command reference.