Skip to content

Machines on the board

Andrea de Ruvo edited this page Aug 18, 2026 · 2 revisions

Machines on the board

What a tile says

Everything on a tile is one glance's worth, ordered by how likely it is to be the reason you looked:

Which one wants you The accent bar down the left edge, and that machine sorts to the top. It is the only thing that gets that bar — a machine's own colour never touches it.
Sessions One chip each, with the window count. Green means it is asking you something; amber means it finished. Click one and you are in that terminal.
Load, and the fullest disk Amber over 74%, red over 90%. Only the disk in the most trouble: a board wants to know there is a problem, not to inventory the filesystems.
Two uptimes The machine's, and how long this Argus has been running. Three Argus instances on one box report the same machine uptime; the second number is the one that tells them apart.
Its address, and a button to copy it Because the useful thing is often not "open it here" but the address itself, to paste into a terminal or send to somebody.
A line of your own A note you write, kept per machine: what the box is for, what it was doing, why it looks like that. Everything else on the tile, the machine said. This is the part only you know.

The footer counts what is actually there — 4 argus on 2 machines, when three of them are on one box.

The same board in the light theme The same board on a phone

Who is in a session

A session chip carries the agent's name when the session says so — argus [claude] — with the model in its tooltip. Both come from what the agent declared on its own pane (@argus_agent, @argus_model, written by the status line hook Argus can install for you), and neither is ever inferred: a board has no process tree to read and no business running ps on another machine, so a tile that guessed would be a tile that is occasionally wrong about a box you cannot see. A session that says nothing shows nothing.

It costs one list-panes per machine per sweep, so forty sessions cost what two do. The model is in the tooltip rather than on the chip because a tile with six sessions would otherwise carry six model names, and the question a board answers is which machine needs me.

How a machine gets onto the board

Two directions, and the network decides which one you can have.

The board asks (pull)

Write the machine down and the board polls it. This is the better arrangement wherever it works: a request that fails is the signal that a machine is down, and there is one file that says what is being watched.

# ~/.config/panoptes/config.yaml
listen: 0.0.0.0:8070
token: <the board's own token, generated on first run>

machines:
  - name: hetzner
    url: http://hetzner.internal:8090
    token: <a watcher token from that machine's Argus>
    # Where a *browser* should go, when that is not where this board asks.
    reach: http://hetzner.example.com:8090
    colour: 4                     # optional; otherwise from the name
    note: the one paying rent     # optional; a reader can write over it

On the Argus side, a watcher token is a key that opens GET /api/overview and nothing else — no shell, no files, no writes, no proxy:

# ~/.config/argus/config.yaml, on each machine
watchers:
  - name: panoptes
    token: <16+ characters, not the same as the main token>

The machine calls in (push)

Some networks only go one way. Measured on the pair this was written for: two boxes on the same wire, same /25, each with the other's MAC in its ARP table, and one of them refusing everything inbound. A board on the reachable side will never poll the other, and no amount of configuration on the board changes that.

So the machine opens the connection instead, in the direction that already works:

# panoptes config: allow it
registration_token: <16+ characters, different from the board's token>
forget_after: 45          # seconds of silence before it stops being believed
# argus config, on the machine that cannot be reached
report_to:
  url: http://board.internal:8070
  token: <the registration token>
  name: gpu2                        # what you want it called on the board
  reach: http://gpu2.internal:8090  # where a browser should go
  every: 10

What it sends is what GET /api/overview returns and nothing else: hostname, uptime, load, memory, the fullest disk, and the session names with which of them is ringing. No file, no path, no token, no command. Off unless configured.

This is not a workaround anybody invented here — it is what Prometheus does in agent mode, and what every dial-out agent does: Tailscale, Cloudflare Tunnel, Teleport, the kubelet registering with its API server. Local pull, remote push.

Three rules keep it honest:

  • Announcing and looking are different keys. The registration token cannot read the board; the board's token cannot invent machines.
  • The list you wrote by hand wins. A machine announcing a name you have configured is refused, so nothing holding the registration key can quietly replace a real machine with one of its own.
  • Silence is the only signal there is. No request fails when nobody is asking, so a machine that stops calling in goes cold after forget_after rather than staying green for ever.

Clone this wiki locally