@pingroom/cli 0.6.2 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +85 -40
  2. package/bin/pingroom.js +487 -225
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,10 +6,10 @@ from CI, scripts, and agents. Delivered as push straight to your phone.
6
6
  One dependency (`qrcode-terminal`, used only to draw the pairing QR). Works
7
7
  anywhere Node ≥ 20 runs.
8
8
 
9
- > **Release status:** npm currently serves 0.6.1. The corrected attachment
10
- > limits are in the tested 0.6.2 release candidate on `main`; the public GitHub
11
- > Action remains pinned to 0.6.1 until 0.6.2 is published and clean-install
12
- > verified.
9
+ > **Release status:** 0.7.2 is prepared for publish — the room grant, the
10
+ > `attachments:write` scope `--attach` always needed, and actionable text on the
11
+ > refusals you can fix. The GitHub Action pins 0.7.2, so publish before relying
12
+ > on it.
13
13
 
14
14
  ## Install and first run
15
15
 
@@ -27,8 +27,10 @@ npx --yes @pingroom/cli
27
27
  ```
28
28
 
29
29
  Either command starts the same connection prompt. QR pairing stores the selected
30
- account, credential, and delivery room in `~/.pingroom`; later commands reuse
30
+ account, credential, and room grant in `~/.pingroom`; later commands reuse
31
31
  them, so a local invocation needs neither `PINGROOM_TOKEN` nor `PINGROOM_ROOM`.
32
+ On the phone you grant one room, several, or every room on the account — the
33
+ first room you pick is the delivery room, where Questions and Handoffs land.
32
34
  The email fallback stores the credential only. Setting
33
35
  `pingroom config set default_room <invite-code>` enables room-addressed commands,
34
36
  but private Agent Inbox and Handoff delivery require a connection approved with
@@ -41,16 +43,17 @@ pingroom ping -m "Deploy succeeded ✅"
41
43
 
42
44
  Commands: `ping` (send), `ask` (ask a human), `watch` (block on an existing
43
45
  question), `list`, `cancel`, `handoff` (hand a decision to a specific human),
44
- `handoffs` (list open or recent Handoffs), `live` (lock-screen progress card),
45
- `hook` (Claude Code), `mcp` (client setup), `activate` (retry the Agent Inbox
46
- test), `config`, and `logout`.
46
+ `handoffs` (list open or recent Handoffs), `listen` (hear pings as they land),
47
+ `live` (lock-screen progress card),
48
+ `hook` (Claude Code), `mcp` (client setup), `activate` (send an optional test
49
+ Question), `config`, and `logout`.
47
50
  Run `pingroom --help` for the full reference.
48
51
 
49
52
  ## Connecting
50
53
 
51
54
  Run `pingroom` (global install) or `npx --yes @pingroom/cli` (no install) with no
52
- arguments. It prints a QR code — scan it with the PingRoom app and pick both the
53
- account and the room the agent delivers to — or take the emailed-code fallback.
55
+ arguments. It prints a QR code — scan it with the PingRoom app, pick the account,
56
+ and grant the rooms this agent may reach — or take the emailed-code fallback.
54
57
 
55
58
  ```
56
59
  $ pingroom
@@ -61,43 +64,55 @@ $ pingroom
61
64
 
62
65
  [QR]
63
66
  Or open: https://pingroom.io/app/agents/pair?token=…
64
- Waiting for approval… ✓ Connected as @agt_ab12cd34ef → #Project X
65
- Sending a test question to PingRoom…
66
- Answer “PingRoom connected. Can you answer this?” on your phone.
67
- Test question answered (Yes). Agent Inbox is ready.
68
- ```
69
-
70
- After QR approval, the CLI saves the active credential first, then sends one
71
- idempotent onboarding Question and observes it through the Handoff wait API.
72
- Short network and server failures are retried, and `Retry-After` is honored for
73
- rate limits within the two-minute overall deadline. An answer alone is not
74
- reported as success: the terminal response must also carry the server's exact
75
- `activation_completed: true` stamp. On supporting server and mobile builds,
76
- that stamp means the native phone returned the opaque proof carried in the push
77
- before the human answer, and this CLI then observed the result. An answered
78
- response whose stamp is false or missing is incomplete and is not retried as if
79
- history could be rewritten. If the Question is still pending when the local
80
- deadline elapses, or activation cannot start, the CLI prints the recovery
81
- command and exits with the connection still saved and usable. A terminal test
82
- without the stamp requires a current PingRoom app and a fresh numbered attempt;
83
- run `pingroom activate` again with the saved connection.
84
-
85
- Resume an open idempotent check with the saved QR credential:
67
+ Waiting for approval… ✓ Connected as @agt_ab12cd34ef → #Project X +2 more
68
+ ```
69
+
70
+ Approving on the phone is the whole ceremony — connecting sends nothing else to
71
+ your phone. The status line reflects the grant: `→ #Project X` for one room,
72
+ `→ #Project X +2 more` for several, `→ all rooms` when you granted every room.
73
+
74
+ ## Proving the round-trip (optional)
86
75
 
87
76
  ```bash
88
77
  pingroom activate
89
78
  ```
90
79
 
