Skip to navigation

CLI

Manage PostNuvia resources from the command line

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:

npm install -g postnuvia-cli

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

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 — see Platform support before picking one by hand.

Platform support

PlatformRequirement
macOS11+ (Apple Silicon and Intel)
Linux — npm, or postnuvia-cli-installer.shNone. You get the static musl build.
Linux — *-linux-musl.tar.gz downloaded manuallyNone. Runs on Alpine and on scratch/distroless images.
Linux — *-linux-gnu.tar.gz downloaded manuallyglibc 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.
Windowsx64. 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:

export POSTNUVIA_API_KEY=am_us_xxx

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

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.

Usage

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

postnuvia <resource> [subresource] <command> [flags...]
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

# 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

FlagDescription
--formatOutput format: json, table, yaml, csv, raw, jsonl, http. Default: table on a terminal, json when piped
--dry-runValidate and print the request locally without sending it
--base-urlOverride the API base URL (or set POSTNUVIA_BASE_URL)
--schemaPrint a machine-readable JSON schema for the current scope
--quietSuppress stdout on success (errors still go to stderr)
--helpShow help
--versionShow 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 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 (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:

RemovedUse instead
postnuvia providers listpostnuvia 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:

OperationCurrent command
Start an app sign-inpostnuvia apps connect --app-id <app_id> --inbox-id <inbox_id>
Authorize a pending sign-inpostnuvia inboxes authorize --inbox-id <inbox_id> --auth-token <auth_token>
Accept an app’s disclosureAdd --accept-disclosure true to connect or authorize
List public keyspostnuvia api-keys list --type public_key
Register a public keypostnuvia api-keys create --public-key '<jwk>'
Check sign-in key statuspostnuvia api-keys get --api-key-id <api_key_id>
Rename a keypostnuvia api-keys update --api-key-id <api_key_id> --name <name>
Revoke a key or cancel a pending sign-in keypostnuvia 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 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:

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.x1.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 flagPOSTNUVIA_API_KEY env var or postnuvia auth login --with-token --scheme BearerAuth

Environment variables are unchanged: POSTNUVIA_API_KEY keeps working as before.

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-compatible skill files directly from its own command surface:

postnuvia generate-skills --output-dir skills

It is also available as a prebuilt skill:

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 page for more details.