Quick start
From a clone to a synchronized local inbox. Every command and output below was executed against version 0.2.0 in an isolated state directory, with --skarbiec-bin pointed at a stand-in Skarbiec CLI that serves one documented bundle item (tea
Overview#
From a clone to a synchronized local inbox. Every command and output below was executed against version 0.2.0 in an isolated state directory, with --skarbiec-bin pointed at a stand-in Skarbiec CLI that serves one documented bundle item (team-inbox) — the same JSON shapes a real Skarbiec emits. Your IDs and timestamps will differ. The full command surface is cli; the flag-free operator journey is onboarding.
Build#
Prerequisites: Rust 1.82+, a skarbiec executable, and a mailbox with IMAP over TLS and SMTP over STARTTLS or implicit TLS.
git clone https://github.com/wisent-ai/skrzynka.git
cd skrzynka
cargo build
./target/debug/skrzynka version{
"product": "skrzynka",
"source": "source-build",
"version": "0.2.0"
}Every command prints one JSON object on stdout and exits 0, or one normalized error envelope on stderr and exits nonzero — automation never parses decorative text.
Inspect the zero state#
status creates the state directory and database if missing, counts local resources, and probes whether skarbiec can be started. It resolves no credential and touches no provider.
$ skrzynka --database "$STATE/skrzynka.db" status
{
"product": "skrzynka",
"version": "0.2.0",
"database_path": "/var/folders/.../skrzynka-docs.15ebyxek/state/skrzynka.db",
"schema_version": 4,
"mailbox_count": 0,
"enabled_mailbox_count": 0,
"message_count": 0,
"poll_interval_seconds": 60,
"skarbiec_available": true
}Without --database the default is ~/.local/share/skrzynka/skrzynka.db; without --skarbiec-bin the default is skarbiec on PATH (configuration).
Declare one mailbox in Skarbiec#
Skarbiec owns the mailbox list. Tag one item skrzynka:mailbox; a complete bundle supplies everything, and only non-secret fields are persisted by Skrzynka:
skarbiec retag team-inbox --tags skrzynka:mailbox
skrzynka --database "$STATE/skrzynka.db" mailbox listmailbox list reads the declaration and prints the mailbox that stands for the item: its UUID, skarbiec_item_id, the address and servers from the item, enabled: true, and last_uid: 0. No password or username appears — the row references its receiving item and, only when configured, a separate sending item; each secret is resolved only while its protocol connection is open. Missing source data is reported under reconciliation.refused by sync and never replaced by defaults. skrzynka mailbox declare --skarbiec-item team-inbox does the tagging itself and also imports every INBOX message.
Synchronize and read#
skrzynka --database "$STATE/skrzynka.db" sync
skrzynka --database "$STATE/skrzynka.db" message listAgainst a reachable mailbox, sync prints one result per enabled mailbox with a summary of received, skipped, and the advanced last_uid cursor, and message list shows the normalized messages (sender, subject, snippet, plain-text body). This isolated lab deliberately has no reachable IMAP endpoint, so the same commands return the exact failure shape you will meet in real operations — per-mailbox, normalized, and non-fatal to other mailboxes:
{
"completed_at": "2026-08-24T23:09:24.159599+00:00",
"mailboxes": [
{
"mailbox_id": "3a9f65f0-a6e1-4520-bd35-708731a6a92f",
"ok": false,
"summary": null,
"error_code": "IMAP_UNAVAILABLE",
"error_message": "IMAP server could not be reached over TLS"
}
]
}The failure is also recorded on the mailbox (last_error_code, last_error_message) where mailbox show <id> and the desktop find it. Every code and its fix: runbook.
Serve the loopback API#
$ skrzynka --database "$STATE/skrzynka.db" serve --bind 127.0.0.1:8791
2026-08-24T23:09:52.159767Z INFO skrzynka: Skrzynka API ready address=127.0.0.1:8791serve starts the IMAP IDLE watchers and the authenticated JSON API used by skrzynka-desktop. Only loopback binds are accepted. Health needs no session:
$ curl -s http://127.0.0.1:8791/healthz
{"status":"ready","product":"skrzynka","version":"0.2.0","schema_version":4}Everything under /v1 requires a Wisent bearer and organization header and fails closed without them (API, walkthrough).
Clean up#
skrzynka --database "$STATE/skrzynka.db" mailbox remove <mailbox-uuid> --confirmRemoval cascades through local messages, reply records and the outbound messages that mailbox originated; the Skarbiec item and the provider mailbox are untouched. The captured end-to-end sequence, including every refusal on the way, is walkthrough-local-lifecycle.