A turn that has run 15 minutes while producing under 50 tokens a minute is a stalled API stream: flagged on the page with an Esc button, and notified once. The container's memory use is shown in the header and notified near the limit. Claude-Session: https://claude.ai/code/session_01QhLkBGEip8wQdaZ54z4AqJ
4.0 KiB
Rig Pocket
A phone-friendly status page and push notifier for OpenRig teams. The OpenRig TUI is great on a laptop and hard to use on a phone; Rig Pocket gives the same overview as an installable web app (PWA):
- every rig and seat, with working / idle / waiting for an answer
- open and recently finished queue items
- the latest commits on every branch of the repositories your teams work in
- questions from the agents, answered right on the page:
- menus and permission prompts are read off the seat's screen and shown as labelled buttons (plus Esc)
- an agent that stopped with a question gets a reply box
- queue items blocked on a human seat are decisions, recorded with
rig queue resolveso the owner wakes up
- a seat whose turn has run long without producing tokens is flagged as hung (a stalled API stream), with an Esc button
- the container's memory use (cgroup v2) in the header, with a warning near the limit
- tap a seat to see its screen (refreshes every 5 s) or type a message to it
- optional push notifications through ntfy: new commits, a seat waiting for an answer (only if it is still waiting on the next poll), a new request to the operator, a lead's task finished, a hung seat, memory running out
It reads everything through the documented rig CLI (--json), so it does not depend on daemon internals.
Python 3 standard library only, no build step.
Run
Run it as the same user as the OpenRig daemon, next to it:
RIG_POCKET_REPOS="~/work/*" python3 server.py # listens on 127.0.0.1:7440
python3 -m unittest # tests
rig-pocket.service is an example systemd unit.
| Variable | Default | |
|---|---|---|
RIG_BIN |
rig |
path to the rig CLI |
RIG_POCKET_BIND / RIG_POCKET_PORT |
127.0.0.1 / 7440 |
listen address |
RIG_POCKET_POLL |
30 |
seconds between snapshots |
RIG_POCKET_REPOS |
(none) | space separated globs of git work trees to show commits from |
RIG_POCKET_ORIGIN |
(none) | if set, POSTs must come from this origin, e.g. https://rig.example.com |
RIG_POCKET_URL |
(none) | where tapping a notification opens |
RIG_POCKET_THEME_CSS / _JS |
weirsoe-theme on assets.weircon.dk | stylesheet and script of the design system |
NTFY_URL / NTFY_TOPIC / NTFY_TOKEN |
(none) | ntfy server, topic and access token; unset = no push |
RIG_POCKET_DONE_DEST |
^orch-lead@ |
regex: notify when a task to such a seat closes |
RIG_POCKET_HUMAN_DEST |
^operator-agent@kernel$ |
regex: notify when such a seat gets a new task |
RIG_POCKET_HUMAN_SEATS |
^operator-human@ |
regex: human seats (not scanned for prompts; items blocked on them are decisions) |
RIG_POCKET_STALL_MIN / _STALL_RATE |
15 / 50 |
a turn this many minutes long, under this many tokens per minute, is hung |
RIG_POCKET_MEM_WARN |
0.9 |
notify when memory use passes this fraction of the limit |
RIG_POCKET_HUMAN_SEAT |
operator-human@kernel |
the seat a decision is recorded as |
Security
Rig Pocket can type into your agents, and OpenRig agents usually run without permission prompts.
Never expose it without authentication. Put it behind a reverse proxy with single sign-on (forward auth)
and, ideally, an IP allow list, and keep it bound to localhost. Write requests need a custom header
(which forces a CORS preflight) and, with RIG_POCKET_ORIGIN, a matching Origin. Seat names are checked
against the current snapshot before anything is passed to rig, and arguments are never run through a shell.
The page is served with a strict Content Security Policy: scripts and styles only from itself and the theme host,
no inline scripts, connect-src 'self'.
Look
The page uses only classes from the shared weirsoe-theme design system
(.wt-card, .wt-tag--warn, .wt-pre, .wt-row, …) and has no stylesheet of its own. Point the two theme variables
at your own copy to re-skin it.
License
MIT