# CLI

> Every Pidgeon endpoint as a terminal command: addresses, messages, threads and webhooks, with the same refusals the API gives.

Every endpoint in this documentation is also a command. `@pidgeon-ai/cli` has
one per operation, generated from the same OpenAPI document as the clients, so
it cannot offer a command the API does not have.

```sh
npm install -g @pidgeon-ai/cli
export PIDGEON_API_KEY=pgn_live_…

pidgeon identities list
```

## The shape

```sh
pidgeon <group> <command> [--flags]
```

The group is the resource, the command is what you are doing to it. `pidgeon --help` lists every group; `pidgeon <group> <command> --help` describes one
command, names the endpoint it calls, and lists its flags with the required
ones marked.

```sh
pidgeon messages send \
--from you@yourdomain.com \
--to someone@example.com \
--subject "First one" \
--text "It works."
```

## Flags

**A list flag repeats.** Several recipients are several `--to`:

```sh
pidgeon messages send --from you@yourdomain.com \
--to one@example.com --to two@example.com --subject Hi --text Hello
```

**`--flag value` and `--flag=value` are the same thing**, and a value may
contain an `=` — a subject often does.

**A nested object takes JSON.** Flags are the top level of a request body;
anything below that is a field you pass as a string:

```sh
pidgeon identities update --id 0c939bd7-2d69-4150-a2ac-de994f0e4887 --send_policy reply_only
```

## Where it points

Production, unless you say otherwise. `PIDGEON_BASE_URL` points it at another
deployment — a self-hosted one, or a staging environment of your own:

```sh
PIDGEON_BASE_URL=https://pidgeon.example.com/api/v1 pidgeon identities list
```

## What it returns

The response body, as JSON, on stdout. Nothing is reformatted or summarised,
so `jq` works and so does piping it into anything else:

```sh
pidgeon identities list --limit 5 | jq -r '.data[].email'
```

A failure prints the API's own message to stderr and exits non-zero — `2` for
something wrong with the command line, `1` for anything else. The message is
the one a person should read: *"That address can only reply to people who have
written to it first"* rather than a status code.