91
- An incomplete explicit retry exits `1`; it never deletes or replaces the saved
92
- credential. The command does not fall back to `PINGROOM_TOKEN`, an email-only
93
- credential, or a credential without `pingroom:handoffs:create` and a
94
- QR-selected delivery room. Email-code and other non-interactive credential
95
- flows do not run the phone-response loop automatically.
80
+ `activate` sends one idempotent onboarding Question and observes it through the
81
+ Handoff wait API. Short network and server failures are retried, and
82
+ `Retry-After` is honored for rate limits within the two-minute overall deadline.
83
+ An answer alone is not reported as success: the terminal response must also
84
+ carry the server's exact `activation_completed: true` stamp. On supporting
85
+ server and mobile builds, that stamp means the native phone returned the opaque
86
+ proof carried in the push before the human answer, and this CLI then observed
87
+ the result. An answered response whose stamp is false or missing is incomplete
88
+ and is not retried as if history could be rewritten.
89
+
90
+ An incomplete run exits `1`; it never deletes or replaces the saved credential.
91
+ The command does not fall back to `PINGROOM_TOKEN`, an email-only credential, or
92
+ a credential without `pingroom:handoffs:create` and a delivery room. A grant of
93
+ all rooms pins no delivery room — pick one under Connected Agents in the app
94
+ first.
96
95
 
97
96
  There is deliberately no `login` command: being unconnected is a state the tool
98
97
  resolves, not one you have to discover. Once connected, bare `pingroom` prints
99
98
  that status line followed by the usual help.
100
99
 
100
+ ### What the approval grants
101
+
102
+ Approving on the phone grants two separate things, and both are enforced:
103
+
104
+ - **Permissions** — the scopes this CLI asks for: `rooms:read`,
105
+ `broadcast:send`, `attachments:write`, `notifications:read`, `questions:ask`,
106
+ `handoffs:create`, `live:write`. Nothing widens them later; a command needing
107
+ one you did not approve returns `403 insufficient_scope`.
108
+ - **Rooms** — one room, several, or all of them. A room outside that grant
109
+ returns `403 room_not_granted` on any write, including pings, questions and
110
+ live streams. Widen it under Connected Agents in the app.
111
+
112
+ Both refusals print the fix, not just the code. A credential paired by an older
113
+ CLI carries the scope set that version asked for — reconnect to re-approve if a
114
+ command starts reporting `insufficient_scope`.
115
+
101
116
  The credential lands in `~/.pingroom/credentials.json` (mode `0600`, inside a
102
117
  `0700` directory). `PINGROOM_HOME` moves that directory; `pingroom logout`
103
118
  clears it.
@@ -206,12 +221,41 @@ on the Lock Screen (iOS Live Activity / Dynamic Island, Android live update, and
206
221
  a full inline card in the app). `start` opens it with one alert, `update` moves
207
222
  it **silently**, `end` closes it with one completion alert.
208
223
 
224
+ ## Hearing replies
225
+
226
+ Everything else here talks; `listen` is how an agent hears — replies to its own
227
+ structured pings, a human's ping in a room it belongs to, anything landing while
228
+ it works.
229
+
230
+ ```bash
231
+ pingroom listen # block, printing each ping as it lands
232
+ pingroom listen --once --json # one batch as JSON, then exit
233
+ pingroom listen --from "$LAST_ID" # catch up from a known ping id
234
+ ```
235
+
236
+ ```
237
+ --timeout <sec> Per long-poll hold (0-30, default 25)
238
+ --limit <n> Max pings per batch (1-100, default 50)
239
+ --from <id> Start after this ping id instead of "now"
240
+ --once Print one batch and exit instead of blocking forever
241
+ --json One JSON object per line instead of a readable line
242
+ ```
243
+
244
+ The server holds each request open until something arrives, so this is a
245
+ long-poll rather than a poll loop: an idle hour costs about 144 requests, not
246
+ one per second. With no `--from` it starts from *now* — the first call takes the
247
+ head cursor and returns nothing, so starting up never replays history. Transient
248
+ failures (429, 5xx, network) back off geometrically and keep listening;
249
+ `--once` is the form to use in a script.
250
+
209
251
  ```
210
252
  pingroom live <start|update|end|get> [options]
211
253
 
212
254
  -c, --correlation-id <id> The stream key — reuse it for every ping (required)
213
255
  --template <name> start only: status | steps | progress | metrics |
214
- countdown | question | matchup (fixed at creation)
256
+ countdown | decision | matchup (fixed at creation;
257
+ 'decision' is the app's name for the wire id
258
+ 'question', which is still accepted)
215
259
  --steps <a,b,c> start only: 2-8 comma-separated step labels
216
260
  -m, --message <text> The card's live message line
217
261
  --progress <0..1> Progress bar / Dynamic Island gauge
@@ -219,13 +263,14 @@ pingroom live <start|update|end|get> [options]
219
263
  --metric <label:value> Repeatable, up to 3 (metrics template)
220
264
  --deadline-at <epoch> Countdown target (countdown template)
221
265
  --eta-at <epoch> Live ETA (status/progress templates)
222
- --prompt <text> The ask (question template)
223
- --option <value:label> Repeatable, up to 4 (question template)
266
+ --prompt <text> The ask (decision template)
267
+ --option <value:label> Repeatable, up to 4 (decision template)
224
268
  --left <label:value> Left side (matchup template)
225
269
  --right <label:value> Right side (matchup template)
226
270
  --center <text> Center score/clock, <= 40 (matchup template)
227
271
  --accent-override <#rrggbb> Semantic accent for this frame
228
272
  --failed end only: finish as failed instead of done
273
+ -d, --data <json> Structured data object carried on this frame
229
274
  -t, --title <text> Card title (<= 40 chars)
230
275
  -a, --action <1-4> Quick-action slot supplying the icon and sound
231
276
  --require-ack Add an Acknowledge button