Command reference
Binary: pidge (npm: pidge-cli — run via
npx pidge-cli …). Node ≥ 18 (WebSocket realtime needs ≥ 22). pidge <command> --help prints
detailed usage.
Commands
Section titled “Commands”| Command | What it does |
|---|---|
message / important / urgent / event / live |
The 5 typed sends. Fire-and-forget by default; add --actions/--wait to ask for a reply. important is the recommended default. Aliases: fyi, report, alert. |
ask |
important --wait: send and block; prints the chosen action JSON. Requires a way to answer. |
approval |
Go/no-go recipe: important + Approve (Face ID)/Reject + --wait. Answer comes back as grant or deny. |
approve "<question>" |
Deny-default permission gate answered by exit code — 0 only on explicit allow. See Approval gates. |
hello |
First contact on a fresh channel: a live-narrated handshake the human confirms. |
notify |
Deprecated — untyped send (server picks the channel default). Prefer a typed send. |
wait <cid> |
Block on an already-sent notification until answered. |
cancel <cid> |
Cancel a still-scheduled notification (idempotent; 409 once delivered). |
inbox |
What you sent: list, --pending, or --summary (counts + answer latency). |
catchup |
Read-only conversation peek, newest first — never consumes. --limit / --before / --digest. |
listen |
Block until the human messages you; print JSON; exit. --all includes notification answers; --follow keeps the session open; --ndjson one object per line; --exec '<handler>' lets the handler’s exit code decide the ack. Consumes, and holds the channel’s consumer lock while it runs — a second listen or a bridge is refused (exit 2). |
online |
Alias for listen --all, one word. The stay-online command (0.54): pidge online --follow --ndjson --timeout 0 under a session-length watch your harness owns (Claude Code’s Monitor, persistent:true) — one message per line, no deadline; the human sees you offline when the session ends. No such stream? One foreground round per turn, run again when it returns (--follow --timeout 0 refuses there). |
bridge --exec '<handler>' |
The 24/7 supervisor — a stand-in: another agent answering in the human’s place while nobody is there. Opt-in. Long-polls, runs the handler once per batch (JSON on stdin), acks the batch’s exact ids on exit 0; yields the channel to a live listen/watch. |
bridge install [--handler claude|codex|gemini | --exec '<handler>'] [--enable] |
Writes the launchd / systemd --user service that runs the bridge from this project, generates the handler + an editable prompt (key never embedded); --enable starts it and proves it with a selftest — exit 0 only on PASS. |
bridge status · bridge uninstall |
The measured ONLINE/OFFLINE verdict (service · lock · server consumers) · stop and remove the service. |
presence · hook install / hook uninstall |
presence prints one line — OFFLINE (start the watch) or listening (read with catchup, never listen) — for Claude Code’s SessionStart hook, which setup installs under Claude Code; hook install/uninstall manage it by hand. |
ack --up-to <id> |
Mark messages processed after handling. --summary "<note>" attributes the work; --renew heartbeats the lease. |
contract set <k>=<v> / contract show |
Declare how you operate (advisory, never policy). |
selftest [--window N] |
Round-trip proof the listener works (PASS 0 / FAIL 2 with the likely cause). --window up to 600 s for a consumer that runs a model per batch. |
setup --claim <code> |
Exchange the single-use claim code for the key, store it (mode 600), claim ownership, run doctor. Run it inside your project: the key is scoped per git project (≥ 0.43). --global uses the shared machine file (daemons/cron); --print prints export lines instead (your terminal only). Under Claude Code it also installs a SessionStart hook running pidge presence. |
terminal <sub> |
Agent Sessions: mirror a coding-agent session (tmux pane) to the human’s phone, E2E-sealed, typed replies back. Preview — enabled per account by the server; not generally available at launch. |
update |
Update this CLI to the latest published pidge-cli (npm/pnpm/yarn/bun auto-detected). |
doctor |
Validate everything without exposing secrets: env source, server, key, device reach, ownership, realtime probe, live consumers. |
whoami |
Which channel this key speaks for (JSON). |
skill install [--target claude|agents|gemini] |
Write the Pidge skill for an AI agent (.claude/skills/pidge/SKILL.md, AGENTS.md or GEMINI.md). Existing differing files are backed up first. |
--version |
Print the CLI version. |
Send options
Section titled “Send options”--title TEXT (required) the headline--body TEXT the message shown on the banner--body-markdown MD rich body for the tap-through detail screen (GFM: tables)--body-markdown-file F read the markdown body from a file ("-" = stdin) — no shell-quoting pain--subtitle TEXT--profile ID low-level alias of the TYPE — prefer the typed subcommands--event-at ISO8601 WHEN the thing happens (required by event)--lead-minutes N notify / start the countdown N min before event_at (5–240)--urgency LEVEL normal | persistent | alarm (low-level — prefer the type)--image PATH_OR_URL image on the banner + feed; a local path is uploaded for you--file PATH a real artifact (xlsx, pdf, csv…) — Quick Look + save to Files (≤25 MB)--url URL deep link the app opens on tap (PR, dashboard, log)--copy TEXT tap-to-copy value on the detail screen (code, token)--note TEXT WHY this runtime armed the send (clear metadata, visible to siblings)--actions LIST|JSON catalog ids (yes,no,approve,reject,accept,decline,later,done, snooze,reschedule,reply,mute) OR a JSON array of custom actions--custom-action SPEC "id:label[:destructive][:confirm][:biometric][:terminal]" (repeatable)--gated add a Face-ID confirm on the consequential action (money/deletion)--wait block until answered, print chosen_action JSON (ask/approval imply it)--deliver-at ISO8601 schedule for later (server-owned)--reply-to URL also POST the answer to your webhook (HMAC-signed, public HTTPS only)--correlation-id ID idempotency + routing key (auto-generated if omitted)--thread ID conversation handle: sends sharing it group as ONE strand on the phone--after CID decision queue: held until that notification is answered--collapse-key KEY replace/update a prior notification--param KEY=VALUE pass ANY raw /notify field (repeatable) — future server fields work day-one without a CLI update--timeout SECONDS how long --wait blocks (ask/approval ≈ 3600 · wait: 300)--interval SECONDS fallback poll cadence (default 30) — normally unused (WS/long-poll)--realtime force the WebSocket · --no-realtime = polling only--quiet-nag silence the once-a-day manifest-version nudge (PIDGE_QUIET_NAG=1)pidge live has its own field flags (--status, --step 3/5, --progress, --ends-at,
--end --outcome "…", --dedicated) — see Live Activities and
pidge live --help.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 |
success / answered |
1 |
usage error |
2 |
error (network, server, broken setup) |
3 |
--wait timed out — no answer yet, not a failure |
4 |
timed out with zero healthy round-trips — the channel looks broken |
approve is different by design: 0 only on explicit allow; deny/timeout/no-answer/HTTP
failure → 1; raw network error (the send never reached the server) → 2. Non-zero always
means “not approved.”
stdout / stderr contract
Section titled “stdout / stderr contract”- stdout is always machine-readable: the raw
201JSON (fire-and-forget) or thechosen_actionJSON (--wait/ask/approval/wait). - Everything human goes to stderr: warnings,
correlation_id=<cid>(the FIRST stderr line ofask), snooze notices, armed-escalation and policy-degrade narration.
Environment
Section titled “Environment”| Variable | Meaning |
|---|---|
PIDGE_URL |
server base URL (https://api.pidge.sh) |
PIDGE_TOKEN |
the channel’s bearer key (hld_…) |
PIDGE_SECRET |
the channel’s E2E key, when the human enabled sealing — see E2E |
PIDGE_AGENT / PIDGE_LABEL |
per-agent identity: config namespace + display label |
PIDGE_E2E_MEDIA |
on/off — per-machine override for sealed attachments |
PIDGE_QUIET_NAG |
1 silences the manifest-version nudge |
Legacy HERALD_URL/HERALD_TOKEN still work. With no env vars set, the CLI reads a
KEY=VALUE config file, so the key never has to appear in an agent’s chat — resolution order:
explicit env vars win; then ~/.config/pidge/agents/<PIDGE_AGENT>/env when PIDGE_AGENT is
set; then the project scope ~/.config/pidge/projects/<hash>/env when setup ran inside a git
project (≥ 0.43); else the shared ~/.config/pidge/env. pidge doctor prints which source is
in use.
The manifest
Section titled “The manifest”GET $PIDGE_URL/api/v1/manifest (Bearer auth) is the full machine-readable spec. Any new server
field is usable immediately via --param key=value — the CLI is a thin pipe over the manifest.
