Skip to main content
The messages-dev CLI is the fastest way to poke at the API by hand, pipe a shell pipeline into a message, or stream live events into a local dev server. It is a single self-contained binary built from the same SDK that powers the TypeScript client.

Install

The script detects your OS and architecture (macOS arm64/x64, Linux arm64/x64), downloads the matching binary from the latest GitHub release, verifies its SHA-256 checksum, and installs it to ~/.messages/bin/. It prints the line you need to add to your shell rc.
Pin a specific release with MESSAGES_CLI_VERSION=v0.2.0 or change the install location with MESSAGES_INSTALL=/opt/messages.
If you already have Node.js, you can install via npm instead:
On macOS the curl-installed binary is not yet signed with an Apple Developer ID. The first time you run it, Gatekeeper may block it; right-click the binary in Finder and choose Open once, or run xattr -d com.apple.quarantine ~/.messages/bin/messages-dev. The npm install does not have this issue.

Authenticate

Two options. Pick the one that fits your context.
MESSAGES_API_KEY always wins over the config file. Create a key in the dashboard under API Keys.

Send your first message

If you have exactly one active line, --from is optional. Otherwise pass --from <handle> to disambiguate. You can also pipe text in over stdin:

Commands

Run messages-dev <command> --help for full flag detail on any of these.

Output and exit codes

By default every command renders human-readable output. Pass --json (or set MESSAGES_OUTPUT=json once for the whole shell) to switch to structured output on stdout. Errors always go to stderr; with --json they take the shape {"error":{"code":"…","message":"…"}}.

Recipes

Pipe stdin into a message

Anything that produces text on stdout can become an iMessage:

Forward live events to a local webhook handler

listen --forward-to turns the CLI into a poor-man’s tunnel for webhook development. It subscribes to your account’s event stream and POSTs each event to your local URL with the same HMAC headers production webhooks use, so you can develop and test webhook handlers without ngrok or a tunnel.
The CLI prints a session HMAC secret on first run; verify deliveries against that, or pin one with MESSAGES_LISTEN_SECRET=…. Filter to specific events or scope to a single line:

Upload an attachment, then send it

Or in one go without jq by upgrading the recipient flow to your code’s needs:
(The non-JSON files upload output prints the bare file_… id, suitable for direct substitution.)

Tapback the latest message in a thread

Troubleshooting

command not found: messages-dev — the install directory is not on your PATH. Add export PATH="$HOME/.messages/bin:$PATH" to your shell rc, or run the binary by full path. macOS blocks the binary on first run — Gatekeeper. See the warning under Install. The npm-installed CLI does not hit this. not_authenticated errors — you signed in on a different machine, or your API key was revoked. MESSAGES_API_KEY takes precedence over ~/.messages/config.json; if you have a stale key exported, the file is ignored. Run messages-dev login or unset MESSAGES_API_KEY. Pin or roll back a version — the install script honors MESSAGES_CLI_VERSION:

See also

TypeScript SDK

The same API as the CLI, in your code.

Webhooks

Long-term event delivery once you outgrow listen --forward-to.