One daemon already saw every session; the dashboard only ever showed one of them well. Under four parallel agents it failed in specific ways, each fixed here: - Sessions were identified by workspace basename, so two agents in one repo were indistinguishable. The daemon now hands out a small ordinal badge in arrival order and the web UI colours each agent by it — rows, timeline lines, and approval cards, which previously asked you to approve `rm -rf` "in remote-grok" without saying which one. - `currentTool` held a single call, so parallel tools overwrote each other. It is now a list; durations are matched FIFO per tool name, since hook payloads carry no call id. - One 400-event ring, evicted oldest-first, let a chatty agent blank everyone else's history. Eviction now takes from whichever session holds the most of the ring. - Sessions sorted by recency jumped under a moving thumb. They are ordered waiting -> error -> working -> idle -> ended, ties on badge, so an agent keeps its slot. - Events carry no workspace root, so a restart came back with a full timeline and an empty roster. The session map is persisted to sessions.json (debounced, flushed on shutdown, 12h cutoff on load). In-flight tools are dropped on the way out: they belonged to a process that no longer exists. - Snapshot pushes now back off to 1s once a snapshot exceeds 24KB, since full-snapshot SSE cost scales with agent count. - Pending approvals are ordered by which expires first, not by arrival. `glance status` and /local/status report the roster by state. e2e suite: 220 passed, 0 failed.
113 lines
5.1 KiB
Markdown
113 lines
5.1 KiB
Markdown
---
|
|
name: glance
|
|
description: Set up, inspect, or control grok-glance — the passkey-guarded phone dashboard for this Grok Build session. Use when the user asks to watch one or several sessions from their phone, enrol a device, expose the dashboard over Tailscale, or turn remote approve/deny on or off.
|
|
---
|
|
|
|
# grok-glance
|
|
|
|
A local daemon plus web dashboard that shows what Grok Build is doing, readable from a phone
|
|
behind a WebAuthn passkey. It can also pause risky tool calls until someone taps approve.
|
|
|
|
One daemon covers every session on the machine, so several agents running at once all appear on the
|
|
same dashboard — no per-session setup.
|
|
|
|
The daemon is started automatically by the `SessionStart` hook. Everything below is done through
|
|
the `glance` CLI at `$GROK_PLUGIN_ROOT/bin/glance`.
|
|
|
|
## First check whether it is even built
|
|
|
|
The plugin ships as TypeScript and must be built once:
|
|
|
|
```sh
|
|
cd "$GROK_PLUGIN_ROOT" && npm install && npm run build
|
|
```
|
|
|
|
`glance status` prints a "not built" error with this same instruction if it is missing. Do not
|
|
attempt to skip the build — the daemon entry point is `dist/server/index.js`.
|
|
|
|
## The commands
|
|
|
|
```sh
|
|
glance status # is it running, which origin, how many devices
|
|
glance up # start the daemon in the background
|
|
glance stop # stop it
|
|
glance logs # last 60 lines of the daemon log
|
|
glance enroll # mint a one-time code + URL for a new phone
|
|
glance set-origin <https-url> # set the public origin and WebAuthn RP ID
|
|
glance devices # list enrolled devices
|
|
glance revoke <id-prefix> # revoke one
|
|
glance approval <off|risky|all> # remote approve/deny policy
|
|
glance sync-hooks # regenerate hooks/hooks.json from hooks/hooks.template.json
|
|
```
|
|
|
|
## Watching several agents
|
|
|
|
Nothing to configure — every session that runs the hooks shows up. `glance status` reports the
|
|
roster and what each agent is doing:
|
|
|
|
```
|
|
sessions : 4 (1 waiting on you, 1 error, 2 working)
|
|
```
|
|
|
|
Points worth passing on to the user:
|
|
|
|
- Agents are identified by a coloured badge (`●1`, `●2`) as well as the workspace name, because two
|
|
agents in the same repo carry the same label. The badge is stable across daemon restarts.
|
|
- The list is ordered by who needs attention (waiting → error → working → idle → ended) and never
|
|
re-sorts underneath a tap.
|
|
- Approval cards say which agent is asking; with `approval risky` on and several agents, expect
|
|
several cards.
|
|
- One noisy agent will not push the others out of the timeline — the event ring is trimmed from
|
|
whichever session is using the most of it.
|
|
|
|
## Getting it onto a phone
|
|
|
|
The dashboard listens on `127.0.0.1` only. Passkeys need a real hostname with valid TLS — a bare
|
|
IP can never be a WebAuthn RP ID — so the supported path is Tailscale Serve:
|
|
|
|
```sh
|
|
tailscale serve --bg 127.0.0.1:8791
|
|
tailscale serve status # read the https://<box>.<tailnet>.ts.net URL
|
|
glance set-origin https://<box>.<tailnet>.ts.net
|
|
glance enroll
|
|
```
|
|
|
|
Then open the printed URL on the phone, type the code, and create the passkey. The phone must be
|
|
on the same tailnet.
|
|
|
|
Changing the origin changes the RP ID, which invalidates existing passkeys. Say so before running
|
|
`set-origin` on a working setup.
|
|
|
|
## Remote approve/deny
|
|
|
|
`glance approval risky` makes `Bash`, `Write`, `Edit`, `MultiEdit` and `NotebookEdit` calls pause
|
|
and wait for a tap on the phone. Defaults that matter:
|
|
|
|
- Nothing waits unless a phone is actually watching the dashboard (`requireWatcher`).
|
|
- If nobody answers within 90s the call is **allowed**, not denied. Flip that on the phone's
|
|
settings panel if you want the opposite.
|
|
- Every failure path is fail-open: daemon down, timeout, bad JSON, a rejected hook secret — the tool
|
|
call proceeds. This is a convenience gate, not a security boundary.
|
|
|
|
`glance approval off` (the default) means Grok Build never blocks on the phone.
|
|
|
|
## When something does not work
|
|
|
|
- **"not running"** → `glance up`, then `glance logs`.
|
|
- **Passkey prompt fails with a security error** → the phone is on a hostname the RP ID does not
|
|
cover. Compare `glance status`'s `rp id` with the hostname in the phone's address bar.
|
|
- **Dashboard loads but shows nothing** → hooks are not firing. `glance status` warns if the hook
|
|
secret in `$GLANCE_HOME/hook.secret` no longer matches the one the daemon loaded (events are being
|
|
dropped with a 403); `glance stop && glance up` fixes that. Otherwise check that
|
|
`hooks/hooks.json` exists and is registered — it is generated, so `glance sync-hooks` rebuilds it
|
|
from the template.
|
|
- **Page says "run npm install && npm run build"** → the web bundle is missing; build it.
|
|
- **Only one agent shows up** → the others were started before the plugin was installed, or in an
|
|
environment where the hooks are not registered. A session appears on its next hook event; nothing
|
|
can be back-filled for one that already ran.
|
|
|
|
## What it deliberately does not do
|
|
|
|
Read-only plus approve/deny. It cannot send prompts, edit files, run tools, or resume a session.
|
|
Do not tell the user otherwise.
|