CLI
A tiny binary that wraps the API for everyday ops — sending mail, tailing events, and inspecting recent logs.
Install
The CLI source package is available in this repository as @sendix/cli. Public npm, Homebrew, and Scoop packages are not published yet.
# Requires Node.js 20.10+ and pnpm 9
pnpm --filter @sendix/cli build
# Run from the workspace
node packages/cli/dist/index.js --helpAuthenticate
Choose persistent local login for a workstation or environment variables for CI.
# Local workstation: writes ~/.sendix/config.json
node packages/cli/dist/index.js login --api-key "$SENDIX_API_KEY"
# Optional non-production API base for local development
node packages/cli/dist/index.js login \
--api-key "$SENDIX_API_KEY" \
--api-base "http://127.0.0.1:3001/v1"
# CI / containers: no config file required
SENDIX_API_KEY="..." node packages/cli/dist/index.js logs --limit 10Environment variables take precedence over the saved config. SENDIX_API_KEYselects the credential and SENDIX_API_BASE_URL overrides the base URL. The default is https://sendix.dev/api/v1.
~/.sendix with owner-only directory permissions and writes config.json with owner read/write permissions. Disk encryption and account access controls remain your responsibility.Commands
The day-one verbs. sendix --help for the rest.
| Command | What it does |
|---|---|
| sendix login --api-key YOUR_API_KEY | Store a Sendix API key locally. |
| sendix send --from [email protected] --to [email protected] --tpl <template-id> | Send a template-rendered message from the terminal. |
| sendix tail | Stream live email events to stdout during operations. |
| sendix guardian --days 30 | Inspect the live deliverability score, provider posture, and recommended actions. |
| sendix logs --status bounced --limit 20 | Query recent email logs by status. |
Send examples
Inline content
node packages/cli/dist/index.js send \
--from "[email protected]" \
--to "[email protected]" \
--subject "Welcome" \
--text "Your account is ready."Published template
node packages/cli/dist/index.js send \
--from "[email protected]" \
--to "[email protected]" \
--tpl "00000000-0000-4000-8000-000000000000" \
--var "name=Ada" \
--var "plan=Pro"A non-template send requires --subject and at least one of --text or --html. Template sends pass repeated --var key=value pairs as template_data. The command prints the API response as formatted JSON; a successful create includes the email ID.
Logs and tail
# One API request, formatted JSON output
node packages/cli/dist/index.js logs --status bounced --limit 20
# Poll the newest 25 email records every 3 seconds
node packages/cli/dist/index.js tail --status failed --interval 3# Human-readable deliverability posture
node packages/cli/dist/index.js guardian --days 30
# Machine-readable output for CI or your own monitoring
node packages/cli/dist/index.js guardian --days 90 --jsonlogs calls the email list endpoint once. tail is a polling helper, not a streaming socket: it repeats the list request and prints newly observed rows as tab-separated created_at, status, and id values. Stop it with Ctrl+C.
Automation and CI
- • Inject
SENDIX_API_KEYfrom the CI secret store; do not runlogin. - • Use a dedicated least-privilege key with an expiry, domain scope, and IP allowlist where practical.
- • Pin the Sendix source revision used to build the CLI so command behavior cannot drift mid-pipeline.
- • Capture stdout as JSON for
sendandlogs; keep stderr for diagnostics. - • Never enable shell tracing around commands that expand a secret environment variable.
Failures and exit codes
| Exit | Meaning | Examples |
|---|---|---|
| 0 | Command completed. | Login saved, send accepted, or list returned. |
| 1 | Usage or non-server API failure. | Missing flag, invalid key, forbidden, validation error. |
| 2 | The API returned a 5xx response. | Temporary server or dependency failure. |
The current CLI performs one request per command and does not add an automatic retry policy. If a job retries send, use the HTTP API or Node SDK with a stable idempotency key so an ambiguous network failure cannot create a duplicate message.

