Tools

CLI

Send and manage messages from your terminal or any shell script, without writing HTTP requests. This page covers what people do most; every command explains the rest with --help.

Set it up

The CLI isn't published as a package yet, so build it from the Ripple repository. It needs Node 22 or newer. From the repository's folder:

Terminal
pnpm --filter @ripple/cli build
alias ripple="node $PWD/apps/cli/dist/index.js"

The alias lets you type ripple, as the examples here do. The CLI reads your key from RIPPLE_KEY, like the curl examples:

Terminal
export RIPPLE_KEY=paste-your-key-here

A send key is enough to send. Reading messages takes an API token, and changing anything takes one with full access.

Tip

Run ripple alone for an overview, and add --help to any command, as in ripple messages search --help, for every option with examples to copy. Mistype a command and the CLI suggests the closest one.

Send a message

Give it a title, then the message in quotes. Without --title, the message's first line is the title:

Terminal
ripple send --title "Hello from Ripple" "The first of many."

The CLI says where it went, such as Sent to Inbox. Add what the message needs:

Terminal
# An alert level: quiet, standard or important
ripple send --title "Disk almost full" --alert important "Only 2 GB left on /data"

# A link to open from the message
ripple send --link https://ci.example.com/builds/42 --link-title "Open build" "Build 42 failed"

# Running updates, grouped into one thread
ripple send --thread "Production deploy" "Tests passed"

Or pipe text in. This sends the end of a test run:

Terminal
make test 2>&1 | tail -20 | ripple send --title "Test results"

A send key always sends to its own source. With an API token, messages go to Inbox unless you add --source with a source ID. Send messages covers titles, alerts, sounds and threads, and ripple send --help lists every option.

Read and organize messages

These commands need an API token. Start with what's new:

Terminal
ripple messages --unread

Unread messages are marked, and times are in your own time zone. To go further:

Terminal
# Open one message in full
ripple messages get msg_abc123

# Search everything except Trash
ripple messages search "release notes"

# Read a whole thread
ripple threads get thr_abc123

Organize messages by ID:

Terminal
ripple messages archive msg_abc123 msg_def456
ripple messages read msg_abc123
ripple messages trash msg_abc123

To deal with one later, snooze it. The CLI reads times the way you'd say them, in your computer's time zone:

Terminal
ripple messages snooze msg_abc123 tomorrow 9am
ripple messages unsnooze msg_abc123

2h and friday at 5pm work too. To move a message outside a thread to another source, use ripple messages move with --source.

Messages explains how lists, threads and snoozes behave, and ripple messages --help lists every command.

Manage sources

Give each script its own source, with its own key:

Terminal
ripple sources create "GitHub Alerts"

The CLI creates the source and prints its send key, ready for your script. To list your sources and their IDs, or get a source's key again:

Terminal
ripple sources
ripple sources key src_abc123

Change a source's name or defaults with update, and quiet a noisy one with mute:

Terminal
ripple sources update src_abc123 --name "Builds" --default-alert quiet
ripple sources mute src_abc123

ripple sources --help covers the rest, including disable, resetting a key and moving a source to Trash.

Warning

ripple sources key src_abc123 --reset --yes replaces a source's send key, and the old key stops working at once. Every script that used it needs the new one.

Restore from Trash

Anything you delete stays in Trash for 30 days:

Terminal
ripple trash

Each item ends with its type and ID, such as message msg_abc123. Put that after restore to bring it back:

Terminal
ripple trash restore message msg_abc123

Deleting from Trash is permanent, so ripple trash delete runs only with --yes. ripple trash --help shows the rest.

Use it in scripts

Get JSON instead of text

Add --json to any command for the API's response exactly as Ripple sent it, one line per response. It pairs well with jq:

Terminal
ripple messages --unread --json | jq -r '.items[].preview'

Errors go to standard error, as JSON with --json, in Ripple's usual shape with a code and a message.

React to new messages

ripple messages watch shows each new message the moment it arrives, until you press Control-C. Add --source for one source's messages. With --json, each message is one line of JSON, so a script can act on it right away:

Terminal
ripple messages watch --json | jq --unbuffered -r 'select(.alert == "important") | .title'

If the connection drops, it reconnects and shows what arrived meanwhile, waiting longer between tries, up to 30 seconds, while Ripple can't be reached. It stops with an error only when Ripple can't be reached at the start or turns it down, as when the token stops working. Watch for new messages describes each message's JSON.

Act on many messages at once

Lists show one page at a time. Add --all to follow every page into one list, or with --json, one line per page. To act on more messages than fit on a command line, give - in place of IDs and pipe them in:

Terminal
ripple messages --read --all --json | jq -r '.items[].messageId' | ripple messages archive -

The CLI sends piped IDs 100 at a time and prints one summary at the end.

Check the exit status

Each kind of failure has its own exit status, so a script can decide what to do next:

StatusMeaning
0It worked
1Ripple turned the request down, or something unexpected went wrong
2The command was mistyped, so nothing was sent
3Not found
4The key is missing, wrong or not allowed to do this
5Rate limited or busy; try again later
6No answer, so the outcome is unknown

A command that stops partway, such as during a batch of piped IDs, exits with the status of the error that stopped it, then says what it didn't get to.

Retry safely

When Ripple can't take a message right away, ripple send keeps trying for up to 5 minutes. That covers no connection, no answer in time, and Ripple being busy or limiting sends (status 429 or 5xx). It waits longer between tries, and never less than Ripple asks; if Ripple asks for more than the 5 minutes, it stops at once. Each wait shows on standard error, except with --json. Every try carries the same idempotency key, so the message arrives only once however many tries it takes.

If it still can't get through, or can't tell whether it did, the CLI exits with the last error's status and prints the key, which --json adds to the error as idempotencyKey. Send the same message with that key, and it arrives only once. So that a script that runs again, such as a rerun CI job, also sends once, give each message your own key from the start:

Terminal
ripple send --idempotency-key deploy-42 "Deploy 42 finished"

Apart from messages watch reconnecting, other commands never retry on their own. After status 6, the request may or may not have gone through, so check before trying again.

Note

ripple send reads piped text only from a shell pipe or a file, never from an open terminal, so it never sits waiting for input. When another program runs ripple send, pass the message as an argument or use --json-file -.

Point it somewhere else

Commands go to https://api.ripplepush.com. To use another address, set RIPPLE_BASE_URL, or save it as baseUrl in ~/.config/ripple/config.json. For one command, use --base-url. When more than one is set, --base-url wins, then the environment variable, then the file.

To keep your key safe, the CLI sends it only over https://, apart from your own computer, and won't use a config file other users could change.

Color shows only in a terminal; set NO_COLOR to turn it off. Requests give up after 30 seconds unless you set --timeout, in milliseconds.