# `scribe-server` CLI reference

Storage service and offline maintenance.

`scribe-server` owns authoritative repository history and objects. It initializes
storage, serves client requests, checks integrity, and performs offline backup,
restore, metadata transfer, and migration. It also provides certificate tools
and remote user/grant administration conveniences.

A server or offline maintenance process exclusively locks its data root. Stop
the service before offline maintenance. `checkpoint` delegates online backup to
the owning service, and `integrity-status` reads saved reports without opening
the root. `serve` opens an existing root; initialization and migration are
explicit commands. `doctor` and `verify` report without repairing data.

Use the [server guide](/docs/server-usage.md) for configuration and startup,
[operations guide](/docs/operations.md) for running a service, and
[maintenance guide](/docs/migration-backup-restore.md) for recovery procedures.

[scribe](/docs/reference/cli/scribe.md) | [scribe-auth](/docs/reference/cli/scribe-auth.md) | [scribe-ctl](/docs/reference/cli/scribe-ctl.md) | [scribe-gateway](/docs/reference/cli/scribe-gateway.md) | [scribe-runner](/docs/reference/cli/scribe-runner.md)

## Reading this reference

Command synopses below come from this checkout’s built `--help` output.
Angle brackets denote values, square brackets optional arguments, and `...`
repeatable arguments. `[OPTIONS]` includes the global options below and any
command-specific options. Global options work before or after a subcommand;
parent-group options also apply to their child commands. Use `--` to end option
parsing when passing a positional path that starts with a dash.

Run `scribe-server --help` for the command list, `scribe-server COMMAND --help` for
command help, and `scribe-server --version` for the build version. The command sections below cover every public action.

## Help and version

`-h` / `--help` works at every command level. `-V` / `--version` is a top-level
option; place it directly after the executable name.

## Global options

| Argument or option | Meaning |
| --- | --- |
| `--json` | Emit JSON command results on stdout. Diagnostics remain on stderr |
| `--timings` | Report nested phase timings to the diagnostic sink (text or --log-format json) |
| `--log-level <LEVEL>` | off\|error\|warn\|info\|debug\|trace |
| `--log-filter <FILTER>` | Target filter, e.g. 'warn,scribe_server=info,scribe_objects=debug' |
| `--log-format <FORMAT>` | text\|json |
| `-v, --verbose...` | -v for debug, -vv for trace |
| `-q, --quiet` | Errors only, no progress |

## Defaults and configuration

Most data-root commands accept `--config FILE` or `--data-dir DIR`;
`auth-init`, `repair-objects`, `compact-objects`, `recover-submissions`, and
`recovery-archive` accept only `--data-dir DIR`. `checkpoint` and
`integrity-status` take the running server's `--runtime-dir` instead of a data
root. Each command section lists its options. `SCRIBE_SERVER_CONFIG` can supply
the configuration path for `serve`.
CLI overrides take precedence; relative CLI paths resolve from the working
directory, and TOML paths resolve from the configuration directory. `restore`
selects its source and destination explicitly. Certificates and remote auth
administration do not need a local data root.

