Grok Build loads plugins out of ~/.grok/plugins/ and clones marketplace sources straight from git; it never runs npm install or a build for you. So a plugin that ships TypeScript is a plugin you have to build by hand before it does anything, and the SessionStart hook's first act is to print "not built yet". dist/ is now committed, and the tree is arranged so that a bare clone can run: - The daemon is bundled to a single ESM file with rolldown, platform node. Its one runtime dependency (@simplewebauthn/server, plus the asn1/cbor tree under it) is inlined; the only imports left in the output are node: builtins. Not minified — a committed blob nobody can read is worse than no committed blob. - tsc no longer emits for the server, it only typechecks (noEmit). rolldown emits. - dist/web was already a self-contained static bundle. - The hook scripts under bin/ were stdlib-only from the start. .grok-plugin/marketplace.json makes the repo its own one-entry catalog with a local source of "./", so `grok plugin marketplace add <git-url>` followed by `grok plugin install grok-glance` works without pinning a SHA of itself. `npm run check:dist` rebuilds and fails if the committed output is stale — the one real hazard of checking in build output. Also drops the daemon's "non-default port, run `glance sync-hooks`" startup note, which the previous commit should have taken with the rest of that scheme; the hook scripts read config.json themselves, so a non-default port needs nothing. The e2e suite now takes GLANCE_ROOT and was run twice: once against the repo, once against a copy containing only tracked files plus dist/ and no node_modules — which is what actually demonstrates the claim, passkey registration and assertion included. 233 checks, both runs green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
108 lines
5.0 KiB
Markdown
108 lines
5.0 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`.
|
|
|
|
## No build step
|
|
|
|
The plugin ships prebuilt: `dist/` is committed, and the daemon is a single dependency-free
|
|
bundle. A clone is ready to run. Only reach for `npm install && npm run build` in
|
|
`$GROK_PLUGIN_ROOT` if `glance status` actually says it is not built, which means `dist/` was
|
|
deleted from the checkout.
|
|
|
|
## 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
|
|
```
|
|
|
|
## 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 that the plugin is registered with Grok Build.
|
|
- **Page says "run npm install && npm run build"** → `dist/web` is missing from the checkout,
|
|
which should not happen in a clone. Re-clone, or 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.
|