Docs / CLI
Ships with the SDKThe flowmails CLI
The SDK is for code. The CLI is for everything that is not code: a terminal session, a cron step, a health check in a deploy script. Same capabilities, same credential, same scopes — five commands, and no raw HTTP anywhere.
# install
npm i -g @flowmails/cli
flowmails --helpThe five commands
flowmails test is the documented connection check — the first thing the install instructions tell you to run, and the first signal in the “time to first agent action” metric.
| Command | What it does |
|---|---|
| flowmails login | Store a credential. Reads the key from a prompt, from stdin, or from --key, and writes it to the config file with 0600 permissions. |
| flowmails test | The connection check: auth, the bound domain, and whether the send path answers. Sends no mail unless you pass --send-to. |
| flowmails addresses | List the account's domains with their routing mode and local parts. --json prints the same thing machine-readably. |
| flowmails watch <addr> | Tail the inbound event log for one mailbox, one JSON object per line. The cursor is persisted, so a reconnect resumes where it stopped. |
| flowmails wait <addr> | Open a durable wait and print the resolved message id. The wait id is persisted too, so a reconnect resumes the same wait. |
The connection check
flowmails test answers three questions in one line, and sends nothing:
- Is the credential live? The account's domains are listed — a rejected or revoked key answers that immediately.
- Which domain is it bound to? The binding is the constraint on sending; the check names it.
- Does the send path answer? The probe is a read against the send origin for a message id that does not exist. A “no such message” answer means the path is live and routed. Nothing was sent.
$ flowmails test
✓ auth ok (fm_012…)
✓ domains: yourapp.com
✓ bound domain: yourapp.com
✓ send path reachable (no message sent)
flowmails test: OK — credential fm_012…, domain yourapp.com, send path reachable (no message sent)Add --send-to someone@example.com to send one real message as part of the check. Without that flag, the check never touches the mail path.
The cursor survives a disconnect
watch and wait persist their position in a state file next to the config, and resume from it on the next run. A dropped connection, a closed laptop or a killed process does not lose a message.
- The cursor is an event id, never a timestamp. Two events can land in the same millisecond, and a cursor that can skip a row loses mail.
- It is written after each event is printed, so a crash replays at most the last one. Delivery is at-least-once, not exactly-once — and the alternative, writing before the print, loses events.
waitpersists the wait id as well, so a reconnect resumes the same wait instead of opening a second one.
$ flowmails watch billing@yourapp.com
{"id":"evt_01","messageId":"<abc@stripe.example>","event":"inbound.received","recipient":"billing@yourapp.com","sender":"no-reply@stripe.example","subject":"Your invoice is ready"}
{"id":"evt_02","messageId":"<def@stripe.example>","event":"inbound.received","recipient":"billing@yourapp.com","sender":"no-reply@stripe.example","subject":"Your receipt"}wait prints the resolved message id on standard output and everything else on standard error, so it composes: id=$(flowmails wait billing@yourapp.com).
Where the key lives
The credential is written to ~/.config/flowmails/config.json with mode 0600, in a directory created with 0700. Override the location with --config or FLOWMAILS_CONFIG.
{
"apiKey": "fm_012…"
}No command prints the key. Every line the CLI writes is scrubbed before it reaches the terminal, so a stack trace carrying the key cannot leak it either — the output shows at most a short prefix.
What the CLI cannot do
Onboarding is the human’s job, by decision and not by omission. The CLI cannot create an account, connect a Cloudflare account, add or verify a domain, deploy the receive worker, or mint a key. Those are dashboard-only.
- Create the account and sign in — dashboard/onboarding
- Mint the key — dashboard/settings/api-keys, or a scoped credential when the agent should hold fewer capabilities.
The device flow is not implemented. flowmails login is the documented paste-a-key fallback: it prompts, or reads the key from stdin or --key, and stores it. It never pretends to authenticate on its own.
The same mailbox, three ways
The CLI is one of three ways to reach the same capabilities. They share one credential and one scope list, so a key that works in one works in all three.
| Surface | Use it when |
|---|---|
| @flowmails/flowmails-sdk | You are writing code. The SDK owns retry, error mapping and attachment encoding — install guide. |
| mcp.flowmails.net | Your agent harness speaks MCP natively. Ten tools, each checked against the credential’s scope —the API page has the list. |
| flowmails | You are in a shell. This page. |
Ship today