CLI
The nodd command sends notifications and waits for responses. Exit codes make it easy to use from a shell.
Install
brew install blipdrop/tap/nodd
You can also download a binary from Releases.
Log in
nodd login
A QR code appears. Scan it under Settings > Log in to CLI in the app and allow it with Face ID within 10 minutes. The send key is saved in ~/.config/nodd/config.json, or under XDG_CONFIG_HOME if set. --name sets the key name, and the default is the host name.
In CI, use environment variables instead of logging in.
NODD_KEY | Send key. Takes priority over the config file |
|---|---|
NODD_API_URL | API URL. Default https://api.nodd.blipdrop.net |
NODD_PROFILE, --profile | Config profile name, one for each channel if you use several. Default default |
Commands
nodd login | Gets a send key by QR code |
|---|---|
nodd logout | Removes the key from this computer. Revoke it in the app |
nodd whoami | Shows the profile, the last four characters of the key, and the API mode |
nodd send TITLE | Sends a notification and prints its ID |
nodd ask TITLE | Asks for approval or a choice and waits |
nodd wait ID | Waits for the response to a sent message. Takes --json |
nodd status ID | Prints the state as JSON |
nodd cancel ID | Cancels a pending question |
nodd done ID | Reports the result. --status succeeded|failed (default succeeded) and --summary |
nodd resolve ALERT_KEY | Resolves an alert. --note |
nodd heartbeat NAME --every SECONDS | Reports that a job is alive and prints the next due time. --every is 60 to 2,678,400. --grace defaults to 10% of --every |
nodd mcp | Runs an MCP server over stdio. See MCP and hooks |
nodd hook | The Claude Code PreToolUse hook |
Options for send and ask
--body TEXT | Body. - reads standard input |
|---|---|
--level low|normal|high | Priority |
--field LABEL=VALUE | A field, up to 6 times |
--link LABEL=URL | A link, up to 2 times |
--sensitive | Hides the body on the lock screen |
--markdown | Formats the body as Markdown and allows 4,000 characters |
--image FILE | Attaches a JPEG or PNG up to 40 KB. Add a description with --image-alt |
--json | Prints the result as JSON |
nodd send also takes --kind notice|alert and --alert-key.
nodd ask
--option ID=LABEL | An option, 2 to 4 times. Asks for a choice instead of approval |
|---|---|
--expires-in SECONDS | Response deadline. Default 3600 |
--input PROMPT | Shows a text field. Read the answer from stderr or --json. Add --input-required to require it |
--secret | Asks for a password or other secret in a masked field. The value arrives encrypted to a key that exists only for this run, and only the value goes to stdout. It refuses to print to a terminal, so pipe it or use --env |
--env NAME -- COMMAND | Runs COMMAND with the value in an environment variable instead of printing it. Use this with AI agents so they never see the value |
--approvals N | People who must approve, 1 to 3. More than 1 needs Team |
--escalate-after SECONDS | Tells other people after this many seconds without a response. Team only |
--no-wait | Prints the send result without waiting |
Answering --input or --secret needs Nodd 1.1 or later. MCP has no equivalent of --secret. Have agents use --env so the value never reaches the model.
nodd ask "Deploy to production?" --approvals 2 --escalate-after 600 --expires-in 3600 && ./deploy.sh
nodd ask "Where should this go?" --option staging=Staging --option prod=Production
nodd ask "Production DB password" --secret --env PGPASSWORD -- psql -h db.example.com app
Standard output gets approved, rejected, the chosen option ID, or a state such as expired. A rejection reason goes to standard error as Note: reason, so standard output stays safe to parse.
Exit codes
These apply to nodd ask and nodd wait.
0 | Approved, or an option was chosen |
|---|---|
10 | Rejected |
11 | Ended without a response (expired, cancelled, or failed) |
12 | Timed out while waiting |
1 | Any other failure |
It waits until 15 minutes after the response deadline. Network failures do not end the wait, and only a recorded response counts as a result.
Monitoring a scheduled job
0 3 * * * /usr/local/bin/backup.sh && nodd heartbeat nightly.backup --every 86400
If the next report does not arrive within --every plus --grace seconds, the channel is told.