Skip to content

Latest commit

 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@simplepush/cli

Command-line client for Simplepush. Binaries: simplepush and sp (alias).

Install

bun add -g @simplepush/cli
# or
npm install -g @simplepush/cli
# or run without installing
bunx @simplepush/cli events --since 24h

Commands

sp task      Send a task, optionally wait for the first completion.
sp subtask   Append a follow-up to an existing task via its append token.
sp cancel    Withdraw a pending task, subtask, or task group you sent.
sp notify    Send a fire-and-forget notification.
sp collect   Collect replies, inputs, or submissions as bounded NDJSON.
sp download  Download one file a collect line referenced, by its ids.
sp get       Read what came back: task listings, one task with its subtasks, a task group, submissions.
sp events    Stream or replay the raw event feed.
sp auth      Log in to an organization (login / logout / status).
sp org       Administer an organization: members, invites, topics, API key, encryption.

Two credentials, picked automatically: your personal API token (from the app settings, via --api-token or $SP_API_TOKEN) for personal sends and sp events, and an organization session (sp auth login) for org sends, org-wide collects and downloads, and sp org.

Examples

Ask a question from a script, block until it is answered

sp task -t ops --title "Deploy v2.1.0 to prod?" \
  -a "approve=Approve:primary,abort=Abort:destructive" \
  --wait

--wait blocks until the recipient taps a button on their phone and prints the result. This turns any shell script into something that can stop and ask a human.

Collect structured answers from real people

Tasks carry typed inputs: text, single or multi choice, action buttons, sliders, photo, voice recording, file upload, and GPS location.

sp task -t field-crew --title "Morning site check" \
  --photo-input "Photo of the meter" \
  --slider-input "Water temperature;min=0;max=40;step=0.5;unit=C" \
  --choice-input "Which pumps are running?;P1,P2,P3;multi=true" \
  --text-input "Anything unusual?;required=false"

Pipe a send into sp collect and get NDJSON back

--format json prints a machine-readable sent line that sp collect consumes. Every answer then arrives as one JSON line, and a final end line tells you why the stream stopped. Built for scripts and agents.

sp task -b --format json --title "Standup" \
  --text-input "What did you ship today?" \
  | sp collect --inputs > answers.ndjson

Notifications work the same way when they carry an input:

sp notify -t ops --content "Restart the staging cluster?" -c "Approve,Deny" \
  --format json | sp collect

Cancel what you no longer need

sp cancel withdraws a pending send; the id's prefix picks what: tsk_ one task, sub_ one follow-up (the chain stays live), grptsk_ every still-pending member of a group. Recipients see the card flip to canceled, and a running sp collect counts the member as done.

sp cancel tsk_0198…

# tear down the rest of a group after the first useful answer
sp cancel grptsk_0198… --reason answered --note "already handled"
# → {"type":"canceled","groupId":"grptsk_…","canceled":2,"skipped":1}

# replace a follow-up with a corrected one (same chain only)
sp cancel sub_0198… --reason superseded --superseded-by sub_0199…

Already-answered members are skipped, never failed; re-canceling is a no-op. With an API token it cancels a personal send, without one it uses the org session. --note is sealed under the target's own key whenever the CLI holds it: the org vault on org cancels, or the matching -p "pw@topic" (topic send) / bare -p "pw" (send to your own devices) on personal ones; otherwise it ships plaintext with a warning.

Download the files people upload

--save-files downloads every collected file (photos, voice recordings, file uploads, reply and submission files) into a directory as it streams in, decrypted and checksum-verified. Each file object on the NDJSON line gains a path with the saved location.

sp task -b --format json --title "Site check" --photo-input "Photo of the meter" \
  | sp collect --inputs --save-files ./meter-photos

sp download fetches a single file after the fact, using the ids a collect line carried (taskId + the upload's id, or a submission's id + its file's id):

sp download tsk_0198… inp_0198…          # task input upload or rfl_… reply file
sp download sbm_0198… sbf_0198… --out .  # submission file

It searches the last 7 days of your event stream for the file's metadata; pass --since 90d for older files.

Capture submissions from your phone

A submission is content you push from the app with no task attached: a note, a photo, a file, a voice memo, a location. sp collect --submissions streams your inbox as NDJSON, one line per submission, and watches until Ctrl-C:

sp collect --submissions --save-files ./inbox -p "account-password"

Attachments land in ./inbox; the bare -p password is your account default and decrypts encrypted submissions. --since 7d backfills earlier submissions first.

Send to your own devices

Omit the target entirely and the send goes to all of your own devices.

sp task --title "Pick up the package" --content "Locker 14, code 8841"

End-to-end encrypt

password@topic encrypts everything sent to that topic on your machine; the same flag decrypts on receive. The server never sees plaintext.

sp task -t alerts -p "hunter2@alerts" --title "Rotate the door code" \
  --text-input "New code?"

sp events -t alerts --since 24h -p "hunter2@alerts"

Attach files and render Markdown

sp task -t design --markdown -f mock.png \
  --title "Design review" \
  --content "Check the **hero section**, then vote:" \
  -c "Ship it,Iterate"

Files are uploaded (and encrypted when the send is), --link attaches URLs instead.

Append follow-ups to a running task

Every send prints an append token. sp subtask uses it to push another step onto the task the recipient already has, with the full input palette available.

sp subtask --append-token "$TOKEN" \
  --content "One more approval needed" \
  -a "accept=Accept:primary,deny=Deny:destructive"

Collect its answers like any send: pipe the sent line, or collect after the fact by pairing the parent task id with the subtask id in --instance (a subtask's events arrive on the parent task, so the id needs both halves):

sp subtask --append-token "$TOKEN" --format json \
  --text-input "ETA?" | sp collect --inputs

sp collect --instance sub_0198… --since 24h

Watch your account live, or replay history

sp events                                        # live firehose
sp events --since 7d --type submission --format pretty
sp collect --submissions --until count:1         # block until the next inbox submission

Run an organization from the terminal

sp auth login                          # browser or device-code flow
sp org members invite "Alice"          # prints a one-time login code for her app
sp notify -b --title "All hands at 3pm" --content "Room 2"
sp task -m "Alice" --title "Badge photo" --photo-input "A selfie please"
sp org encryption enable               # end-to-end encryption for the whole org

Run sp <command> --help for every flag, or see the full CLI guide.

Building a standalone binary

Bun can compile the CLI into a single-file native binary:

bun run build:binary
./bin/simplepush --help

Query what came back

The read commands mirror the MCP query tools, so an agent can ask questions like "every task that expired unanswered this week, grouped by assignee":

sp get tasks --status expired --since 7d --format json  # one JSON object per line
sp get tasks --status pending --member anna --all       # follow cursors to the end
sp get tsk_…                                            # the chain: root + subtasks, decrypted where keys are held
sp get sub_…                                            # one subtask on its own
sp get grptsk_…                                         # per-recipient status of a group send
sp get submissions --since 24h --member anna
sp events --since 7d --member anna                      # events replay, narrowed client-side

A page that was cut off ends with {"type":"more","cursor":"…"} (json) or an info line (pretty); pass the cursor back with --cursor, or --all to page automatically. --since/--until take ISO-8601 instants or relative windows (7d, 12h). For personal accounts the HTTP query surface (sp get) is a subscription feature — sp events, sp collect and sp download stay free.

About

Command-line client for Simplepush.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages