# CLI

Send your first email straight from the terminal: install the `bird` CLI, log in once, and send. No code, no API key to copy around.

## 1. Install

Homebrew (macOS, Linux):

```bash
brew install messagebird/tap/bird
```

Or the install script (macOS, Linux):

```bash
curl -fsSL https://cli.bird.com/install.sh | sh
```

On Windows, use the PowerShell installer at `https://cli.bird.com/install.ps1`. See [Install the CLI](/docs/cli#install) for details.

## 2. Log in

```bash
bird auth login --scope emails:write
```

This opens a browser consent page where you pick a workspace and approve the grant. `--scope emails:write` is what lets step 3 send: a bare `bird auth login` requests a read-only baseline, and the send would be refused. The CLI stores a workspace-bound OAuth token in `~/.config/bird/credentials.json` and refreshes it automatically on use; the API region is recorded from the workspace, so nothing else needs configuring. On a headless machine or over SSH, add `--device` to get a code you approve on another device.

## 3. Send an email

Send from Bird's shared onboarding domain to the [`delivered@messagebird.dev` sandbox address](/docs/guides/email/testing-sandbox): no domain verification, no real mailbox needed.

```bash
bird email send \
  --from onboarding@messagebird.dev \
  --to delivered@messagebird.dev \
  --subject "Hello from Bird" \
  --html "<p>My first Bird email.</p>"
```

The CLI prints the accepted message as JSON. The `*_count` fields track your recipients through the delivery states; right now one recipient is accepted and none are delivered:

```json
{
  "id": "em_01ky7ma8y2es1s2akzk53tmjn0",
  "status": "accepted",
  "category": "marketing",
  "from": { "email": "onboarding@messagebird.dev" },
  "to": [{ "email": "delivered@messagebird.dev" }],
  "subject": "Hello from Bird",
  "accepted_count": 1,
  "processed_count": 0,
  "delivered_count": 0,
  "deferred_count": 0,
  "bounced_count": 0,
  "complained_count": 0,
  "rejected_count": 0,
  "open_count": 0,
  "click_count": 0,
  "track_opens": true,
  "track_clicks": true,
  "created_at": "2026-07-23T13:58:20.866Z"
}
```

`--to` is repeatable for multiple recipients, `--text` sends a plain-text body, and `--dry-run` prints the resolved request without sending it.

## 4. Check the result

`accepted` means Bird took the message and delivers it asynchronously. Read it back by its `em_` ID and watch the status reach `delivered`:

```bash
bird email get em_01ky7ma8y2es1s2akzk53tmjn0
```

Add `--format text` for a human-readable card instead of JSON.

This whole flow is script- and agent-friendly by design: every command emits JSON to stdout by default, errors are a JSON envelope on stderr, and exit codes are semantic, so a script (or an AI agent) branches on structure, never on prose. See [the CLI for agents](/docs/ai/cli-for-agents) for the full contract.

## Next steps

- [CLI reference](/docs/cli): install, authentication, the output contract, and the main command groups.
- [The CLI for agents](/docs/ai/cli-for-agents): JSON output, exit codes, `--dry-run`, and idempotent retries.
- [Send your first email](/docs/get-started/send-your-first-email): the same flow over raw HTTP and the SDKs.
- [Sending domains](/docs/guides/email/sending-domains): verify your own domain for production sending.