@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.
- package/README.md +85 -40
- package/bin/pingroom.js +487 -225
- 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:**
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
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
|
|
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), `
|
|
45
|
-
`
|
|
46
|
-
|
|
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
|
|
53
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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 |
|
|
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 (
|
|
223
|
-
--option <value:label> Repeatable, up to 4 (
|
|
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
|