# Configuration

> Every flag, environment variable, and default, with precedence rules, hosted mode, and the session-directory and shared-cache notes.

Canonical URL: https://www.slivingdoc.dev/docs/v0.1/reference/configuration/ · Version: 0.1 · Updated: 2026-09-27

Full site index: https://www.slivingdoc.dev/llms.txt

`serve`, `pull`, and `commit` read the same flags and environment
variables. Flags override environment variables, and the environment
overrides defaults. In S3 mode a bucket is required, as `--bucket` or
as `SLIVINGDOC_BUCKET`; in hosted mode the token names its space. `-h` on any of the three prints
the same reference. A non-empty `SLIVINGDOC_TOKEN` switches to hosted
storage; see [Hosted mode](#hosted-mode).

| Function                     | Flag                     | Environment variable              | Default                             |
| ---------------------------- | ------------------------ | --------------------------------- | ----------------------------------- |
| Hosted API token (0.2.0+)    | none                     | `SLIVINGDOC_TOKEN`                | empty (S3 mode)                     |
| Bucket or hosted space       | `--bucket`               | `SLIVINGDOC_BUCKET`               | S3: required; hosted: token's space |
| S3 object prefix             | `--prefix`               | `SLIVINGDOC_PREFIX`               | `slivingdoc`                        |
| S3 region                    | `--region`               | `AWS_REGION`                      | `us-east-1`                         |
| S3 endpoint                  | `--endpoint`             | `AWS_ENDPOINT_URL_S3`             | empty (AWS resolution)              |
| Hosted API endpoint (0.2.0+) | `--endpoint`             | `SLIVINGDOC_ENDPOINT`             | `https://api.slivingdoc.dev`        |
| S3 path-style access         | `--path-style`           | `SLIVINGDOC_PATH_STYLE`           | `false`                             |
| Workspace root               | `--workspace-root`       | `SLIVINGDOC_WORKSPACE_ROOT`       | session dir / working dir           |
| Private state root           | `--private-root`         | `SLIVINGDOC_PRIVATE_ROOT`         | session dir / user cache            |
| Shared pack cache            | `--shared-pack-cache`    | `SLIVINGDOC_SHARED_PACK_CACHE`    | `false`                             |
| CAS retry limit              | `--commit-retries`       | `SLIVINGDOC_COMMIT_RETRIES`       | `8` (0..100)                        |
| Checkpoint pack count        | `--checkpoint-packs`     | `SLIVINGDOC_CHECKPOINT_PACKS`     | `256` (minimum 1)                   |
| Retained checkpoints         | `--retained-checkpoints` | `SLIVINGDOC_RETAINED_CHECKPOINTS` | `1` (0..64)                         |
| Read-only paths              | `--read-only-paths`      | `SLIVINGDOC_READ_ONLY_PATHS`      | empty (no read-only path)           |
| Writable paths               | `--writable-paths`       | `SLIVINGDOC_WRITABLE_PATHS`       | empty (no confinement)              |
| Log levels                   | `--log-level`            | `LOG_LEVEL`                       | `info`                              |
| Log timestamps               | `--log-timestamp`        | `SLIVINGDOC_LOG_TIMESTAMP`        | `true`                              |

`--workspace-root` is the root below which request paths may live, and is
also the notebook directory an omitted path resolves to. The private root
holds the internal Git repository, the state record, and the operation
locks. It must not be at or below the workspace root. Both roots become
absolute before startup.

## Hosted mode

A non-empty `SLIVINGDOC_TOKEN` makes `serve`, `pull`, and `commit` store
the notebook through the hosted storage API at slivingdoc.dev instead of
S3. The token has no flag, so it never appears in a process listing.
Hosted mode needs slivingdoc 0.2.0 or newer: a 0.1.x release ignores
the token and stays in S3 mode. What changes:

- A token reaches exactly one space, and from slivingdoc 0.2.2 on the
  space comes from the token: `--bucket` / `SLIVINGDOC_BUCKET` can be
  left out. When given, it must be 1 to 63 lowercase letters, digits,
  and inner hyphens, and name the token's own space; a different space
  stops startup with `the token reaches hosted space "<space>", not
"<bucket>" ...`. Releases 0.2.0 and 0.2.1 need `--bucket`.
- The endpoint is `--endpoint`, else `SLIVINGDOC_ENDPOINT`, else
  `https://api.slivingdoc.dev`. It must be `https` unless the host is
  loopback.
- `AWS_REGION`, `AWS_ENDPOINT_URL_S3`, and the AWS credential chain are
  not read. `--region` is accepted and unused. `--path-style` is
  still parsed and validated, so a bad value still fails, then unused.
- `--prefix` still applies, inside the space.
- The token must be printable ASCII with no white space. A refusal names
  `SLIVINGDOC_TOKEN` and never prints its value.

At startup, instead of the S3 compatibility probe, slivingdoc checks
that the API answers and that the token was granted the space. The
check only reads, so a read-only token passes it; its commits are then
refused. A refused token stops startup with
`hosted storage refused the token: ...; check SLIVINGDOC_TOKEN and --bucket`.

When a commit would take the account past its storage limit it is
refused as `STORAGE_FULL`: nothing is published, your edited files stay
in place, and pulls keep working. slivingdoc first tries to compact the
space into one checkpoint, which lets a commit that deletes notes shrink
a full space. Past the monthly request allowance, writes are refused as
`REQUEST_LIMIT` and reads slow down, then return `RATE_LIMITED`. Limits
and prices are on [Pricing](/pricing/).

> **Warning:** With `SLIVINGDOC_TOKEN` set, every command runs in hosted
> mode, and an `--endpoint` on the command line receives the token, even
> one copied from an S3 setup. Unset the token before working against a
> bucket.

## How values are read

Flags override environment variables, which override defaults — with one
sharp edge: an explicitly empty flag value does **not** fall back to the
environment. `--read-only-paths=` clears an inherited
`SLIVINGDOC_READ_ONLY_PATHS` rather than falling back to it, and the same
holds for every shared flag. That is how a process asks not to inherit a
setting its parent exported.

Boolean values are parsed as Go booleans, so `true`, `false`, `1`, and
`0` all work. Decimal integer values do not accept a sign. An invalid
flag value refuses startup before any native or network dependency is
touched; the one exception is `LOG_LEVEL`, whose malformed value is
reported and falls back to `info` — see
[Logging and profiling](/docs/v0.1/reference/logging/).

## The session directory

`serve` with neither root configured takes a per-process session directory
and puts both roots inside it:

```text
<tmp>/slivingdoc-<random>/notebook    the workspace root
<tmp>/slivingdoc-<random>/private     the private root
```

This is the default because it needs no configuration and no
coordination: 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 — the durable notebook is the bucket, so nothing of
value is in it. A process killed outright leaves its directory for the
operating system to reap; no later process reuses it, because the derived
private key binds to that random path.

Configuring either root turns the default off, and neither root is
removed at shutdown. Use that when humans and agents share one
directory, or when you want the notebook to survive a server restart on
disk. `pull` and `commit` never take a session directory: they default
to the working directory, which you can still open after the process
exits.

## The shared pack cache

By default every workspace keeps its own cache of downloaded pack bytes
inside its private state, so several agents on one machine 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:

```text
<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 re-downloaded,
never trusted. Only pack bytes are shared: each workspace keeps its own
private repository, baseline, and locks.

The directory names make manual cleanup easy. Remove a notebook's
directory when you are done with it, and the next pull simply
re-downloads.

> **Note:** Writing into the shared 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-is.

> **Warning:** `--workspace-root` and `--private-root` must never point at
> the same directory, and the private root must not sit at or below the
> workspace root. Startup refuses otherwise.

See [S3 requirements](/docs/v0.1/reference/s3/) for the bucket permissions
this configuration assumes, and
[Restrict agents with path policies](/docs/v0.1/guides/path-policies/) for
`--read-only-paths` and `--writable-paths` in practice.