The [server TOML reference in the guide](/docs/server-usage.md#configuration-file)
covers settings such as storage workers, transfer admission, pack sizing, and
log retention that have no CLI flag. `serve` defaults to plaintext loopback TCP;
non-loopback plaintext requires `--allow-non-loopback` or its TOML equivalent.
TLS/auth requires all four `[auth]` settings and an `auth-init`-prepared root.

Logging defaults to `info`, on stderr. Selection is CLI, then `SCRIBE_LOG`,
then server logging configuration, then defaults. `--log-format` accepts `text`
or `json`. `--log-level` conflicts with `--log-filter`; `-v`/`--verbose`
selects debug, repeated twice selects trace, and conflicts with `-q`/`--quiet`.
`--timings` independently enables phase timings and requires the default-enabled
`timings` build feature. `--json` controls stdout results independently.

`--verbose` and `--quiet` also conflict with explicit `--log-level` or
`--log-filter`. Choose one verbosity/filter selection. Text diagnostics are the
default; redirected output is plain and `NO_COLOR=1` disables terminal colors.

## Command index

- [certs](/docs/reference/cli/scribe-server.md#certs) — Create a private CA or issue server PEM certificates
- [certs init-ca](/docs/reference/cli/scribe-server.md#certs-init-ca) — Create ca.pem and ca-key.pem in a new directory. Keep the CA key offline
- [certs issue](/docs/reference/cli/scribe-server.md#certs-issue) — Issue server.pem (the certificate followed by its CA) and server-key.pem using an existing Scribe CA
- [init](/docs/reference/cli/scribe-server.md#init) — Create a new, empty data root and write a configuration file
- [serve](/docs/reference/cli/scribe-server.md#serve) — Run the service (plaintext TCP by default; TLS with the --auth options)
- [auth-init](/docs/reference/cli/scribe-server.md#auth-init) — Initialize versioned security ownership state while the data root is offline
- [users](/docs/reference/cli/scribe-server.md#users) — Manage users in the shared auth service using operator credentials
- [users add](/docs/reference/cli/scribe-server.md#users-add) — Create a user; set their login password with `users password`
- [users password](/docs/reference/cli/scribe-server.md#users-password) — Set/reset a login password and invalidate every existing user session
- [users list](/docs/reference/cli/scribe-server.md#users-list) — List users and service accounts: key, ID, name, enabled, administrator, kind (at most 256 rows; continue with --after LAST_KEY)
- [users disable](/docs/reference/cli/scribe-server.md#users-disable) — Disable a user and revoke every credential they hold (enabling again revives none)
- [users enable](/docs/reference/cli/scribe-server.md#users-enable) — Re-enable a disabled user
- [permissions](/docs/reference/cli/scribe-server.md#permissions) — Manage per-repository grants in the shared auth service
- [permissions set](/docs/reference/cli/scribe-server.md#permissions-set) — Give a user a role on one repository (replaces any existing role)
- [permissions revoke](/docs/reference/cli/scribe-server.md#permissions-revoke) — Remove a user's role on one repository
- [permissions list](/docs/reference/cli/scribe-server.md#permissions-list) — List grants, optionally for one repository (at most 256 rows; continue with --after LAST_KEY)
- [verify](/docs/reference/cli/scribe-server.md#verify) — Verify repository structure and, with --full, every object's bytes
- [doctor](/docs/reference/cli/scribe-server.md#doctor) — Fast, exhaustive, read-only health check of a data root (refuses to run beside a live server). Exit 0 healthy, 1 problems, 2 could not run
- [integrity-status](/docs/reference/cli/scribe-server.md#integrity-status) — Read saved online object-verification coverage and findings. Does not open the data root. Exit 0 checked, 1 findings, 2 incomplete/unavailable
- [usage](/docs/reference/cli/scribe-server.md#usage) — Space and record counts for every repository in a data root: head, live paths, objects, loose/packed/metadata sizes, and filesystem capacity. Read-only; refuses to run beside a live server (exit 2)
- [backup](/docs/reference/cli/scribe-server.md#backup) — Exclusive offline backup of the whole data root into an empty directory
- [checkpoint](/docs/reference/cli/scribe-server.md#checkpoint) — Ask the running server to take an online incremental backup
- [restore-checkpoint](/docs/reference/cli/scribe-server.md#restore-checkpoint) — Restore the latest completed online checkpoint into a new data root
- [restore](/docs/reference/cli/scribe-server.md#restore) — Restore a backup into an empty destination and assign a new incarnation
- [export-metadata](/docs/reference/cli/scribe-server.md#export-metadata) — Engine-neutral logical export of one repository's metadata
- [import-metadata](/docs/reference/cli/scribe-server.md#import-metadata) — Import a logical metadata export into a repository directory that has objects but no metadata database
- [rebuild-locator](/docs/reference/cli/scribe-server.md#rebuild-locator) — Rebuild the object locator index of one or every repository from its packs and loose files (explicit offline repair; refuses to run beside a live server)
- [repair-objects](/docs/reference/cli/scribe-server.md#repair-objects) — Preview or apply verified offline object repair without rolling back history
- [compact-objects](/docs/reference/cli/scribe-server.md#compact-objects) — Reclaim unreferenced objects and repack retained bytes offline; rerun to resume after a crash
- [recover-submissions](/docs/reference/cli/scribe-server.md#recover-submissions) — Recover interrupted submission staging while holding the data-root lock
- [recovery-archive](/docs/reference/cli/scribe-server.md#recovery-archive) — Verify, consolidate, relocate, or restore an independent metadata archive offline
- [staging-branches](/docs/reference/cli/scribe-server.md#staging-branches) — List branch snapshots left unfinished by an interrupted branch creation and, with --abandon, discard one so its name is available again (refuses to run beside a live server; never touches an active branch)
- [migrate](/docs/reference/cli/scribe-server.md#migrate) — Apply supported metadata upgrades within the shared-snapshot format

## certs

Create a private CA or issue server PEM certificates

```text
scribe-server certs [OPTIONS] <COMMAND>
```

Subcommands: [init-ca](/docs/reference/cli/scribe-server.md#certs-init-ca), [issue](/docs/reference/cli/scribe-server.md#certs-issue).

## certs init-ca

Create ca.pem and ca-key.pem in a new directory. Keep the CA key offline

```text
scribe-server certs init-ca [OPTIONS] --out <NEW_DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--out <NEW_DIR>` | New directory to receive the certificate and private-key PEM files |
| `--days <DAYS>` | Certificate lifetime in days [default: 3650] |

Output directories must be new. Certificate lifetimes accept 1–3650 days.

## certs issue

Issue server.pem (the certificate followed by its CA) and server-key.pem using an existing Scribe CA

```text
scribe-server certs issue [OPTIONS] --ca <DIR> --out <NEW_DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--ca <DIR>` | Directory containing ca.pem and ca-key.pem |
| `--out <NEW_DIR>` | New directory to receive the certificate and private-key PEM files |
| `--dns <DNS>` | Exact DNS name clients use; repeat for additional names (no wildcards) |
| `--ip <IP>` | IP address clients use; repeat for additional addresses |
| `--days <DAYS>` | Lifetime in days; the CA must remain valid for this entire period [default: 365] |

Output directories must be new. Certificate lifetimes accept 1–3650 days. Provide at least one `--dns` or `--ip`; both are repeatable. DNS wildcards are not accepted. The CA must remain valid throughout the requested leaf lifetime.

## init

Create a new, empty data root and write a configuration file

```text
scribe-server init [OPTIONS] --data-dir <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | New or empty directory for repositories and metadata |
| `--config-out <FILE>` | Where to write the configuration (refuses to overwrite without --force) |
| `--listen <ADDR>` | Listen address written into the configuration [default: tcp://127.0.0.1:7447] |
| `--force` | Overwrite an existing configuration file |

`--data-dir` is required. `--config-out` is optional: omit it to initialize only the data root. `--force` permits overwriting the configuration file, never a nonempty data root.

## serve

Run the service (plaintext TCP by default; TLS with the --auth options)

```text
scribe-server serve [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--auth-namespace <NAMESPACE>` | Namespace this server was registered in (`scribe-auth servers add --namespace`) |
| `--auth-credential <FILE>` | This server's credential file (`scribe-auth credentials create --server`): the auth endpoint, its CA, and this server's device key and certificate |
| `--tls-cert <FILE>` | This server's certificate PEM; clients see its CA fingerprint on first connection |
| `--tls-key <FILE>` | This server's private key PEM |
| `--config <FILE>` | Configuration file (or SCRIBE_SERVER_CONFIG); flags override it |
| `--data-dir <DIR>` | Data root created by init |
| `--log-dir <DIR>` | Daily log files here instead of stderr |
| `--runtime-dir <DIR>` | Holds scribe-server.pid, listen, and shutdown-request (default <data-dir>/run) |
| `--listen <ADDR>` | tcp://host:port; port 0 picks a free port, reported in <runtime-dir>/listen |
| `--allow-non-loopback` | Acknowledge that the plaintext protocol will be exposed beyond loopback |

The four auth settings (`--auth-namespace`, `--auth-credential`, `--tls-cert`,
`--tls-key`, or `namespace`, `credential`, `tls_cert`, `tls_key` in `[auth]`)
must resolve together; otherwise startup fails with `auth requires namespace,
credential, TLS certificate and TLS key`. An `[auth]` table with no keys is
refused rather than read as plaintext. CLI values can override TOML. The auth
endpoint and the CA of the auth service's TLS certificate come from the
credential file, which holds this server's device key; see
[credential files](/docs/auth.md#credential-files). The credential file and
the TLS key must be outside the data directory. With auth, the listener speaks
TLS 1.3 only and accepts only the hybrid post-quantum key exchange
`X25519MLKEM768`; clients authenticate with access certificates, verified
against the access CAs the server fetches from auth.

The runtime directory is created private (0700 on Unix); an existing one that
group or other accounts can write is refused, because its files stop the
server and request backups. Stop with SIGINT, SIGTERM, or the runtime
directory’s `shutdown-request` file; started durable work finishes before exit.

## auth-init

Initialize versioned security ownership state while the data root is offline

```text
scribe-server auth-init [OPTIONS] --data-dir <DIR> --namespace <NAMESPACE>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | Data root created by init |
| `--namespace <NAMESPACE>` | Namespace this server was registered in at the auth service |

## users

Manage users in the shared auth service using operator credentials

```text
scribe-server users [OPTIONS] <COMMAND>
```

| Argument or option | Meaning |
| --- | --- |
| `--admin-credential <FILE>` | Administrator credential file (written by `init`, `credentials create`, `admin-credential issue`, `migrate`, `restore` or `scribe login --admin`): the auth endpoint, its CA, and the administrator's device key and certificate |
| `--state-dir <STATE_DIR>` | Durable pending administrative requests. Defaults to `auth-admin` in the Scribe configuration directory |

Subcommands: [add](/docs/reference/cli/scribe-server.md#users-add), [password](/docs/reference/cli/scribe-server.md#users-password), [list](/docs/reference/cli/scribe-server.md#users-list), [disable](/docs/reference/cli/scribe-server.md#users-disable), [enable](/docs/reference/cli/scribe-server.md#users-enable).

The options above apply to every `users` subcommand. `--admin-credential` is
required for remote administration; the auth endpoint and its CA come from the
file. A storage server's credential cannot administer users. `--state-dir`
retains pending requests for durable retries; it is created private and must
not be inside a `.scribe` directory. The Scribe configuration directory is the
same root as `scribe --config-dir` / `SCRIBE_CONFIG_DIR`. These actions match
`scribe-auth users`.

## users add

Create a user; set their login password with `users password`

```text
scribe-server users add [OPTIONS] <NAME>
```

| Argument or option | Meaning |
| --- | --- |
| `<NAME>` | Short username or email-style principal, e.g. [alice@company.example](mailto:alice@company.example) |
| `--administrator` | Make the user a central auth administrator |
| `--service` | Create a service account: no password or sign-in, never an administrator, at most writer grants; issue its credential with `scribe-auth credentials create --service` |

`--service` conflicts with `--administrator`. Issue a service account's
credential file with
[`scribe-auth credentials create --service`](/docs/reference/cli/scribe-auth.md#credentials-create).

## users password

Set/reset a login password and invalidate every existing user session

```text
scribe-server users password [OPTIONS] --password-file <FILE> <NAME>
```

| Argument or option | Meaning |
| --- | --- |
| `<NAME>` | Username whose password to set |
| `--password-file <FILE>` | File containing the password; never supplied as a command-line secret |

## users list

List users and service accounts: key, ID, name, enabled, administrator, kind (at most 256 rows; continue with --after LAST_KEY)

```text
scribe-server users list [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--after <KEY>` | Pagination cursor: the first column of the last row shown [default: ""] |

The kind column is `person` or `service`. Results are paginated, at most 256 rows. Pass the last row’s first column as `--after KEY` to continue.

## users disable

Disable a user and revoke every credential they hold (enabling again revives none)

```text
scribe-server users disable [OPTIONS] <NAME>
```

| Argument or option | Meaning |
| --- | --- |
| `<NAME>` | Username |

Disabling revokes the user's sessions and machine credentials; `users enable`
restores the account, and the user signs in again or receives new credential
files.

## users enable

Re-enable a disabled user

```text
scribe-server users enable [OPTIONS] <NAME>
```

| Argument or option | Meaning |
| --- | --- |
| `<NAME>` | Username |

## permissions

Manage per-repository grants in the shared auth service

```text
scribe-server permissions [OPTIONS] <COMMAND>
```

| Argument or option | Meaning |
| --- | --- |
| `--admin-credential <FILE>` | Administrator credential file (written by `init`, `credentials create`, `admin-credential issue`, `migrate`, `restore` or `scribe login --admin`): the auth endpoint, its CA, and the administrator's device key and certificate |
| `--state-dir <STATE_DIR>` | Durable pending administrative requests. Defaults to `auth-admin` in the Scribe configuration directory |

Subcommands: [set](/docs/reference/cli/scribe-server.md#permissions-set), [revoke](/docs/reference/cli/scribe-server.md#permissions-revoke), [list](/docs/reference/cli/scribe-server.md#permissions-list).

The options above apply to every `permissions` subcommand. Supply `--admin-credential`. These actions match `scribe-auth grants`; repository keys are `NAMESPACE/REPOSITORY_ID`.

## permissions set

Give a user a role on one repository (replaces any existing role)

```text
scribe-server permissions set [OPTIONS] --role <ROLE> <USER> <REPOSITORY>
```

| Argument or option | Meaning |
| --- | --- |
| `<USER>` | Username |
| `<REPOSITORY>` | Repository key: <namespace>/<repository id> as printed by `scribe repo list` |
| `--role <ROLE>` | reader: read and sync; writer: submit and branch; maintainer: also forced unlock [possible values: reader, writer, maintainer] |

Maintainers also activate, change, or remove the `locks.rules` section in
`.scribe/config.toml` on `main`,
including through a merge. Writers can propose rules on other branches.
Profile-only edits retaining the same ordered lock rules remain Writer operations;
see [repository configuration](/docs/repository-config.md). See
[repository roles](/docs/auth.md#credentials-and-roles).

## permissions revoke

Remove a user's role on one repository

```text
scribe-server permissions revoke [OPTIONS] <USER> <REPOSITORY>
```

| Argument or option | Meaning |
| --- | --- |
| `<USER>` | Username |
| `<REPOSITORY>` | Repository key: <namespace>/<repository id> |

## permissions list

List grants, optionally for one repository (at most 256 rows; continue with --after LAST_KEY)

```text
scribe-server permissions list [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--repo <REPOSITORY>` | Repository key: <namespace>/<repository id> |
| `--after <KEY>` | Pagination cursor: the first column of the last row shown [default: ""] |

Results are paginated, at most 256 rows. Pass the last row’s first column as `--after KEY` to continue.

## verify

Verify repository structure and, with --full, every object's bytes

```text
scribe-server verify [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--full` | Re-hash every object (slow on large repositories) |
| `--repo <REPO>` | Only this repository (name or id) |

## doctor

Fast, exhaustive, read-only health check of a data root (refuses to run beside a live server). Exit 0 healthy, 1 problems, 2 could not run

```text
scribe-server doctor [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Only this repository (name or id) |
| `--threads <N>` | Hashing threads (default: available parallelism, at most 64) |
| `--quick` | Skip re-hashing chunk bytes; still checks every header and hashes structured objects |

Alias: `scan`. Threads default to available parallelism, capped at 64. Exit 0 means healthy, 1 means reported problems, and 2 means the check could not run. This command never repairs data.

## integrity-status

Read saved online object-verification coverage and findings. Does not open the data root. Exit 0 checked, 1 findings, 2 incomplete/unavailable

```text
scribe-server integrity-status [OPTIONS] --runtime-dir <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--runtime-dir <DIR>` | Serving process runtime directory, containing integrity progress |
| `--repo <ID>` | Only this repository id |

Reads saved reports without opening the data root, so it runs beside a live
server. `--json` emits one structured report. Exit 0 means completed saved
coverage without findings, 1 means findings, and 2 means incomplete/unavailable
reports. See [online integrity checking](/docs/online-integrity.md) for scope,
scheduling, and progress recovery. Saved coverage is not a live health
guarantee.

## usage

Space and record counts for every repository in a data root: head, live paths, objects, loose/packed/metadata sizes, and filesystem capacity. Read-only; refuses to run beside a live server (exit 2)

```text
scribe-server usage [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Only this repository (name or id) |

Alias: `df`. Exit 0 means success, 1 means reported problems, and 2 means the inventory could not run. Stop the service before running it.

## backup

Exclusive offline backup of the whole data root into an empty directory

```text
scribe-server backup [OPTIONS] --to <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--to <DIR>` | Empty destination directory; receives every durable file plus BACKUP_MANIFEST |

## checkpoint

Ask the running server to take an online incremental backup

```text
scribe-server checkpoint [OPTIONS] --runtime-dir <RUNTIME_DIR> --to <TO>
```

| Argument or option | Meaning |
| --- | --- |
| `--runtime-dir <RUNTIME_DIR>` | Runtime directory belonging to the running server |
| `--to <TO>` | Backup store, reused for subsequent incremental checkpoints |

Works with authenticated and unauthenticated servers. The owning server pins
committed metadata and copies missing objects while continuing to serve requests.
The store holds every repository, private ones included, so `--to` must be an
absolute path that is neither inside the data root nor contains it
(`checkpoint destination must be an absolute path outside the data root`). The
server creates it private (0700 on Unix) and refuses one that group or other
accounts can write, or that contains links or special files. Checkpoint files are written as new private files (0600 on Unix), never
through an existing entry.
Keep the complete backup store, including the checkpoint chain. See the
[checkpoint procedure](/docs/migration-backup-restore.md#online-incremental-checkpoints).

## restore-checkpoint

Restore the latest completed online checkpoint into a new data root

```text
scribe-server restore-checkpoint [OPTIONS] --from <FROM> --to <TO>
```

| Argument or option | Meaning |
| --- | --- |
| `--from <FROM>` | Online backup store |
| `--to <TO>` | New destination directory (must not exist) |

Replays checksummed metadata journals and verifies copied objects before publishing
the destination. Restored roots and repositories receive new incarnations. Failed
restores remain quarantined beside the requested destination for diagnosis.

## restore

Restore a backup into an empty destination and assign a new incarnation

```text
scribe-server restore [OPTIONS] --from <DIR> --to <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--from <DIR>` | Backup directory written by `backup` |
| `--to <DIR>` | Empty directory that becomes the new data root |

## export-metadata

Engine-neutral logical export of one repository's metadata

```text
scribe-server export-metadata [OPTIONS] --repo <REPO> --to <FILE>
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Repository name or id |
| `--to <FILE>` | Output file (.scmx) |

## import-metadata

Import a logical metadata export into a repository directory that has objects but no metadata database

```text
scribe-server import-metadata [OPTIONS] --repo <REPO> --from <FILE>
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Repository name or id |
| `--from <FILE>` | Export file written by export-metadata |

## rebuild-locator

Rebuild the object locator index of one or every repository from its packs and loose files (explicit offline repair; refuses to run beside a live server)

```text
scribe-server rebuild-locator [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Only this repository (name or id) |

Every entry is re-hashed before it is indexed; unverifiable bytes are skipped and listed. The rebuilt database replaces the old one only once durable, then each repository is verified structurally. Exit 0 when everything was indexed and verified, 1 when entries were skipped or problems remain.

## repair-objects

Preview or apply verified offline object repair without rolling back history

```text
scribe-server repair-objects [OPTIONS] --data-dir <DIR> --repo <REPO>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | Existing destination data root; held under its exclusive OS lock |
| `--repo <REPO>` | Destination repository name or id |
| `--from <DIR>` | Offline data root or physical backup containing the same repository id. Restore an online checkpoint to a separate root before using it here |
| `--object <ID>` | Also check this kind:full-digest identity, including absent locator rows |
| `--apply` | Apply the previewed repair; default is read-only preview. No changes are installed if any damaged object lacks a verified replacement |
| `--resume` | Finish a verified, prepared swap after interruption, without the donor |
| `--abort` | Discard a preparation only while the original store is still in place |

The default is a read-only preview. `--from` is required unless using
`--resume` or `--abort`. `--apply` prepares, verifies, and installs
replacements while preserving history and damaged evidence. Repeat
`--object <ID>` to additionally check identities outside accepted history.
`--json` emits one structured result. Exit 0 means the requested
preview/action succeeded, 1 means unavailable replacements or remaining
verification problems, and 2 means the command could not run. See
[verified object repair](/docs/object-repair.md).

## compact-objects

Reclaim unreferenced objects and repack retained bytes offline; rerun to resume after a crash

```text
scribe-server compact-objects [OPTIONS] --data-dir <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | Data root created by init |
| `--repo <REPO>` | Only this repository (name or id) |
| `--list-uploads` | List durable upload pins as JSON lines without collecting objects |
| `--abandon-workspace <WORKSPACE_ID>` | Explicitly release this workspace's upload pins; accepted history remains retained |
| `--incremental` | Reuse unchanged packs and rewrite only fragmented packs within a byte budget |
| `--rewrite-budget-mib <REWRITE_BUDGET_MIB>` | Maximum source pack MiB selected for rewriting by incremental compaction [default: 1024] |

Typical invocations:

```sh
scribe-server compact-objects --data-dir DIR [--repo NAME_OR_ID]
scribe-server compact-objects --data-dir DIR [--repo NAME_OR_ID] --incremental [--rewrite-budget-mib 1024]
scribe-server compact-objects --data-dir DIR [--repo NAME_OR_ID] --list-uploads
scribe-server compact-objects --data-dir DIR --repo NAME_OR_ID --abandon-workspace WORKSPACE_ID
```

The default action reclaims unreferenced objects and repacks retained content.
Stop the server first. All accepted history, including deleted files, and the
transitive content of active workspace upload pins are retained. The command
verifies retained bytes before replacing the store. It requires temporary disk
space for a complete copy of retained data plus its temporary graph index.

`--incremental` reuses unchanged payloads with hard links and rewrites packs below
80% live while their total source sizes fit `--rewrite-budget-mib` (default 1024).
Zero allows reclamation without rewriting live payloads. Reachability and copy
progress are durable; rerun this mode after interruption. The saved selection is
reused; a lower budget that cannot fit it is refused. Additional disk includes
selected payloads, staging and repository-sized mark/locator indexes. This mode
does not verify reused payload bytes; use doctor or full compaction to scrub them.

`--list-uploads` emits one JSON line per pin, with its workspace, identity, and
active state. `--abandon-workspace` explicitly releases that workspace's upload
pins; it does not collect objects in the same invocation. Use it only when those
unfinished uploads are no longer needed. Workspace retirement also deactivates
pins. Accepted history remains protected regardless of pin state.

After interruption, rerun `compact-objects` to finish the recorded swap. Serving
and locator rebuild refuse a pending swap. Corrupt relocated objects stop
compaction; full mode verifies every retained object. The original store stays
intact until the replacement is durable. Incremental mode restarts scratch work
when its metadata boundary changes before a swap marker is published; a changed
boundary after marker publication refuses installation. Compaction is offline;
distributed garbage collection and online pack reader coordination are not
implemented here.

## recover-submissions

Recover interrupted submission staging while holding the data-root lock

```text
scribe-server recover-submissions [OPTIONS] --data-dir <DIR>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | Data root created by init |

Explicit offline recovery of interrupted submission preparation, under the
exclusive data-root lock. Removes unaccepted staging rows, clears accepted undo
inventories, and consolidates accepted rename lock transfers in bounded
transactions. Accepted history and original operation outcomes are preserved.
Normal server startup uses the same recovery implementation.

## recovery-archive

Verify, consolidate, relocate, or restore an independent metadata archive offline

```text
scribe-server recovery-archive [OPTIONS] --data-dir <DIR> --database <FILE>
```

| Argument or option | Meaning |
| --- | --- |
| `--data-dir <DIR>` | Existing data root; the command takes its exclusive OS lock |
| `--database <FILE>` | Metadata file relative to the data root, such as catalog.redb |
| `--verify` | Verify the archive without changing its bytes (the default) |
| `--consolidate` | Publish a self-contained base and prune covered journal rows and segments |
| `--relocate <DIR>` | Copy and verify the archive into a new directory, then select that location |
| `--restore-to <FILE>` | Restore into a new quarantined metadata file relative to the data root |
| `--reclaim-pages` | Reclaim unreachable snapshot preparation pages in this repository database |

The actions are mutually exclusive; verification is the default. `--database`
and `--restore-to` are relative paths within the locked data root. Examples are
`catalog.redb`, `auth-state.redb`, and `repos/<repository-id>/metadata.redb`.
`--relocate` requires a new destination directory and retains the original copy.
`--restore-to` requires a new file and writes quarantined metadata, never replacing
the source. `--reclaim-pages` applies to repository metadata only.

Consolidation verifies a full recovery base before pruning covered journal rows
and archive segments. Page reclamation retains every historical root. Both are
restartable offline operations. `--json` returns `{"recovery_end":N}` or, for
reclamation, `{"reclaimed_pages":N}`. See the
[recovery procedure](/docs/migration-backup-restore.md#independent-metadata-recovery-and-retention)
for archive placement, required backups, and quarantine handling.

## staging-branches

List branch snapshots left unfinished by an interrupted branch creation and, with --abandon, discard one so its name is available again (refuses to run beside a live server; never touches an active branch)

```text
scribe-server staging-branches [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--repo <REPO>` | Only this repository (name or id) |
| `--list` | List the unfinished snapshots and change nothing (the default) |
| `--abandon <BRANCH>` | Discard this unfinished snapshot (branch name, branch id, or pending operation id) |

`--abandon` requires `--repo` and conflicts with `--list`; the selector must
match exactly one staging branch. A branch that was activated is history and is
never removed: it is not listed and cannot be selected. Listing changes nothing.

```text
game (c2a5ffbcb70dac2cb19374dea9e4e1bc): 1 staging branch(es)
  lighting (cf0307b1f4a27d0008cfa407674f67a2): operation 7bd0b9c712aa0016d4fe292299f17b12, 8 staged row(s), pinned at change 2, staged at most 0m ago
1 staging branch(es); abandon one with --repo REPO --abandon BRANCH after confirming its client is gone
```

## migrate

Apply supported metadata upgrades within the shared-snapshot format

```text
scribe-server migrate [OPTIONS]
```

| Argument or option | Meaning |
| --- | --- |
| `--config <FILE>` | Configuration file naming the data root |
| `--data-dir <DIR>` | Data root |
| `--dry-run` | Report what would change without writing |
| `--to <TO>` | Stop at `current` (default) or `schema-3` |

The default applies all supported schema and metadata upgrades in order. `--dry-run` reports without writing. Pre-snapshot development generations are incompatible and require their matching build; follow the maintenance guide.

## Use cases

### Inspect a stopped data root

```sh
scribe-server doctor --data-dir ./server-data
scribe-server usage --data-dir ./server-data --json
```

The service must be stopped before these commands take the root lock.
[Server setup](/docs/server-usage.md) covers initialization and startup by hand
(the [minimal-server tutorial](/docs/tutorials/01-minimal-server.md) lets
`scribe-ctl` run them), [bare metal](/docs/manual/bare-metal.md) covers
certificates and auth by hand, and the [maintenance guide](/docs/migration-backup-restore.md)
backup and restore.

## Output and exit codes

Most commands exit 0 on success and 1 on runtime failure; argument errors
exit 2. `doctor` and `usage` exit 1 for reported problems and 2 when they cannot
run. `integrity-status` exits 1 for findings and 2 when saved reports are
incomplete or cannot be read. `repair-objects` exits 1 when a replacement is
unavailable or verification problems remain, and 2 when it could not run.
`verify` exits 1 for findings or inability to run, and so does
`rebuild-locator` for skipped entries or verification problems. `serve --json`
emits its final result after shutdown; use runtime files and logs for readiness.

`--json` selects machine-readable stdout results; diagnostics stay separate.
See [JSON output](/docs/json-output.md) for schemas, help, and error behavior, and
[logging](/docs/logging.md) for filters, sinks, timing events, and build features.
