CLI reference
skrzynka is a noninteractive JSON CLI. Successful commands print one pretty-printed JSON value to stdout and exit 0. Application failures print one compact envelope to stderr and exit 1:
Overview#
skrzynka is a noninteractive JSON CLI. Successful commands print one pretty-printed JSON value to stdout and exit 0. Application failures print one compact envelope to stderr and exit 1:
{"error":{"code":"MAILBOX_PROFILE_INVALID","message":"imap_host is required","retryable":false}}Argument parsing failures are Clap text and exit 2. Logs go to stderr. Every command except serve, version and onboarding acts for the organization named by --organization <ID>; a command without it is refused with ORGANIZATION_REQUIRED, and no organization is assumed. Rows written before organizations existed carry the stored namespace legacy-local; name it to read them.
Global options#
| Option | Default | Meaning |
|---|---|---|
--organization <ID> | none | Required organization scope for data commands; serve, version and onboarding do not require it |
--skarbiec-bin <PATH> | skarbiec | executable invoked for credential operations |
-h, --help | — | help; no state or network access |
-V, --version | — | package version text from Clap |
Global options may appear with subcommands. skrzynka version instead emits the machine JSON object {product, version, source} and opens no database.
Service and inspection#
skrzynka serve
skrzynka serve --bind <SOCKET>| Option | Default | Rule |
|---|---|---|
--bind | 127.0.0.1:8788 | address IP must be loopback |
Opens the database, reads each enabled mailbox as its provider announces new mail (IMAP IDLE; no polling interval), and serves the HTTP API. It remains in the foreground. Startup readiness is the stderr log Skrzynka API ready address=....
skrzynka status
Returns {product, version, database, schema_version, mailbox_count, enabled_mailbox_count, message_count, skarbiec_available}. The Skarbiec probe runs skarbiec version but resolves no item.
skrzynka version
Returns {product:"skrzynka", version, source}. Source builds report source-build unless the compile-time SKRZYNKA_SOURCE_REVISION was set.
Mailboxes#
mailbox declare
skrzynka mailbox declare --skarbiec-item <ID>Skarbiec owns the mailbox list: an item tagged skrzynka:mailbox is a mailbox. declare validates the item's profile, adds the tag, and imports every INBOX message, one commit each. Only the item reference is an input; profile flags are refused. The canonical mailbox declare reference owns the complete behavior.
Inventory and state
| Command | Output / effect |
|---|---|
mailbox list | reconcile with Skarbiec, then a JSON array sorted case-insensitively by display name, then email |
mailbox show <UUID> | one mailbox object |
mailbox undeclare <UUID> | remove the skrzynka:mailbox tag; the mailbox keeps its mail with enabled:false; return object |
mailbox remove <UUID> --confirm | cascade-delete the local state of an undeclared mailbox; return {"removed":"<UUID>"} |
Removal without --confirm is CONFIRMATION_REQUIRED; removal of a declared mailbox is MAILBOX_STILL_DECLARED. It never deletes provider or Skarbiec state.
Synchronization#
skrzynka --organization <ID> sync [--mailbox <UUID>]With --mailbox, runs one pass that imports everything past the cursor and returns {mailbox_id, received, skipped, last_uid, completed_at}; a dependency failure exits 1, keeping every message committed before it. Without it, processes every enabled mailbox and returns {completed_at, reconciliation, mailboxes:[...]}. Individual failures are embedded as {mailbox_id, ok:false, summary:null, error_code, error_message} and the command still exits 0.
Messages, replies, and outbound mail#
message list
skrzynka message list [--mailbox <UUID>] [--limit <N>] [--offset <N>]Without --limit every message from --offset (default 0) on is listed; with it, a page of that many. Returns newest imported messages first, optionally for one mailbox.
message show
Returns one message object. Invalid UUID syntax is rejected by Clap before the application; an absent UUID returns NOT_FOUND.
message reply
skrzynka message reply <MESSAGE-UUID> --body-file <PATH>
[--idempotency-key <KEY>]The file must be regular and UTF-8; its size is the SMTP server's to accept or refuse. Omitting the key generates a new UUID. Returns the reply attempt on SMTP acceptance or when an identical key already exists. Provider and validation failures use the standard error envelope; persisted attempt state remains available through the HTTP reply list.
message send
skrzynka message send --mailbox <UUID-OR-ADDRESS> --to <ADDRESS> [--to <ADDRESS>]
[--cc <ADDRESS>] --subject <TEXT> --body-file <PATH>
[--idempotency-key <KEY>]Originates mail the mailbox did not receive. --mailbox accepts the mailbox UUID or the mailbox's own address, and an address naming more than one mailbox is refused with MAILBOX_SELECTOR_AMBIGUOUS rather than silently picked. --to and --cc are repeatable bare addresses, comma-splittable, deduplicated in order; a display name is refused. The subject must not be empty and the body file is regular UTF-8; the SMTP server accepts or refuses its size. Returns the stored outbound message; the idempotency key claims the row before anything reaches the provider.
message outbound
skrzynka message outbound [--mailbox <UUID-OR-ADDRESS>] [--limit <N>] [--offset <N>]Without --limit every outbound message from --offset (default 0) on is listed; with it, a page of that many. Returns originated mail newest first, optionally for one mailbox, and resolves no credential.
Gmail connection#
| Command | Output / effect |
|---|---|
account connection --provider gmail --bind <SOCKET> [--email <ADDRESS>] | {account, mailbox_id, receiving_skarbiec_item_id, usable_paths, paths}; each of app_password, oauth and delegation is measured against Google and reported usable, refused or unproven with its code, the provider's own words, the non-secret facts observed and the exact next step |
account authorize --provider gmail --bind <SOCKET> --skarbiec-item <ID> | Start the PKCE flow and serve the loopback callback on the required --bind address, which the configured OAuth client must accept. After authorization completes, exit when its mailbox exists. See Gmail connection for prerequisites and measured refusals. |
account delegate --provider gmail --email <ADDRESS> [--display-name <TEXT>] | prove delegated access, persist the mailbox bundle in Skarbiec, and return a new or existing mailbox |
account app-password --provider gmail --email <ADDRESS> [--display-name <TEXT>] [--mailbox <ID-OR-ADDRESS>] | read the app-specific password from stdin, prove it against Gmail IMAP, persist its deterministic bundle in Skarbiec, and create or reconnect the Gmail mailbox; with --mailbox, attach it as the selected existing row's receiving credential without changing that row's outgoing identity or SMTP setup |
Skrzynka never performs the domain-wide delegation grant. It exists only in the Workspace admin console, so a missing grant is reported as GOOGLE_DELEGATION_NOT_GRANTED with the client ID, the scope and the console URL. See Gmail connection for the OAuth client's measured state.
Command pages#
Every public top-level command and every public leaf subcommand has its own canonical reference page:
- help
- serve
- status
- version
- onboarding
- mailbox: mailbox overview, mailbox declare, mailbox undeclare, mailbox list, mailbox show, mailbox remove.
- account: account overview, account connection, account authorize, account delegate, account app-password, account disconnect.
- message: message overview, message list, message show, message reply, message send, message outbound.
- sync
Exit and retry contract#
- 0: command's local contract completed. For all-mailbox sync, inspect each
ok. - 1: normalized application error. Retry only when
retryable:true, and never automatically resend an ambiguous reply. - 2: command line could not be parsed.
See runbook for every stable error family.