# Command line (npx agentboxd)

Source: https://agentboxd.com/docs/cli

> Manage inboxes, send and read mail, wait for verification codes and watch events live from a terminal or a script with npx agentboxd.

The `agentboxd` npm package includes a command line. It uses the same API key and sees the same inboxes as the SDKs and the MCP server, prints tables for people and JSON for scripts, and needs nothing but Node.js 20 or newer.

shell:

```bash
npx agentboxd login                        # paste your key at the hidden prompt
npx agentboxd inboxes create --username support-agent --client-id support-agent
npx agentboxd send support-agent@homingbox.net \
  --to someone@example.com --subject "Hello" --text "Reply to this and my agent will see it."
npx agentboxd messages list support-agent@homingbox.net --unread
```

## Install and log in

Run it with `npx agentboxd …` without installing, or install it once with `npm install -g agentboxd`. Then log in with a key from [API keys](https://agentboxd.com/app/api-keys):

shell:

```bash
npx agentboxd login              # prompts for the key without echoing it
echo "$KEY" | npx agentboxd login   # or pipe it (CI, scripts)
npx agentboxd whoami             # workspace, plan and where the key came from
```

- `login` checks the key against the API and saves it in `~/.config/agentboxd/config.json` (`$XDG_CONFIG_HOME` if set) on macOS and Linux, or `%APPDATA%\agentboxd\config.json` on Windows. The file is readable by your user only (mode 0600). `logout` deletes it.
- `AGENTBOXD_API_KEY` in the environment always wins over the saved key, so CI and agents never need `login`.
- The key is never taken as a command-line flag, so it doesn’t end up in your shell history.
- API keys are created and revoked in the dashboard, not from the command line.

## Commands

`<inbox>` is an inbox id or its address. Every command takes `--json` (print the API response) and `--base-url`; `npx agentboxd <command> --help` shows its options.

| Command | What it does |
| --- | --- |
| `login` · `logout` · `whoami` | Save, delete or check the API key. |
| `inboxes list [--temporary]` | Your inboxes, temporary ones included (`--temporary`: only those). |
| `inboxes create [--username] [--display-name] [--client-id] [--domain]` | A new inbox; the same `--client-id` returns the same inbox. Prints the address. |
| `inboxes create --temporary [--ttl 900]` | A receive-only inbox that deletes itself after the TTL (60 s to 24 h). See [Temporary inboxes](https://agentboxd.com/docs/temporary-inboxes). |
| `inboxes pause <inbox> [--reason]` · `inboxes resume <inbox>` | The kill switch: refuse every send from the inbox, and turn sending back on. |
| `send <inbox> --to … --subject …` | A new email. Body from `--text`, `--text-file`, `--html-file` or stdin; `--cc`, `--bcc`, `--attach FILE` (repeatable), `--idempotency-key`. |
| `reply <inbox> <message-id>` | A reply in the thread; `--all` answers everyone. Same body options. |
| `messages list [<inbox>] [--unread] [--direction]` | Newest first; `*` marks unread mail. Without an inbox, the mail of every inbox the key can see. `--cursor` for the next page. |
| `messages get <message-id>` | One message: headers, warnings, a detected code, attachments and the new text of the email. |
| `wait-code <inbox> [--since 10m\|ISO] [--from] [--timeout 120]` | Waits for a verification code or magic link and prints only it. See below. |
| `tail [--inbox …] [--event …] [--envelope] [--since EVENT_ID]` | Prints events as they happen, over the [realtime stream](https://agentboxd.com/docs/realtime-events), until Ctrl-C. |
| `drafts list [<inbox>] [--status draft,scheduled]` | Drafts waiting for review, in every inbox or one. |
| `drafts send <inbox> <draft-id>` | Approve and send a draft now. See [Drafts](https://agentboxd.com/docs/drafts). |
| `events list [<inbox>] [--response needs_action] [--expand]` · `events get <event-id>` · `events respond <event-id> --response accepted [--draft]` | [Meetings](https://agentboxd.com/docs/api#meetings): invites and meetings, soonest first (`--expand` lists each occurrence of a [series](https://agentboxd.com/docs/api#recurring-series)); one meeting with its organizer check; the answer, which goes to the organizer only (`--comment`, or `--propose-start` and `--propose-end` for another time). `--draft` saves the answer for a person to approve instead of sending it ([meeting drafts](https://agentboxd.com/docs/drafts#meeting-drafts)). |

## Scripts and sign-up codes

`wait-code` prints just the code (or the link when there is no code) on stdout and the details on stderr, so it drops into a shell variable. Take the time before you trigger the email and pass it as `--since`; a duration such as `--since 5m` works too. It waits up to `--timeout` seconds and exits with status 3 if nothing arrived.

signup.sh:

```bash
inbox=$(npx agentboxd inboxes create --temporary --ttl 900 --json | jq -r .id)
since=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# … submit the sign-up form with the inbox's address …
code=$(npx agentboxd wait-code "$inbox" --since "$since" --from acme.com --timeout 120) || exit 1
echo "code: $code"
```

With `--json` every command prints the API’s response unchanged (the same objects as the [API reference](https://agentboxd.com/docs/api)), and errors as `{ "error": { "status", "code", "message", "details" } }`.

| Exit status | Meaning |
| --- | --- |
| 0 | Done. |
| 1 | The API refused the request or could not be reached. The message and a hint are on stderr, e.g. `401` (log in again), `403` (the key lacks a permission), `423 inbox_paused`, `429` (with the wait). |
| 2 | A usage error: an unknown command or option, a missing argument, no API key. |
| 3 | `wait-code` timed out. |

## Watch events live

`tail` opens the realtime stream with a single-use token, reconnects on its own and resumes where it left off. `--json` prints one event per line, ready for `jq`. It needs Node.js 22 or newer, or the `ws` package installed next to it.

shell:

```bash
npx agentboxd tail --inbox support-agent@homingbox.net --event message.received
2026-09-26 10:04  message.received        Dana <dana@example.com>  Opening hours  7c1e…

npx agentboxd tail --json | jq -c 'select(.type == "message.bounced")'
```

## For agents

Coding agents with a shell (Claude Code, Codex, Cursor and others) can use the CLI directly: give them `AGENTBOXD_API_KEY` and they can create an inbox, read a code with `wait-code` and answer mail. `messages get` starts the email text with an `UNTRUSTED EMAIL CONTENT` line and shows a `warning:` line for mail that failed authentication or looks like phishing or prompt injection, like the [MCP server](https://agentboxd.com/docs/mcp) does. The [agent skill](https://agentboxd.com/docs/mcp#agent-skill) teaches them when to use which command.

## Other servers

Point the CLI at a [dedicated deployment](https://agentboxd.com/docs/self-hosting) or a local development server with `--base-url http://localhost:3000` or `AGENTBOXD_BASE_URL`. `login --base-url …` saves the URL with the key. The order is: `--base-url`, then `AGENTBOXD_BASE_URL`, then the saved URL, then `https://api.agentboxd.com`.
