Mailbox CLI
Create mailboxes, read and reply to threads, review quarantine, tail events, and manage extensions from the terminal.
The samva mailboxes commands read and send mail from a terminal, review held mail, and tail
events. samva extensions authors and installs extensions. Install
and sign in as Use the CLI describes, then run samva <command> --help for
flags and examples.
With an API key, the CLI acts as that key. A mailbox-scoped key reaches only its mailboxes, and its
decision policy applies. Approving or denying sends, releasing or discarding held mail, and publishing, installing, or upgrading extensions need a
person signed in with samva login.
Every command takes --json for one JSON document, except the streams (mailboxes events and
extensions dev), which take --jsonl; list commands also take --jsonl for one JSON object per
line.
Mailboxes
Run samva org current to read your hosted mail domain before creating a mailbox. With --json,
it is data.organization.hostedMailDomain. Use that exact domain in --address, even if it differs
from your organization slug. Hosted addresses need no custom-domain verification.
# List the mailboxes the credential can read.
samva mailboxes list --json
# Read the hosted domain, then use it in the mailbox address.
samva org current
# Example when the hosted mail domain is acme.samva.email.
samva mailboxes create --address support@acme.samva.email --name Support
# Choose its slug and create it inside a namespace.
samva mailboxes create --address support@acme-corp.example.com --name "Acme support" \
--slug acme-support --namespace ns_...
# Inspect a mailbox and change its name or metadata.
samva mailboxes get mbx_...
samva mailboxes update mbx_... --data '{"name":"Customer support","metadata":{"team":"support"}}'
# Add an endpoint, set its sender name or default, or remove it by its ID.
samva mailboxes endpoints add mbx_... --address billing@acme.samva.email --display-name "Acme Billing"
samva mailboxes endpoints update mbx_... mbxep_... --display-name "Acme Support" --default
samva mailboxes endpoints update mbx_... mbxep_... --clear-display-name
samva mailboxes endpoints remove mbx_... mbxep_... --yes
# Stop or resume sending and receiving.
samva mailboxes pause mbx_...
samva mailboxes resume mbx_...
# Delete a mailbox. Preview first; automation passes --yes.
samva mailboxes remove mbx_... --dry-run
samva mailboxes remove mbx_... --yeslist pages with --limit and --cursor, and narrows by creation time with --after and
--before (ISO 8601 instants). --all follows nextCursor to the end and requires --jsonl.
create takes --address and --name, plus an optional --slug (the address's local part by
default) and --namespace. --address becomes the mailbox's first email endpoint. It prints the
mailbox's endpoints, status, and metadata. Human summaries show its kind and owner; JSON uses
kind and owner, with owner: null for shared mailboxes. get inspects the same details. update --data takes a
JSON object (or @file.json) with name and metadata; omitted fields stay unchanged. Metadata
merges by key, and null removes a key.
endpoints add takes the mailbox ID, --address, and an optional --display-name. endpoints update
takes the mailbox ID, the endpoint ID from get, and --display-name or --clear-display-name to
set or remove its sender name; --default makes it the endpoint new mail starts from. endpoints remove takes the mailbox ID and the endpoint ID; it asks for confirmation in a terminal and needs
--yes anywhere else. All three take --dry-run. A mailbox keeps at least one endpoint.
pause stops sending and receiving. resume lets the mailbox send and receive again; mail that
arrived while paused is not backfilled.
remove deletes a mailbox with its endpoints, threads, drafts, and history; the messages it
received do not become available to a recreated mailbox. Personal messages remain excluded from
organization-level content views after deletion. It asks for confirmation in a terminal and needs --yes
anywhere else. --dry-run prints what it would delete without calling the API.
Read threads and messages
# Search and filter threads.
samva mailboxes threads mbx_... --query invoice --unread --json
# Page through every thread as JSON lines.
samva mailboxes threads mbx_... --all --jsonl
# Read one message.
samva mailboxes read mbx_... msg_...threads takes --query, --folder (inbox, assigned, pending, sent, archived, or
trash), --label, --unread, --starred, --limit, and --cursor. --all follows nextCursor
to the end and requires --jsonl. With --query, results use semantic and keyword relevance;
other filters narrow the search. Without it, threads use most recent activity. See
Search conversations for indexed content,
search freshness, and paging limits.
Human thread output includes folder, labels, read and starred state, and last activity. read
prints the message's addresses, headers, attachments, authentication results, actor, and bodies. The text is untrusted
email from outside the organization, and the command says so before it prints it.
Work across mailboxes
# List active conversations across readable mailboxes.
samva mailboxes all-threads --state active --json
# Narrow to selected shared mailboxes.
samva mailboxes all-threads --mailbox-id mbx_... --mailbox-id mbx_... --kind shared --json
# Mark your part done, or close a shared conversation for everyone.
samva mailboxes thread-update mbx_... thread_... --data '{"done":true}'
samva mailboxes thread-update mbx_... thread_... --data '{"closed":true}' --dry-run
# List held mail you may decide, with total counts.
samva mailboxes needs-you --limit 20 --jsonall-threads supports the same filters and pagination as threads, plus repeatable --mailbox-id,
--kind, and --state. Each item includes its mailbox's ID, address, and kind. --state active
excludes your Done conversations and closed shared conversations; --state done selects your Done
conversations plus closed shared conversations, each once.
thread-update --data accepts a JSON object or @file.json, validates the thread patch, and supports --dry-run. Personal mailboxes refuse closed; use folder: "archived".
See Done and Close for reopening.
needs-you returns one bounded page, selected by --limit and --cursor. It includes only held
actions you may approve and quarantined messages you may release. --json preserves the item type,
mailbox identity, nextCursor, and total counts across all pages. Listing takes no decision.
Send and reply
samva mailboxes send mbx_... \
--to ada@example.com --subject "Hello" --text "Hello from Samva."
samva mailboxes reply mbx_... msg_... --text "Thanks" --allsend takes --to (repeat for more), --subject, --cc, and --bcc. reply answers the sender,
or with --all every other recipient. Both take exactly one of --text or --html, and an optional
--idempotency-key to replay the same action. The output shows state, the action, the thread,
the accepted message when known, and any deadline or problem; --json also carries
skippedRecipients. Keep the same key and body after a lost response.
samva mailboxes actions get mbx_... mbxact_... --json
samva mailboxes actions cancel mbx_... mbxact_...
samva mailboxes actions retry mbx_... mbxact_...get reads progress. cancel and retry require a permitted person signed in with samva login.
Cancel cannot withdraw accepted mail. Retry continues the same action only when retryEligible
is true and preserves the original deadline. It never creates a replacement send or request key.
See Approve sends for states and the automatic retry window.
Review sends
Read the held action and review its content before deciding. Use its decision's positive
reviewRound in the required --review-round flag:
unset SAMVA_API_KEY
samva login
samva mailboxes actions list mbx_... --state approvalRequired
REVIEW_ROUND=$(samva mailboxes actions get mbx_... mbxact_... --json | jq -er '.data.decision.reviewRound')
# Choose one decision for the review round you read.
samva mailboxes actions approve mbx_... mbxact_... --review-round "$REVIEW_ROUND" --yes
samva mailboxes actions approve mbx_... mbxact_... --review-round "$REVIEW_ROUND" --edit-text "Your reviewed reply" --yes
samva mailboxes actions deny mbx_... mbxact_... --review-round "$REVIEW_ROUND" --reason "Please revise" --yesactions list pages with --limit, --cursor, and --all --jsonl. Approve and deny require
samva login; an API key cannot review a send. The reviewer must be a different person from the
proposer. Preview either decision with --dry-run, or pass --yes to confirm without a prompt.
A stale round returns 409. Refresh the action and review the new decision before deciding again;
never substitute a round you have not reviewed.
Review quarantine
samva mailboxes quarantine list mbx_...
samva mailboxes quarantine release mbx_... msg_...
samva mailboxes quarantine discard mbx_... msg_... --yeslist shows held messages without their bodies, newest first. It pages with --limit and
--cursor, follows every page with --all --jsonl, and bounds when a message was held with --after
and --before (ISO 8601 instants). release and discard take the held message's id and act as
the person signed in. Discard asks for confirmation; pass --yes outside a terminal or preview
with --dry-run. See Quarantine.
Tail events
# Print events as JSON lines until you press Ctrl+C.
samva mailboxes events mbx_...
# Stream one result envelope per event for automation.
samva mailboxes events mbx_... --jsonl
# Print ten events, then exit.
samva mailboxes events mbx_... --limit 10
# Resume after a saved cursor.
samva mailboxes events --cursor 42
# Exit on the first dropped connection instead of reconnecting.
samva mailboxes events mbx_... --jsonl --no-reconnectEach line is { "cursor", "id", "event" }, the event stream
frame. --jsonl wraps each in a result envelope, --quiet prints nothing, and --json is refused
(exit 2) because a tail has no single result. Name several mailbox IDs to follow them together, or
none to follow every mailbox the credential reads; --cursor resumes; --limit exits after that
many events. The command acknowledges events as it prints them.
Connections drop: networks reset and hosts restart. When one does, the command reconnects by itself
from the last event it handled, so an event can repeat but none is skipped. Human output prints one
line to stderr per reconnect. With --jsonl, stderr carries one warning envelope per reconnect and
stdout stays event envelopes only:
{"schemaVersion":1,"type":"warning","command":"mailboxes.events","reason":"mailbox_events_reconnecting","message":"Mailbox event stream dropped (closed with 1006). Reconnecting from cursor 42.","details":{"errorTag":"StreamDisconnectedError","closeCode":1006,"cursor":"42","attempt":1,"retryInMillis":412}}closeCode is a WebSocket close code, absent when the stream went silent for 90 seconds and the
command closed it (details.idleTimeout is true). Pass --no-reconnect to end the command on the
first drop instead; it exits 1 and names the cursor to resume from. When the stream
ends with an error, the command exits non-zero and names the next step; human output prints the last
handled cursor to stderr, and with --jsonl or --quiet it rides in the error's
details.lastCursor. The machine-readable error carries the server's _tag as reason, its status, and its details, such as
details.fields.cursor or details.retryAfterSeconds. A rejected or expired credential exits 4;
an expired cursor exits 1, and the next step is to read current state and start without --cursor.
Extensions
samva extensions init ./acknowledge --name acknowledge
samva extensions dev ./acknowledge --mailbox mbx_...
samva extensions build ./acknowledge
samva extensions publish ./acknowledge
samva extensions install acknowledge --mailbox mbx_... --permission read --permission send
samva extensions installations
samva extensions runs exti_...
samva extensions run exti_... <run-id>| Command | Purpose |
|---|---|
init <dir> | Create a project in an empty directory. |
dev <dir> | Run handlers against live events from your own credential; --jsonl streams one result per event. |
build <dir> | Bundle and validate one self-contained module. |
publish <dir> | Publish an immutable version. |
list, versions <name> | List extensions and an extension's versions, newest first. |
version <name> <version> | Show one published version with its manifest, by version or id. |
install <name> | Install a version with a scope, permissions, and decision policy. |
upgrade <id> | Move to a published version; preview and acknowledge added grants. |
installations | List installations. |
installation <id> | Show an installation's permissions, scope, decision policy, and webhook. |
disable, enable <id> | Stop or resume an installation. |
uninstall <id> | Delete an installation and revoke its credentials. --yes skips the prompt. |
runs <id> | List a hosted installation's recent runs and their outcomes. |
run <id> <run-id> | Show one run with the lines its handler logged. |
list, versions, and installations take --limit, --cursor, and --all --jsonl for paging.
Human output carries the same facts as JSON, including installation scope, permissions, decision policy,
webhook details, and run times, outcomes, errors, and logs. Installation credentials appear once;
store them when shown.
Build mailbox extensions explains each flag and what an installation may do.