Bubble Tea CLI Guide
CLI source: cli/zmail
Install/Run
cd cli/zmail
go mod tidy
go run . --base-url https://zerg-mail.com
Session file defaults to:
~/.config/zmail-cli/session.json
Override:
go run . --base-url https://zerg-mail.com --session-file /path/session.json
Supported Workflows
- Login and session restore
- Workspace selection
- Mailbox selection
- Inbox browsing and message detail
- Read/archive/spam/trash actions
- Compose and send with attachments
- Reply with preserved threading headers
- Create mailboxes
- Manage webhooks (list/create/toggle/delete/test + delivery previews)
- Headless automation commands for bootstrap, drafts, threads, policies, webhooks, sent tracking, and authenticated raw API access
Main Keybindings
Global
ctrl+c/q: quit
Login
tab/shift+tab: move fieldenter: submit
Inbox/Message
j/kor arrows: move selectionenter: open messagefortab: cycle folderu: toggle reada: archives: spamt: trashd: download attachments
Compose
[/]: switch sender mailboxctrl+s: sendesc: cancel
Mailbox Management
n: create mailbox
Webhooks
h: open webhooks manager (from mailbox or inbox)c: create webhookx: toggle active/inactive on selected webhookt: send test event (message.received)d: delete selected webhookr: refreshb/esc: back
Known Notes
- Test action currently emits
message.received; other test event types are available via API. - CLI is session-based and requires a valid product account.
Headless Automation
Run the CLI with a command to skip the TUI and operate in JSON-producing automation mode.
go run . --base-url http://127.0.0.1:18080 bootstrap local --email operator@example.com --password password123
go run . --base-url http://127.0.0.1:18080 mailbox list
go run . --base-url http://127.0.0.1:18080 message list --folder sent
go run . --base-url http://127.0.0.1:18080 message get --id 42 --mark-read
go run . --base-url http://127.0.0.1:18080 send --from postmaster@local.zmail.test --to user@example.com --subject "Hello" --body "Hi"
go run . --base-url http://127.0.0.1:18080 send --from agents@local.zmail.test --to user@example.com --subject "Re: Hello" --body "Hi back" --reply-to-message-id 42
go run . --base-url http://127.0.0.1:18080 draft list
go run . --base-url http://127.0.0.1:18080 thread list
go run . --base-url http://127.0.0.1:18080 policy list --direction outbound --type block
go run . --base-url http://127.0.0.1:18080 webhook list
go run . --base-url http://127.0.0.1:18080 sent list
Named automation commands currently cover:
auth login|whoami|logoutbootstrap localworkspace list|selectmailbox list|createmessage list|get|read|move|labels|attachment-downloaddraft list|get|create|update|delete|sendthread list|get|labelspolicy list|get|create|deletewebhook list|get|create|update|delete|test|deliveriessent listsendrequest
Use request when you need a raw endpoint that is newer than the typed surface.
It accepts repeatable --query key=value and --header name=value flags plus
--bearer for service-token calls. When --output is used, the raw response is
written with owner-only (0600) permissions; use that form for one-time domain
verification or service-token responses.
# Create a workspace-owned sending domain with the saved human session
go run . --base-url https://zerg-mail.com request --method POST \
--path /app/api/sending-domains \
--body '{"domain":"example.com","selector":"zmail1"}'
# Create a mailbox-scoped service token after DNS verification
go run . --base-url https://zerg-mail.com request --method POST \
--path /app/api/service-tokens \
--body '{"sending_domain_id":1,"mailbox":"auth@example.com","name":"Auth worker","scopes":["message:send"]}' \
--output "$HOME/.config/zmail-cli/auth-service-token.json"
# Exercise the transactional API without a human session
go run . --base-url https://zerg-mail.com request --method POST \
--path /v1/transactional/messages \
--bearer "$ZMAIL_SERVICE_TOKEN" \
--header "Idempotency-Key=core-auth-email:$OUTBOX_ID" \
--body '{"from_mailbox":"auth@example.com","to":"user@example.net","subject":"Verify","body":"Code: 123456"}'