scribe CLI reference
Documentation/CLI reference
scribe CLI reference42 min read

scribe CLI reference

On this page

Version-control client.

scribe manages repositories and local working copies: add, edit, move, submit, sync, branch, merge/cherry-pick, inspect history, and manage locks. Project commands coordinate selected mounted workspaces. The client connects to a storage server or gateway. It also manages client login sessions and remembered TLS trust. Workspace commands find the workspace root (.scribe/_state/SCRIBE_FORMAT) by walking up from the current directory. Paths for workspace edits must stay inside that workspace. get takes a repository-relative historical path and an explicit local destination; downloads and exports can be written outside the workspace.

For a first round trip, read the tutorial. For daily work, use the client guide and branch and merge guide.

scribe-server | scribe-auth | scribe-ctl | scribe-gateway | scribe-runner

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 -h for the workflow overview, scribe COMMAND -h for a command summary, and scribe COMMAND --help for its full options. Use scribe --version for the build version. The command sections below cover every public action.

Help and version

-h shows common options; --help also includes advanced connection, trust, and diagnostic options. Both work at every command level. -V / --version is a top-level option; place it directly after the executable name.

Global options

Argument or optionMeaning
--server <URL>Server URL (tcp:// or tls://); selection order is documented below
--transfer-compression <none|lz4>Object transfer compression (overrides the workspace preference for this command)
--transfer-jobs <N>Maximum parallel data transfers, 1–8 (default 4; or SCRIBE_TRANSFER_JOBS). Use 1 for serial transfers
--tls-ca <TLS_CA>CA certificates for a tls:// server (or SCRIBE_TLS_CA)
--config-dir <CONFIG_DIR>Override the shared per-user configuration root (or SCRIBE_CONFIG_DIR)
--trust-fingerprint <TRUST_FINGERPRINT>Approve first-use trust, trust replace or trust forget only when this full BLAKE3: fingerprint matches
--credential-file <CREDENTIAL_FILE>Machine credential file from scribe-auth credentials create (or SCRIBE_CREDENTIAL_FILE); never stored in workspace state
--anonymousUse anonymous TLS access; ignore saved sessions and SCRIBE_CREDENTIAL_FILE
--jsonMachine-readable JSON on stdout
--global-ignore <FILE>Global ignore file (lowest precedence)
--timingsReport nested phase timings to the diagnostic sink (text or --log-format json)
--log-level <LEVEL>off|error|warn|info|debug|trace (default warn); diagnostics go to stderr
--log-filter <FILTER>Target filter, e.g. 'warn,scribe_client=debug' (or SCRIBE_LOG)
--log-format <FORMAT>text|json
-v, --verbose...-v for debug, -vv for trace
-q, --quietErrors only, no progress

Defaults and configuration

Server selection is --server, then SCRIBE_SERVER, then the workspace's recorded endpoint, then tcp://127.0.0.1:7447. Both tcp:// and tls:// URLs are supported. Every tls:// connection uses TLS 1.3 with the hybrid post-quantum key exchange X25519MLKEM768; a server or proxy that cannot offer it fails the handshake. The client proves its identity with a short-lived access certificate for its own device key, presented only inside a handshake with a verified server; no password or reusable secret reaches a storage server.

Login defaults to SCRIBE_USERNAME for the username and SCRIBE_AUTH for the auth service URL. Explicit login arguments override these defaults; unset or empty variables require the corresponding argument. Later commands reuse the saved session.

Parallel transfers automatically use up to four data connections when enough work is queued. --transfer-jobs overrides SCRIBE_TRANSFER_JOBS; both accept 1–8. See parallel transfers for scheduling and resource bounds.

Transfer compression is --transfer-compression, then the saved workspace preference, then none. Both none and lz4 are supported. A command override does not change the saved preference, except that workspace creation saves its initial selection. workspace config --compression changes it persistently in .scribe/_state/state.redb. Repository storage compression is a separate, immutable creation policy.

--credential-file or SCRIBE_CREDENTIAL_FILE selects a machine credential file instead of the saved login session; --anonymous conflicts with --credential-file and ignores SCRIBE_CREDENTIAL_FILE. The file holds the auth endpoint, the CA of the auth service's certificate, a device key, and its credential certificate; on Unix it must not be readable by other accounts, and its directory must not be writable by them. The access certificate fetched for it is cached under credentials/ in the configuration root. See credential files. --tls-ca or SCRIBE_TLS_CA selects explicit trust instead of remembered trust. --trust-fingerprint conflicts with --tls-ca. --config-dir, then SCRIBE_CONFIG_DIR, overrides the per-user configuration root. Defaults are ~/Library/Application Support/Scribe on macOS, %LOCALAPPDATA%\Scribe on Windows, and $XDG_CONFIG_HOME/scribe or ~/.config/scribe on Linux. Trust and sessions live in trust/ and sessions/ under that root, outside workspaces. Scripts and --json never prompt for trust. The root holds device keys: an override must be a location only you can read. A root Scribe creates is private on every platform (on Windows, a protected access list for your account, SYSTEM and Administrators); one that already exists keeps its permissions, so keep --config-dir or SCRIBE_CONFIG_DIR user-private, as the default %LOCALAPPDATA% is.

Logging defaults to warn, on stderr. SCRIBE_LOG supplies a target filter. --log-filter overrides it; --log-level and --log-filter cannot be combined. -v/--verbose selects debug, repeated twice selects trace; -q/--quiet selects errors only and conflicts with verbose. --timings independently enables phase timings and requires a build with the timings feature (enabled by default). --log-format accepts text or json; it controls diagnostics independently of --json command results.

--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

Start with scribe -h for commands grouped by workflow and common options. scribe --help adds connection, trust, and diagnostic options. At every level, scribe COMMAND --help explains that command's arguments and available actions.

For ordinary work, create a workspace, sync it, open intended files with edit or add, inspect status, and submit -m "Description". Additional commands support specific workflows; they are not prerequisites for submitting a change.

When you need to…Use
Inspect opened work without changing itscribe status
Discover unopened modifications and untracked filesscribe status --scan (or scribe scan)
Check offline intent and acquire required locksscribe reconcile
Also open discovered tracked editsscribe reconcile --scan; use explicit add/delete for new/missing files
Inspect the parent and mounted working copiesscribe project status --scan at the project root
Publish children and then record their pins in the parentscribe project publish -m "Description"

status and submit operate on the current workspace. sync also follows its selected mounts at recorded pins; project sync uses the same workflow at the project root. Project publication is a sequence of accepted submissions: a child can succeed before the parent. --continue resumes the saved publication; --abort resolves transmitted outcomes and preserves already accepted changes.

Recovery follows the pending operation shown by status, and every workflow spells it the same way: --continue resumes and --abort abandons. That is branch --continue for branch creation/rename (no abort: the saved intent may already be accepted), move --continue / --abort, merge --continue / --abort, cherry-pick --continue / --abort, resolve --continue / --abort, workspace view --continue / --abort for a view transition, and project publish --continue / --abort. sync also finishes an interrupted sync or view transition. The earlier subcommand spellings branch continue and workspace view cancel still parse as hidden aliases so existing scripts keep working; new scripts should use the flags.

diagnostics

Show offline client versions, endpoints, configuration sources, and paths.

text
scribe diagnostics [OPTIONS]
sh
scribe diagnostics
scribe diagnostics --json
scribe --server tls://host:7447 diagnostics

Works inside or outside a workspace. Reports the client version, the storage protocol versions it speaks (tcp_protocol, 2, on a plaintext tcp:// connection; tls_protocol, 4, on a mutual-TLS tls:// connection), local workspace schema, OS and architecture, executable and current directory, effective storage endpoint and its source, transfer compression, the parallel transfer-jobs limit, credential selection, and local session status. An invalid SCRIBE_TRANSFER_JOBS value is reported in issues. The saved session's auth endpoint is separate from SCRIBE_AUTH, which configures a future login. Server software versions, connectivity, and server-side session revocation are not checked.

Paths include the configuration root, trust and session directories, selected server's session directory, selected credential/CA files, global ignore file, workspace root, .scribe/_state descriptor/database/lock/cache/temporary/recovery/local-ignore locations, and repository configuration and root ignore files. Paths are absolute locations; reporting one does not imply that it exists. Nested .scribeignore files are not enumerated. An anonymous selection suppresses the credential file.

Inspection does not connect, create configuration or lock files, open the object cache, recover a database, or clear temporaries. Credential and CA file contents are not read; saved session keys and certificates are never included in output. Workspace or session inspection failures appear in issues and cause exit status 1 with ok: false. Other available information remains in the report; an unreadable workspace never silently selects the default server. null means unavailable or not configured. No log file is created: CLI diagnostics normally go to stderr.

login

Log in with a username and password; save a reusable session outside workspaces (with --admin, an administrator credential file)

text
scribe login [OPTIONS] [USERNAME]
Argument or optionMeaning
[USERNAME]Username registered by the auth administrator (or SCRIBE_USERNAME)
--auth <URL>Auth service URL (tls://host:port; or SCRIBE_AUTH)
--password-file <FILE>Read password from this file instead of prompting with hidden input
--auth-ca <FILE>Auth service CA PEM; otherwise approve remembered TLS trust
--discardDrop an unfinished login so another username or auth service can be used (retry first if it may have succeeded); with --admin, the unfinished sign-in for --out
--adminSign in as an auth administrator: write a short-lived administrator credential file (--out) for scribe-auth --admin-credential or the web administration page; no session is saved and no storage server is needed
--out <FILE>With --admin: the new credential file (mode 0600 on Unix), outside any .scribe directory; an existing file is refused

Without --password-file, login requires a terminal and reads hidden input. Login generates a new device key and credential id, saves both with the pending operation before anything is sent, and sends the username, password, and public key to the auth service, which answers with a credential certificate. The private key never leaves the session directory. Sessions are saved for the selected storage endpoint under sessions/ in the per-user configuration root, never in .scribe/. A file given with --auth-ca is copied into the session directory as auth-ca.pem and reused by later renewals and logout. Success prints Logged in as USER; session valid for N days.

Logging in again while a session is active revokes the previous session first. If that revocation fails, the client logs session.revoke_failed and the old session stays valid until it expires. A login whose answer was lost is retried by running the same command again, which resolves the saved operation without creating a second session; --discard takes no other login arguments and forgets only the local intent (see auth).

Later commands present a one-hour access certificate fetched from auth with the session's credential certificate. The client renews it once half its lifetime has elapsed by local elapsed time, so a wrong wall clock does not cause hourly failures; parallel commands wait while one renews.

scribe login --admin --out FILE is administrator sign-in. It takes the same username, password and trust arguments, but saves no session and needs no storage server: auth checks the password as for login and, for an enabled auth administrator, certifies a new device key as an administrator credential that lives for the hours auth is configured with (8 by default; see scribe-auth serve --admin-session-hours). FILE is the same credential file scribe-auth credentials create writes, holding the auth endpoint, the one CA that verified it (so remembered trust with more than one CA needs --auth-ca), the device key and its certificate. It is created with mode 0600, never inside .scribe, and an existing FILE is refused. Use it with scribe-auth --admin-credential FILE or load it on the web administration page. The key and the pending operation are saved under admin-sign-in/ in the per-user configuration root before anything is sent, so rerunning the same command after a lost answer writes the credential auth already issued instead of a second one; --admin --discard --out FILE forgets an unfinished one. Success prints Signed in as USER (auth administrator); administrator credential saved to FILE (valid for N hours, until TIME). Use it with scribe-auth --admin-credential FILE or load it on the web administration page.; with --json, {"username", "credential_file", "credential", "expires_ms"}.

whoami

Show local login status for the selected server (does not verify server-side revocation)

text
scribe whoami [OPTIONS]

Works inside a workspace or with --server tls://HOST:PORT outside one. Reports saved username and expiry, no saved session, expired session, an unfinished login, pending logout, anonymous access, a selected credential file, or plaintext access. Corrupt session state is an error. It does not contact the server: a saved session may have been revoked, and a selected credential file is not read or validated (Credential file selected; its identity is in the file.).

--json returns server, status, username, expires_ms, and verified (always false). Status is one of active, none, expired, login_pending, logout_pending, anonymous, credential_file, or plaintext. Unavailable identity and expiry are null. Successful inspection exits 0 even when not logged in; scripts should inspect status. Credentials are never printed.

logout

Revoke the saved user session and remove it locally; retry after connection failures

text
scribe logout [OPTIONS]
Argument or optionMeaning
--auth-ca <FILE>Auth service CA PEM; otherwise the file given at login, or remembered TLS trust

Revocation must succeed before the local session is removed: the client authenticates to auth with the session's credential certificate and revokes that credential, then deletes the device key and certificates. A failed connection retains the pending logout; repeat the command to finish it. Auth answers success for a credential it already revoked, so a retry always completes. A trust failure before the request retains nothing. A session whose credential has already expired is removed locally without contacting auth. With an unfinished login saved, logout refuses until that login is retried or discarded. Without a saved session the command reports not logged in at SERVER and exits 1. Success prints Logged out; session revoked.

trust

Manage remembered TLS server trust, without sending credentials

text
scribe trust [OPTIONS] <COMMAND>

Subcommands: add, show, forget, replace.

Saved trust holds one or more CAs per server. A CA handover (the server presents its new certificate with a handover certificate signed by the CA you already trust) is followed without a prompt: the new CA is saved beside the old one, and the old one is dropped once the server no longer uses it. Any other change of a server's CA is refused before anything is sent:

text
The CA of tls://scribe.example:7557 changed.
  trusted: BLAKE3:…
  now:     BLAKE3:…
If your administrator confirms this change, run: scribe --server tls://scribe.example:7557 trust replace

trust add

Approve trust for an unknown server; presents no credential

text
scribe trust add [OPTIONS]

No command-specific options; global and parent-group options still apply.

trust show

Show saved trust for the selected server, without connecting

text
scribe trust show [OPTIONS]

No command-specific options; global and parent-group options still apply.

trust forget

Remove saved trust. Requires --trust-fingerprint matching a saved value

text
scribe trust forget [OPTIONS]

No command-specific options; global and parent-group options still apply.

It removes the server's whole saved record, every CA in it; the next connection asks for trust again. A record from an older Scribe version, which cannot be read as trust, is removed without --trust-fingerprint.

trust replace

Replace the saved CA of a server whose CA changed; presents no credential

text
scribe trust replace [OPTIONS]
OptionDescription
--auth-ca <FILE>Replace the sign-in service CA file saved with this server's session (from login --auth-ca) with FILE, instead of the server's own trust

Use only after your administrator confirmed the change. The command connects without credentials; if saved trust still verifies the server (including through a CA handover, which it follows), it prints Nothing was replaced and changes nothing. Otherwise it shows the saved and the new fingerprints and asks you to type replace; with --trust-fingerprint the new fingerprint must match instead, and --json or a non-interactive terminal never prompts. All saved CAs of that server are replaced by the one it presents.

--server names the server whose trust is replaced; for a sign-in service trusted through the shared trust store, that is the sign-in service's own address (the refusal names the exact command). With --auth-ca FILE, the CA file saved at login --auth-ca for the selected server's session is replaced by FILE after FILE verifies the sign-in service; --trust-fingerprint must then match a certificate in FILE.

text
scribe --server tls://scribe.example:7557 trust replace
scribe --server tls://scribe.example:7557 --trust-fingerprint FP trust replace
scribe --server tls://scribe.example:7557 trust replace --auth-ca new-auth-ca.pem

branch

Create, list, and rename branches (stable identities)

text
scribe branch [OPTIONS]
scribe branch <COMMAND>
Argument or optionMeaning
--continueResolve the saved outcome of an interrupted create or rename

Subcommands: list, create, rename. --continue conflicts with a subcommand; with neither, the command explains what it expects and exits 1. See branch --continue.

branch list

List branches with their heads

text
scribe branch list [OPTIONS]

No command-specific options; global and parent-group options still apply.

branch create

Create a branch from a source branch's head or a pinned change

text
scribe branch create [OPTIONS] <NAME>
Argument or optionMeaning
<NAME>New branch name (unique ignoring case and Unicode normalization)
--from <BRANCH>Source branch (default: the workspace branch)
--revision <CHANGE>Start from this change on the source branch instead of its head

branch rename

Rename a branch; its id, history, workspace bindings, and locks are unchanged

text
scribe branch rename [OPTIONS] <OLD> <NEW>
Argument or optionMeaning
<OLD>Current name (main cannot be renamed)
<NEW>New name

branch --continue

Continue an interrupted create or rename by resolving its saved outcome.

text
scribe branch --continue [OPTIONS]

The saved operation id is resolved on the server, never re-sent as new intent. There is no --abort for branch operations: the server may already have accepted the saved intent, and an unknown outcome is only ever resolved by asking. scribe branch continue remains a hidden alias. Without a saved operation the command reports that nothing is pending and exits 1.

switch

Switch the workspace to another branch (requires no opened files, pending submit, or held locks)

text
scribe switch [OPTIONS] <BRANCH>
Argument or optionMeaning
<BRANCH>Branch name

The branch is resolved before anything changes, so an unknown name is refused without touching the workspace. Text output names the destination first (switched to BRANCH (branch ID)) and then prints the ordinary sync summary; --json returns the sync report with branch (id) and branch_name added.

merge

Merge a source branch into the workspace branch; submit after resolving

text
scribe merge [OPTIONS] [SOURCE]
Argument or optionMeaning
[SOURCE]Source branch name (omit with --continue or --abort)
--revision <CHANGE>Merge the source as of this change instead of its head
--base <CHANGE>Merge base to use when more than one best base exists
--continueResume the pending merge without changing its pinned source
--abortAbandon the pending merge; displaced local files are kept in .scribe/_state/recovery

Omit SOURCE with --continue or --abort. --continue conflicts with --abort. Start a merge with no opened files; full and partial workspace views are supported. Like cherry-pick, the command exits 1 while any path remains unresolved and the report ends with the scribe resolve step to take; the report is still printed and no error object is appended. See partial-view integration for excluded conflicts.

Resolve conflicts, then submit; preparation alone does not accept history. Recorded renames are matched before content merging; competing names, rename/delete cases, and occupied destinations are reported as groups. See rename-aware merging.

cherry-pick

Apply one ordinary accepted change from another branch; submit after resolving.

text
scribe cherry-pick [OPTIONS] [CHANGE]
Argument or optionMeaning
[CHANGE]Repository change number to apply
--from <FROM>Source branch name or ID that accepted the selected change
--continueResume the pinned cherry-pick without selecting new intent
--abortAbandon the pending cherry-pick and retain displaced files in recovery

Starting requires both CHANGE and --from; omit both with --continue or --abort. Resume and abort are mutually exclusive. Start with no opened files or unfinished sync. Full and partial workspace views are supported. Resolve any conflicts, review the result, then use ordinary scribe submit to accept it. The command returns a nonzero exit status when paths remain unresolved.

Merge commits and cherry-pick commits cannot be selected as sources. Repeating a source already in the target ancestry or recorded as picked reports it as already applied. The resulting commit records source provenance without adding a merge parent. See cherry-pick for backports, later whole branch merges, web/SDK use, and recovery; see partial-view integration for excluded conflicts.

resolve

Inspect or resolve branch and stale-file conflicts

text
scribe resolve [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Paths to resolve (rename groups are chosen together); with no flags, list unresolved paths
--oursTake the workspace branch's version for the given paths (or --all)
--theirsTake the source branch's (or server's) version for the given paths (or --all)
--workingAccept the file as it is now in the working copy after manual editing
--updateRefresh stale opened files against the server head before resubmitting
--abortAbandon the pending resolution (same as merge --abort)
--continueResume the pending resolution workflow (same as merge --continue)
--allApply the chosen side to every path in the plan instead of the listed paths
--export <EXPORT>Export base/ours/theirs into an empty directory for external tools

Choose one of --ours, --theirs, --working, --update, --abort, --continue, or --export. --all applies a side selection to the entire plan. With no action, list unresolved paths. --abort and --continue are equivalent to merge --abort and merge --continue (--continue is refused when no resolution is pending); --export requires an empty destination.

Selecting a member of a rename group selects the entire group. With an agreed destination, --ours/--theirs choose contents there; with conflicting names they choose a layout. For --working, write the resolved content at the agreed destination, or arrange the displayed group paths when names conflict. Grouped merges and partial-view integrations must be aborted and restarted if their target advances; --update does not replan them. Choices that include excluded paths are refused until those paths are in the view. This also applies to --all, which selects the entire plan; name only included paths when resolving their conflicts separately. During a merge or cherry-pick, workspace view add includes missing paths without discarding completed resolutions. Expansion retains the pinned revisions; resume an interrupted view transition with sync.

repo

Repository administration

text
scribe repo [OPTIONS] <COMMAND>

Subcommands: create, list, info.

repo create

Create an empty repository with a main branch

text
scribe repo create [OPTIONS] <NAME>
Argument or optionMeaning
<NAME>Letters, digits, '-', '_', '.'; not starting with '.'; at most 128 bytes
--storage-compression <none|lz4>Permanent repository storage policy; cannot be changed after creation [default: none]

Storage compression accepts none (default) or lz4 and cannot be changed after creation. Authenticated repository creation requires namespace administration.

repo list

List repositories you can access

text
scribe repo list [OPTIONS]

No command-specific options; global and parent-group options still apply.

repo info

Show a repository's id, main branch, head, and incarnation

text
scribe repo info [OPTIONS] <REPO>
Argument or optionMeaning
<REPO>Repository name or id

workspace

Manage one repository working copy, its view, and shared view presets

text
scribe workspace [OPTIONS] <COMMAND>

Subcommands: list, remove, create, config, register, info, profiles, view, mounts, trust-history.

workspace list

List your active server registrations; without auth, list every registration

text
scribe workspace list [OPTIONS]
Argument or optionMeaning
--repo <REPO>Repository name or id; mutually exclusive with --all-repos
--all-reposList across every accessible repository, including through a gateway
--everyoneInclude other owners; requires Maintainer in each selected repository with auth
--tag <NAME[=VALUE]>Only registrations carrying this tag; NAME matches any value, NAME=VALUE exactly (repeatable, all must match)

Columns are WORKSPACE, REPOSITORY, OWNER, LABEL, TAGS, CREATED, and LOCKS, sized to their contents so header and rows line up. The label is the one recorded at registration: AUTHOR@HOST for a workspace the CLI created. TAGS lists the registration's tags comma-separated, - for none; --tag runner keeps the workspaces runners made, --tag runner-id=<id> one runner's. Filtering happens in the CLI after the pages are fetched. Without a repository selection, use the current workspace repository if present, otherwise all accessible repositories. Authenticated listing defaults to the current principal's registrations. Anonymous public access cannot list them; without auth, all registrations in the selected repositories are visible. An authorization failure in any selected repository fails the command rather than producing a partial admin inventory.

Use global --server URL to select a storage endpoint or gateway and --json for structured inventory. No local checkout is required. See workspace administration.

workspace remove

Permanently retire a server registration; preserve local files and accepted history

text
scribe workspace remove [OPTIONS] <WORKSPACE>
Argument or optionMeaning
<WORKSPACE>Full workspace id from workspace list; held locks must be released first
--repo <REPO>Repository name or id; required outside a workspace

With auth, an owner needs repository read access to remove their registration; removing another owner's registration requires Maintainer. Without auth, any connected client may remove a registration. The same rules apply through a gateway.

Removal affects only the selected registration, frees its active-workspace quota slot, and has no undo. Retired identities cannot register again, acquire locks, or publish new work. Other registrations, project mount pins, local files, and accepted history remain intact. Held locks must be explicitly released first; removal does not force-unlock them.

Repeat the command with the same per-user configuration directory after a connection failure to resolve its saved outcome safely. See workspace administration for lock release and recovery from an old computer.

workspace create

Create a workspace for a repository in a directory

text
scribe workspace create [OPTIONS] <REPO> <DIRECTORY>
Argument or optionMeaning
<REPO>Repository name or id
<DIRECTORY>Directory to hold the working copy (must not already contain a workspace)
--view <PREFIX>Inclusion prefixes (repeatable); with --profile, add local inclusions to that profile
--profile <NAME>Named profile from the repository's accepted .scribe/config.toml file
--author <AUTHOR>Author label for submits; --author overrides the default (the logged-in user, then $SCRIBE_AUTHOR, then the OS user name)
--readonlyMark unopened tracked files read-only (Perforce convention)
--tag <NAME[=VALUE]>Tag the registration (repeatable, at most 16); a tag is NAME or NAME=VALUE and never changes afterwards
--preset <art>Start the repository configuration from a preset: writes .scribe/config.toml and opens it for add; submit to apply

--view is repeatable. Change an existing selection with workspace view. --profile reads the accepted definition at the main branch head; --view adds local inclusions when used with a profile. --author overrides the default label, which is the logged-in username when a session is saved for the server, then SCRIBE_AUTHOR, then the OS username; authenticated attribution on the server comes from the credential regardless. The registration label is AUTHOR@HOST. --tag adds name or name=value markers to the registration beside the label — what made the workspace and why, for workspace list --tag and the web inventory to filter on. A name is 1–63 lowercase ASCII letters, digits, -, _ or . starting with a letter or digit, a value printable ASCII without spaces, the whole tag at most 64 bytes, names unique, at most 16 per workspace. Tags are fixed by the first registration: there is no command to change them, and the server refuses a re-registration that names different ones. (A runner tags its workspaces runner and runner-id=<id>.) The selected transfer compression is saved for future connections. The report names the branch (main for a new workspace) and --json includes branch_name and tags.

--preset art writes a starting .scribe/config.toml (kind = "art" plus lock rules for binary art formats) into the new working copy and opens it for add. Nothing is submitted: review the file, then run scribe submit. The command is refused before anything is created when main already has an accepted .scribe/config.toml, or when the --view prefixes (without --profile) exclude it. See repository configuration.

workspace config

Set the workspace preference for compression on subsequent connections

text
scribe workspace config [OPTIONS] --compression <none|lz4>
Argument or optionMeaning
--compression <none|lz4>Compression for uploads and downloads; independent of repository storage

Run inside the workspace. --compression is required and accepts none or lz4. This updates the saved transfer preference; it does not change repository storage compression.

workspace register

Register an anonymous working copy under the logged-in writer, preserving local edits.

text
scribe workspace register [OPTIONS]
OptionMeaning
--tag <NAME[=VALUE]>Tag the registration (repeatable, at most 16); a tag is NAME or NAME=VALUE and never changes afterwards

Run in the anonymous working copy after login. --tag sets the tags the registration is made with, as workspace create --tag does; an anonymous copy has none until then. Requires repository write permission. Persists a fresh identity before transmission; interrupted registration can be retried. Files and opened edits remain in place. See public repositories.

workspace info

Show the current workspace

text
scribe workspace info [OPTIONS]

No command-specific options; global and parent-group options still apply. Works offline. The branch line shows the name the working copy last learned from the server with the id in parentheses; workspace create, switch, and status --remote record it, and branch list always shows the server's current names.

workspace profiles

List accepted workspace profiles at the current branch head.

text
scribe workspace profiles [OPTIONS]

Works even if .scribe/config.toml is outside the current view. Definitions come from accepted history; local unsubmitted edits are not read.

workspace view

Inspect or safely change which repository paths are materialized.

text
scribe workspace view [OPTIONS]
scribe workspace view <COMMAND>
scribe workspace view show [OPTIONS]
scribe workspace view add [OPTIONS] <PREFIXES>...
scribe workspace view remove [OPTIONS] <PREFIXES>...
Subcommand or optionBehavior
showShow the active selection and any pending transition; no network required
setReplace the selection; active integrations allow expansion at their pinned target
add <PREFIXES>...Add local inclusion prefixes and sync missing content
remove <PREFIXES>...Remove selected prefixes and selected descendants
--continueResume an interrupted view change (same as scribe sync); refused when none is pending
--abortSafely reconcile back to the active selection after an interrupted change

--continue and --abort conflict with each other and with a subcommand. scribe workspace view cancel remains a hidden alias of --abort.

The set usage from --help is:

text
scribe workspace view set [OPTIONS] <--view <PREFIX>|--profile <NAME>|--all>
OptionMeaning
--view <PREFIX>Inclusion prefix; repeat to select multiple paths, or extend a profile
--profile <NAME>Apply a named profile from the accepted .scribe/config.toml file
--allSelect the entire repository; conflicts with --view and --profile

At least one selection option is required. --profile and --view can be combined. remove cannot carve an exception from a broader inclusion or remove the last prefix. The active selection and watermark advance only after the transition completes. Resume an interrupted transition with scribe sync or workspace view --continue; opened exclusions must be reverted or the transition abandoned with workspace view --abort. Displaced files are retained in recovery, including clean files, and each is announced on stderr as preserved PATH at RECOVERY. See views and profiles.

workspace mounts

List versioned repository mounts at the current branch head without probing targets

text
scribe workspace mounts [OPTIONS]

No command-specific options; global and parent-group options still apply.

Lists versioned mount declarations at the current branch head without contacting target repositories. Selection follows the saved workspace view. Use scribe sync to materialize selected mounts and check target access. See repository mounts.

workspace trust-history

Establish a new history anchor after inspecting a restored or replaced repository

text
scribe workspace trust-history [OPTIONS] --accept-current
Argument or optionMeaning
--accept-currentExplicitly trust the currently connected repository head; local files are preserved

Explicitly trust the connected repository's current history for this workspace branch after inspecting a restore or replacement authority. This persists a new commit/incarnation anchor and invalidates the old verified baseline. It changes no working files or sync watermark. Subsequent sync proves the replacement state and preserves local work through normal recovery rules.

Ordinary workspace creation establishes first-contact trust. Sync and workspace head checks refuse rollback, incarnation changes and parent chains that do not reach the saved anchor. A check processes at most 4,096 envelopes, saves progress, and asks you to retry if more remain. Backward sync changes materialized state without moving the trusted head backward. Proof pages shrink automatically to fit bounds; an unprovable single-entry page fails explicitly before applying files.

project

Coordinate a parent workspace and its selected repository mounts

text
scribe project [OPTIONS] <COMMAND>
scribe project status [OPTIONS]
scribe project sync [OPTIONS]
scribe project update [OPTIONS] <NAME>
scribe project publish [OPTIONS]
Command and optionBehavior
statusOffline component status from working-copy mount declarations
status --scanInclude tracked and untracked discovery in each local component
status --verifyHash bytes; implies --scan
status --remoteCheck selected repositories independently; report heads and locks
sync --revision <REVISION>Optional exact parent revision; otherwise use ordinary sync's saved target/head rules
update <NAME> --revision <REVISION>Stage this mount's pin; default is its local sync/submission revision, never remote head
publish -m, --message <MESSAGE>Prepare opened work, submit selected children, then submit the parent with confirmed pins
publish --continueRecover the saved publication using its original operation IDs
publish --abortResolve transmitted outcomes and release unsent work; preserve accepted history and local edits

Publication requires exactly one of --message, --continue, or --abort. Pin update edits the parent's tracked .scribe/config.toml under ordinary lock rules; it does not submit. Pending publication blocks ordinary participant mutations until root recovery finishes. Unselected children need no remote access. See project workflows for precise preparation, selection, rejection, restore, and unknown-outcome behavior.

edit

Open tracked files for edit; acquire required locks unless --offline

text
scribe edit [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Files inside the workspace
--offlineOpen locally without a server connection; reconcile locks and revisions later

See offline work and reconciliation. Refused while a merge or other conflict resolution is active; see opening files.

An online edit also looks at the current lock holders once the files are opened: a path another workspace holds, whether or not the policy requires a lock there, is reported on stderr as warning: PATH is locked by AUTHOR (workspace ID); submit will be refused until it is released. The file stays opened; the warning exists so the refusal does not first appear at submit. --offline makes no such check.

reconcile

Check opened files against server revisions and acquire required locks

text
scribe reconcile [OPTIONS]
Argument or optionMeaning
--scanVerify tracked contents and open discovered edits; report missing and untracked paths

File contents and baselines are preserved. Exit 0 means all opened paths passed at the checked revisions; exit 1 returns a per-path report of blockers. The server rechecks on submit. See the workflow guide.

move

Move a tracked file or folder to an exact new path, preserving history

text
scribe move [OPTIONS] [SOURCE] [DESTINATION]
Argument or optionMeaning
[SOURCE]Existing file or folder, including destinations of earlier pending moves
[DESTINATION]Exact destination path (must not already exist)
--id <ID>Select a pending move from status (otherwise interrupted, then latest)
--continueResume an interrupted move
--abortUndo an unsubmitted move, preserving current file contents
--afterRecord a rename already done outside Scribe: SOURCE is gone and DESTINATION holds the file, edited or not
--detectPair missing tracked files with untracked files holding exactly their recorded bytes, and record each pair as a move
--dry-runWith --detect, report the pairs without recording them

Provide both SOURCE and DESTINATION for a new move. Omit them with --continue, --abort, or --detect; those actions are mutually exclusive. --id requires --continue or --abort. Destination must be an exact, absent path. Moves remain pending until submit.

With --after, SOURCE must be a tracked file that is already gone and DESTINATION an untracked regular file that is present; its bytes may differ from SOURCE's. It prints Recorded move A -> B (1 tracked files, move ID).

--detect prints would move A -> B (dry run) or moved A -> B (move ID) per pair and unpaired PATH: reason for every missing tracked file it could not pair uniquely, then suggests move --after for those; --json returns dry_run, moves (source, destination, size, id once recorded), unpaired (path, reason) and hashed. See moving files.

add

Open new files for add (directories recurse, honoring ignore rules)

text
scribe add [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Files or directories inside the workspace
--forceAdd even if ignored (does not override containment or the reserved .scribe/_state)
--offlineRecord the add locally without contacting the server or acquiring locks

Refused while a merge or other conflict resolution is active; see opening files.

The add is recorded locally first. The paths just opened are then checked as reconcile would check them, for those paths only: a lock the policy requires is acquired, as edit acquires it, and a file already at that path on the server is reported. Findings are printed as warnings and leave the exit status alone; submit enforces them either way. A server that cannot be reached, a missing session, or a pending submit skips the check with its reason, and the add stands as pending reconciliation. --offline records the add without trying the server, so it never waits on one that is down or behind a lost VPN.

A file named on the command line that is skipped (ignored, already tracked, already opened, outside the view, a link) is reported as skipped PATH: reason and the command exits 1 after printing the report. Files skipped while recursing into a named directory are the documented ignore behavior and leave the exit status 0.

delete

Open tracked files for delete and remove them locally

text
scribe delete [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Tracked files inside the workspace
--forceDelete even if locally modified (a copy is kept under .scribe/_state/recovery)
--offlineRecord the deletion locally without contacting the server or acquiring locks

Refused while a merge or other conflict resolution is active; see opening files. The deletion is recorded locally first, then checked as for add: a lock the policy requires is acquired, as edit acquires it, and a newer revision of the file on the server is reported. --offline records the deletion without trying the server.

The opened deletion is recorded before the local file is removed (to .scribe/_state/recovery, including files that equal the recorded base), so an interrupted delete can be completed by repeating it or undone with revert. A locally modified file is refused without --force and reported under skipped while the other paths are still opened. A copy kept in recovery is announced on stderr as preserved PATH at RECOVERY, the same notice revert and sync print (summarized to a count above ten files); stdout carries only the command's report. scribe recovery list maps entries back to their paths.

revert

Restore opened files to their workspace base

text
scribe revert [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Opened files; their local contents are kept under .scribe/_state/recovery first

The local file being replaced is kept in recovery whether or not it was modified. A preserved copy is announced on stderr as preserved PATH at RECOVERY.

diff

Show unified diffs of opened text files against their baseline or a revision

text
scribe diff [OPTIONS] [PATHS]...
Argument or optionMeaning
[PATHS]...Files inside the workspace (default: every opened file)
--revision <CHANGE>Compare against this accepted change on the workspace branch instead of the file's baseline

Read-only: nothing is opened, locked, or written, and the working copy's baseline, opened intent, and sync watermark are untouched. Without paths every opened file is compared; a named path must be opened or tracked unless --revision selects accepted history for it. The baseline bytes come from the server (through the local object cache), so the command needs a connection. Files opened for add compare against /dev/null, deletions against the baseline. A pending move compares the destination with its origin's baseline.

Output is the usual unified format, three lines of context, one --- a/PATH / +++ b/PATH header per changed file; unchanged files print nothing. A file on either side above the review bound (2 MiB) prints PATH: too large to diff; a file with a NUL byte in its first 8 KiB prints Binary files a/PATH and b/PATH differ. The exit status is 0 whether or not differences exist; a path that is neither opened nor tracked is a usage error. --json lists every compared file with status, added, removed, and the hunks in diff; see JSON output.

sh
scribe diff
scribe diff Source/Player.cpp
scribe diff --revision 41 Source/Player.cpp

status

Inspect changes and unfinished work in the current workspace

text
scribe status [OPTIONS]
Argument or optionMeaning
--remoteAlso query branch head, active main-branch lock rules, and current holders
--scanAlso report tracked-but-unopened modifications, deletions, and untracked files
--verifyHash contents instead of trusting fingerprints (implies --scan)

Default status is local and limits file inspection to opened/workflow paths. --scan widens discovery. Rows combine local state, moves, reconciliation, resolution groups, deferred updates, and optional locks. --remote failure retains the local report, marks remote state unavailable, and exits 1. Local inspection or ignore-rule problems also exit 1; changes/conflicts alone do not. See unified status.

The header names the workspace, repository, and branch, the sync watermark, and what was scanned (scanned: opened paths only ... without --scan). The branch is shown by name with --remote, which asks the server; the local report shows the id, since a workspace stores only that. After the rows, a Summary: line counts paths by intent (3 opened for add, 1 opened for edit, ...) and Next: lines suggest the following step: scribe submit when files are opened and no workflow is pending, scribe reconcile only when an edit was opened offline, otherwise the pending workflow's --continue / --abort command.

scan

Discover changes across the workspace (same as status --scan)

text
scribe scan [OPTIONS]
Argument or optionMeaning
--verifyHash contents instead of trusting fingerprints

submit

Submit opened file changes together as one changeset (default: all opened files)

text
scribe submit [OPTIONS] --message <MESSAGE> [PATHS]...
Argument or optionMeaning
-m, --message <MESSAGE>Change description
--keep-locksRetain locks on submitted files after a successful submit
[PATHS]...Exact opened files to submit; omit to submit all. Moves include their complete group

--message / -m is required. If the outcome is unknown, keep the pending state and rerun submit to resolve it; do not invent a replacement operation.

sh
scribe submit -m "Fix movement" -- Source/Player.cpp Source/Movement.cpp

Paths are relative to the current directory (absolute paths inside the workspace also work). Each must name an exact opened file, including a deleted file's former path. Directories and unopened paths are refused before publishing anything; duplicates are collapsed. Unselected files retain their contents, opened state, baselines, locks, and pending moves. Paths cannot cross into a mounted workspace.

Selecting either endpoint of a move includes its entire move group, including folder moves and dependent rename chains. A merge, cherry-pick, or active conflict resolution must be submitted in full: omit paths. After an unknown outcome, any new message or path selection is ignored while the original saved candidate is resolved; that invocation does not start another submission.

A submit above the server's per-submit change-set cap is refused with limit_exceeded, naming the entry count, the cap, and the configuration key. For a first population of a repository, use import; the cap is not raised for ordinary work, because a single acceptance holds the repository publication gate for its whole duration.

A successful submit releases your locks on submitted paths by default. Rejected submits and locks on other paths are unchanged. Recovery uses the saved choice.

import

Populate a repository from an existing tree as a sequence of changes, each within the server's per-submit cap

text
scribe import [OPTIONS] --message <MESSAGE>
Argument or optionMeaning
-m, --message <MESSAGE>Description recorded on every change this import creates
--batch-size <N>Entries per change (default: the cap the server advertises)
--dry-runReport how many changes the import would create, without submitting

Open the tree first with scribe add, then run import. It submits the opened adds in path order as a sequence of changes, each no larger than the server's max_submit_entries, which it reads from the server handshake rather than assuming. A batch the server still refuses as oversize is halved and re-sent under a fresh operation id, so a lower cap or a gateway default cannot strand the import. Every change carries the message verbatim.

import accepts only adds. An opened edit, delete, keep, or move destination is refused, naming the path: splitting a change set that contains a rename could publish an intermediate change in which the moved file exists nowhere, and rename pairs can be arbitrarily large, so no batch size makes that safe. Submit such work with submit, which stays atomic. This is also why there is no submit --split.

Each batch is an ordinary submit, so its operation id is persisted before transmission and an unknown outcome is resolved by asking the server, never guessed. Re-run import after any interruption: it resolves the batch that was in flight, then continues with the paths the server has not accepted. A run with nothing left to import succeeds and reports that it is already complete, so the command is safe to repeat until it does.

The plan — file count, change count and batch size — is written to stderr before the first change is sent, and each accepted change as it lands. --dry-run reports the same plan and sends nothing.

sync

Sync the workspace and selected mounts (default: head, mounts at recorded pins)

text
scribe sync [OPTIONS]
Argument or optionMeaning
--revision <CHANGE>Pinned change number, including an older revision

Defaults to the verified branch head. Older revisions use verified backward changes when a verified baseline is available; otherwise sync proves a full snapshot. Opened paths are deferred; displaced files go to .scribe/_state/recovery. The sync watermark and applied proof binding advance together only when the journal is fully applied. The trusted history pin remains at the newest verified head. Restored incarnations require explicit acceptance.

get

Download one file at a pinned revision without changing workspace state

text
scribe get [OPTIONS] --revision <CHANGE> --to <FILE> <PATH>
Argument or optionMeaning
<PATH>Exact repository-relative path at the requested revision (independent of current directory)
--revision <CHANGE>Pinned changeset number on the selected branch
--to <FILE>New destination file; parent directory must exist; existing entries are never replaced
--repo <REPO>Repository name or id (required outside a workspace; defaults to the workspace repository)
--branch <BRANCH>Branch name or id (defaults to workspace branch, or main with --repo)

See downloading one historical file for revision selection, verification, and interruption behavior.

export

Export a pinned change into an empty directory (no workspace state)

text
scribe export [OPTIONS] --revision <CHANGE> --to <DIR>
Argument or optionMeaning
--revision <CHANGE>Change number to export
--to <DIR>Empty destination directory
--repo <REPO>Repository name or id (default: the current workspace's)
--view <PREFIX>Restrict to these directory prefixes

--revision and --to are required. Outside a workspace, also select --repo. Repeat --view for multiple prefixes. The destination must be empty; export creates no workspace state.

log

Show history (of a path when given)

text
scribe log [OPTIONS] [PATH]
Argument or optionMeaning
[PATH]Restrict history to this path
--first-parentExclude merge-source history for this path (branch origins are retained)
--all-branchesDiscover related revisions on every branch, including unmerged work
--at <CHANGE>Pin all-branch history to this repository change (reuse history_snapshot when paging)
--limit <LIMIT>Maximum entries, newest first [default: 20]
--before <CHANGE>Only changes strictly before this change number
--after-path <AFTER_PATH>Continue after this historical path within --before (use the last log row)

--first-parent and --all-branches require PATH and conflict with each other. --at requires --all-branches. The all-branch view selects the file incarnation at that snapshot and labels each row by commit ancestry. Reuse its reported history_snapshot with --at for stable continuation. See cross-branch history. --after-path requires both PATH and --before; pass the last row’s change and historical path together to retain tied history entries. --limit defaults to 20.

Each row shows the change's current description: the message it was submitted with, or the latest correction recorded with describe, marked with who revised it and when. --json carries both as message and note (null when never corrected) and reports notes_available, which is false against a server that predates descriptions.

describe

Correct the description of an accepted change, or show its revisions

text
scribe describe [OPTIONS] <CHANGE>
Argument or optionMeaning
<CHANGE>Change number
-m, --message <TEXT>New description; the change keeps its submitted message
--expect <REVISION>Only apply when the description is still at this revision (default: the current one, read first)
--historyList every recorded description of the change instead

The commit and its message are never rewritten: a description is appended to the change's journal on the server, log shows the latest one in place of the message, and --history lists every revision with its author and time. The server attributes each revision to the signed-in principal. A writer may describe their own changes; anyone else's need a maintainer. --expect refuses with note_revision_stale when someone described the change in the meantime, so a retry after a lost reply never records a duplicate. Servers older than the description journal refuse the command as unsupported_version.

info

Show local and server state of a path

text
scribe info [OPTIONS] <PATH>
Argument or optionMeaning
<PATH>File inside the workspace

lock

Acquire, release, and inspect repository-wide file locks and rules

text
scribe lock [OPTIONS] <COMMAND>

Subcommands: acquire, release, list, rules. Ordinary edit already acquires required locks; use lock acquire when reserving a path explicitly.

lock acquire

Acquire exclusive locks across all branches, held until explicitly released

text
scribe lock acquire [OPTIONS] <PATHS>...
Argument or optionMeaning
<PATHS>...Files to lock, including new paths that will be added

lock release

Release locks held by this workspace, or force release with permission

text
scribe lock release [OPTIONS] <PATHS>...
Argument or optionMeaning
<PATHS>...Locked files; with --repo, exact repository-relative paths
--repo <REPO>Repository name or id for remote administration; requires --force
--forceRelease a lock held by another workspace

--repo <REPO> permits forced unlock without a local workspace and requires --force. Paths are then exact repository-relative paths. Maintainer permission is required on authenticated servers, even for the caller's own lost workspace; without auth, any connected client may force-unlock. Generation checks still apply. See workspace administration.

lock rules

Show active main-branch lock rules, or explain one path

text
scribe lock rules [OPTIONS] [PATH]
Argument or optionMeaning
[PATH]Optional file path to explain under the server's active policy

lock list

List current lock holders

text
scribe lock list [OPTIONS]
Argument or optionMeaning
--repo <REPO>Repository name or id; permits listing without a local workspace
--prefix <DIR>Only locks below this directory prefix [default: ""]

--repo <REPO> lists locks without a local workspace. Otherwise the current workspace selects the repository. Listing requires repository read access with auth. Remote administration works directly or through a gateway.

ignore

Ignore-rule tools

text
scribe ignore [OPTIONS] <COMMAND>

Subcommands: explain.

ignore explain

Explain why a path is or is not ignored

text
scribe ignore explain [OPTIONS] <PATH>
Argument or optionMeaning
<PATH>Path inside the workspace

recovery

List and prune files retained under .scribe/_state/recovery

text
scribe recovery [OPTIONS] <COMMAND>

Subcommands: list, prune.

Sync, revert, delete and resolution move every local file they replace or remove into .scribe/_state/recovery, even when its bytes equal the recorded base. Nothing is pruned automatically.

recovery list

List retained entries with their original path, reason, and time

text
scribe recovery list [OPTIONS]

recovery prune

Remove retained entries; intent archives and unreadable entries are kept

text
scribe recovery prune [OPTIONS]
Argument or optionMeaning
--older-than <DURATION>Only entries retained longer ago than this (for example 30m, 12h, 7d, 2w)
--allEvery retained entry regardless of age

One of --older-than or --all is required. Entries kept are named with the reason: an intent archive, an unreadable index, or an entry newer than the cut-off.

Use cases

Change the transfer preference

Inside an existing workspace:

sh
scribe workspace config --compression lz4
scribe --transfer-compression none sync
scribe workspace info

The override affects only this sync; the saved preference stays LZ4.

Inspect history

sh
scribe log Assets/Hero.uasset --limit 10
scribe log Assets/Hero.uasset --all-branches --limit 10
scribe get Assets/Hero.uasset --revision 42 --to ./Hero-at-42.uasset

Use a revision and historical path from your repository. To continue a cross-branch history page, retain its snapshot and cursor; see file history.

For a complete creation/submit/sync exercise, follow the minimal-server tutorial. The auth tutorial adds login and grants.

Output and exit codes

ExitMeaning
0Success
1User or semantic error
2Invalid CLI arguments or refusal to destroy local data
3Submit outcome unknown; preserve pending state and retry submit
4Integrity failure
5Transport or storage failure

Status/scan return 1 with their available report when local inspection or discovery is incomplete. status --remote also returns 1 with the local report and remote state unavailable when enrichment fails, including transport failures. Changes or conflicts alone do not cause a nonzero status exit. Reconciliation returns 1 when its report contains blockers. merge and cherry-pick return 1 with their report while paths remain unresolved. add returns 1 after its report when a file named on the command line was skipped. In each of these cases the report is the only stdout document; no error object follows it. See the status workflow.

Notices about preserved local contents (preserved PATH at RECOVERY) and warnings such as a foreign lock observed by edit go to stderr without the scribe: error prefix; stdout is reserved for the command's result.

A failure prints one scribe: MESSAGE line on stderr. A server-side refusal shows its detail followed by the stable code name in parentheses, for example scribe: permission denied (forbidden); the numeric code appears only in the --json error object ("error": "forbidden (9): permission denied", "code": "forbidden"). See JSON output.

--json selects machine-readable stdout results; diagnostics stay separate. See JSON output for schemas, help, and error behavior, and logging for filters, sinks, timing events, and build features.

Source docs/reference/cli/scribe.mdSnapshot 2b8dcccb