> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.postnuvia.com/llms.txt.

# CLI

> PostNuvia's official command-line interface

## Getting started

The PostNuvia CLI lets you interact with the PostNuvia API directly from your terminal. Create inboxes, send messages, manage threads, and more — all without writing code. It ships as a single native binary with no runtime dependencies.

### Installation

Install with npm:

```bash
npm install -g postnuvia-cli
```

Or install from the release script, which picks the right binary for your machine:

```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/postnuvia-to/postnuvia-cli/releases/latest/download/postnuvia-cli-installer.sh | sh
```

Both paths give you a statically linked binary with no system dependencies, on any Linux distribution. Prebuilt archives are also on the [releases page](https://github.com/postnuvia-to/postnuvia-cli/releases) — see [Platform support](#platform-support) before picking one by hand.

#### Platform support

| Platform                                          | Requirement                                                                                                                                                                                     |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| macOS                                             | 11+ (Apple Silicon and Intel)                                                                                                                                                                   |
| Linux — npm, or `postnuvia-cli-installer.sh`      | None. You get the static musl build.                                                                                                                                                            |
| Linux — `*-linux-musl.tar.gz` downloaded manually | None. Runs on Alpine and on `scratch`/distroless images.                                                                                                                                        |
| Linux — `*-linux-gnu.tar.gz` downloaded manually  | **glibc 2.34+ and OpenSSL 3.** Debian 12 needs `apt install libssl3`; Ubuntu 20.04, Amazon Linux 2, and other glibc \< 2.34 distributions cannot run this build — use the musl archive instead. |
| Windows                                           | x64. On Windows ARM64 the installer currently fetches the x64 binary.                                                                                                                           |

If a manually downloaded `-gnu` binary fails to start, the error names only the first thing it cannot find, which makes two different problems look alike:

```
error while loading shared libraries: libssl.so.3: cannot open shared object file
```

On Debian 12 that really is just the library — install `libssl3` and it works. On older distributions the same message hides a glibc floor you cannot install past (`GLIBC_2.34 not found` appears once OpenSSL is present). Rather than diagnosing it, switch to the musl archive, which has no such requirements.

### Authentication

Set your API key as an environment variable:

```bash
export POSTNUVIA_API_KEY=am_us_xxx
```

Or store it in your OS keychain so it survives across shells:

```bash
postnuvia auth login --with-token --scheme BearerAuth   # paste your API key when prompted
postnuvia auth status                                   # shows which credential source is active
```

Get your key from the [PostNuvia Console](https://console.postnuvia.com).

## Usage

Commands follow the resource structure of the API, with nested subcommands:

```bash
postnuvia <resource> [subresource] <command> [flags...]
```

```bash
postnuvia inboxes messages send --inbox-id inb_xxx --to user@example.com --subject "Hello" --text "Hi there"
```

Use `--help` on any command for details, or `--schema` for a machine-readable description of every command — useful when an AI agent is driving the CLI.

### Examples

```bash
# List inboxes
postnuvia inboxes list

# Create an inbox
postnuvia inboxes create --display-name "My Inbox"

# Send a message
postnuvia inboxes messages send \
  --inbox-id inb_xxx \
  --to user@example.com \
  --subject "Hello" \
  --text "Hi there"

# Preview the request without sending it
postnuvia inboxes messages send --dry-run \
  --inbox-id inb_xxx \
  --to user@example.com \
  --subject "Hello" \
  --text "Hi there"

# List threads
postnuvia inboxes threads list --inbox-id inb_xxx

# Create a webhook
postnuvia webhooks create \
  --event-types message.received \
  --url https://example.com/webhook
```

## Features

The CLI provides commands for:

* **Inbox management:** Create, list, update, and delete inboxes
* **Message operations:** Send, reply, forward, and read emails
* **Thread management:** List, search, and manage email threads
* **Drafts:** Create, update, send, and delete drafts
* **Webhooks:** Create and manage webhook endpoints
* **Domains:** Add and verify custom domains
* **Pods:** Manage pod resources and their inboxes
* **API keys:** Create and manage API keys

## Global flags

| Flag         | Description                                                                                                              |
| ------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `--format`   | Output format: `json`, `table`, `yaml`, `csv`, `raw`, `jsonl`, `http`. Default: `table` on a terminal, `json` when piped |
| `--dry-run`  | Validate and print the request locally without sending it                                                                |
| `--base-url` | Override the API base URL (or set `POSTNUVIA_BASE_URL`)                                                                  |
| `--schema`   | Print a machine-readable JSON schema for the current scope                                                               |
| `--quiet`    | Suppress stdout on success (errors still go to stderr)                                                                   |
| `--help`     | Show help                                                                                                                |
| `--version`  | Show version                                                                                                             |

Request-bearing commands additionally accept `--json <JSON|->` to supply the whole request body as JSON (or from stdin), `--params <JSON>` to merge extra parameters, and `--query <EXPR>` to filter output with a [JMESPath](https://jmespath.org) expression.

Shell completions (`postnuvia completion`) and man pages (`postnuvia man`) are built in.

## Known limitations

* **Windows npm package** — `npm install -g postnuvia-cli` does not yet install a Windows binary. Windows users should install from the [GitHub releases page](https://github.com/postnuvia-to/postnuvia-cli/releases) (`postnuvia-cli-installer.ps1`), which ships the same binary. On Windows ARM64 that installer fetches the x64 binary, which runs under emulation.
* **`--dry-run` is not an acceptance guarantee.** Flag values are type-checked locally, so `--limit abc` fails before a request is made. `--dry-run` then shows the request that would be sent — the API can still reject it on grounds the CLI cannot check, such as an unknown ID or a permission error.
* **No auto-pagination.** List commands return one page. Paginate manually: pass `--limit`, read `next_page_token` from the response, and pass it back as `--page-token`.

## Apps commands

`postnuvia providers` was renamed to `postnuvia apps` when the API renamed
`/v0/providers` to `/v0/apps`. The `providers` commands and the endpoints they
call are removed, so CLI 1.7.0 and earlier cannot browse or connect apps.
Upgrade with `npm install -g postnuvia-cli@latest` and use `apps`:

| Removed                                                                         | Use instead                                                      |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `postnuvia providers list`                                                      | `postnuvia apps list`                                            |
| `postnuvia providers search --q <name>`                                         | `postnuvia apps search --q <name>`                               |
| `postnuvia providers get --provider-id <provider_id>`                           | `postnuvia apps get --app-id <app_id>`                           |
| `postnuvia providers list-accounts --provider-id <provider_id>`                 | `postnuvia apps list-accounts --app-id <app_id>`                 |
| `postnuvia providers connect --provider-id <provider_id> --inbox-id <inbox_id>` | `postnuvia apps connect --app-id <app_id> --inbox-id <inbox_id>` |

Accounts carry `app_id` and `app_name` in place of `provider_id` and
`provider_name`.

The `provider_connect` and `provider_share_owner` permissions are now `app_connect`
and `app_share_owner`. The CLI checks `--permissions` against the names it knows, so
releases from the permission rename on reject `provider_connect` as an unknown
property, and earlier releases reject `app_connect`. Switch the names in your
scripts when you upgrade. The API rejects the old names with a `400`.

## Upgrading to 1.4

Public keys and AgentID sign-in keys use the same `api-keys` commands as bearer
keys. Upgrade with `npm install -g postnuvia-cli@latest` to use these commands:

| Operation                                    | Current command                                                               |
| -------------------------------------------- | ----------------------------------------------------------------------------- |
| Start an app sign-in                         | `postnuvia apps connect --app-id <app_id> --inbox-id <inbox_id>`              |
| Authorize a pending sign-in                  | `postnuvia inboxes authorize --inbox-id <inbox_id> --auth-token <auth_token>` |
| Accept an app's disclosure                   | Add `--accept-disclosure true` to connect or authorize                        |
| List public keys                             | `postnuvia api-keys list --type public_key`                                   |
| Register a public key                        | `postnuvia api-keys create --public-key '<jwk>'`                              |
| Check sign-in key status                     | `postnuvia api-keys get --api-key-id <api_key_id>`                            |
| Rename a key                                 | `postnuvia api-keys update --api-key-id <api_key_id> --name <name>`           |
| Revoke a key or cancel a pending sign-in key | `postnuvia api-keys delete --api-key-id <api_key_id>`                         |

Connect and authorize require `app_connect`. Accepting a disclosure that
shares the owner's name or email also requires `app_share_owner`. Connect
automatically supplies an idempotency key; use `--idempotency-key` to reuse the
same attempt across manual runs.

The dedicated public-key lifecycle commands have been removed. Revoke multiple
keys by listing them and deleting each one individually. See
[AgentID Sign-In](https://docs.postnuvia.com/agentid-sign-in) for the full flow.

New in 1.4: `postnuvia inboxes search` and `postnuvia pods inboxes search`, `postnuvia api-keys get`,
and `update` under `api-keys`, `inboxes api-keys`, and `pods api-keys`. `postnuvia api-keys list`
takes `--type`, and `postnuvia threads get` takes `--limit` and `--page-token`.

## Upgrading to 1.2

`POSTNUVIA_TOKEN` is no longer read. Versions 1.0 and 1.1 accepted it as an alternative to
`POSTNUVIA_API_KEY`; no other PostNuvia surface ever used it, and it has been removed. If you
set it, switch to the standard variable:

```bash
export POSTNUVIA_API_KEY="$POSTNUVIA_TOKEN"
```

Nothing else changed — commands, flags and output formats are identical to 1.1. Query flags are
now type-checked locally, so an invalid `--limit abc` fails before a request is made instead of
returning a 400 from the API.

## Upgrading from 0.7.x

Version 1.0 is a full rewrite, and some invocations changed:

| 0.7.x                                       | 1.0                                                                                     |
| ------------------------------------------- | --------------------------------------------------------------------------------------- |
| `postnuvia inboxes:messages send ...`       | `postnuvia inboxes messages send ...` (spaces, not colons)                              |
| `postnuvia inboxes retrieve ...`            | `postnuvia inboxes get ...`                                                             |
| `postnuvia threads retrieve-attachment ...` | `postnuvia threads get-attachment ...`                                                  |
| `--format pretty` / `explore`               | `--format table` (default on a terminal); `raw` and `jsonl` still work, plus new `http` |
| `--transform` (GJSON)                       | `--query` (JMESPath)                                                                    |
| `--api-key` flag                            | `POSTNUVIA_API_KEY` env var or `postnuvia auth login --with-token --scheme BearerAuth`  |

Environment variables are unchanged: `POSTNUVIA_API_KEY` keeps working as before.

> **Note**
>
> If you pin an older 0.7.x release, note that it installs its binary through a `postinstall` script. npm 12 blocks install scripts by default, so on npm 12 or newer a 0.7.x install completes but leaves no working binary — `postnuvia` then fails with `spawnSync … bin/.postnuvia ENOENT`. Version 1.0 and later ship the binary inside the package and are unaffected.

## AI skill

The CLI can generate [AgentSkills](https://skills.sh)-compatible skill files directly from its own command surface:

```bash
postnuvia generate-skills --output-dir skills
```

It is also available as a prebuilt skill:

```bash
openclaw skills install postnuvia-to/postnuvia-skills/postnuvia-cli
```

This works with any compatible tool, including OpenClaw, Claude Code, Cursor, and Codex. See the [Skills](/integrations/skills) page for more details.