skip to content
agentmash get started
docsthe live view

what you see

the live view

Open the dashboard link and the first thing on screen is the live view: the directories people are working in, laid out as places, and every agent as a named cursor standing on the file it is changing — the way a design tool shows collaborators, for a repository. A cursor glides when its agent moves to another file, pulses while it is typing (an edit in the last few seconds), and carries a one-line bubble saying what the edit did. Two cursors on one file is a collision you can see forming. A ⚑ on a file is a claim; a ✓ is a reconciled one.

The column on the right is who is here now — working, typing, thinking (a prompt arrived after the last edit), idle — with their task and the file they are on. The peek under it follows whatever just happened, or whichever file or cursor you pick, by click or by key.

A crew agent is drawn as itself. When the edit was made by one of the crew, a subagent Claude Code ran from the crew's plugin or from a team agentmash team committed, the cursor becomes that agent's mascot and the tag reads alice lv3 · pipe, the level staying with the person; the rail shows its head. It keeps the person's colour, tag and glow: the crew robot may be the very robot another person in the room is drawn as, and those three are what tell the two apart. The person's own mascot comes back with the next edit the main agent makes, or as soon as they send a new prompt, since a prompt always goes to the main agent. Two crew agents editing in parallel in one session share its one cursor: the newest edit wins. The hooks send the agent's catalog name (agent_type: "pipe-backend") and nothing more; Claude Code's own agents and any agent you gave a name of your own are sent as null (see Threat model). It is sent by the Claude Code hooks from the release after 0.4.0, and by repos installed through the web installer after this deploy.

Presence is the default; code is opt-in. Out of the box the live view shows who is where and what changed in a sentence (+12/-3 lines, touching User) — the same summary the hooks already send. Nobody's code leaves their machine. A room that wants more runs:

npx agentmash diffs on

From the next edit on, each agent's hooks also send the text the edit replaced and the text it wrote (clipped to 4 000 characters a side), and the live view shows it beside the file and the first line of it in the cursor's bubble. Three things are true of streamed diffs:

  • They are never written to disk on the server. They ride beside the event on the WebSocket and sit in a small in-memory ring so a dashboard that opens late sees the last few; a server restart, agentmash diffs off or agentmash purge events forgets them.
  • The room's switch is enforced by the server, not trusted from the hook. A diff sent to a room that has not opted in is dropped.
  • Every developer keeps a veto. AGENTMASH_DIFFS=0 (or "stream_diffs": false in the committed config) keeps that developer's text at home whatever the room says; their presence and summaries still show.

The other pages are the same room from other angles: people is the same hour person by person; changes is the code; collisions is who stood on whom, now and by place; history looks back.

Presence: who is actually here

The board's whole claim is that it shows who is working right now, so it has to be able to say when someone isn't. Every developer carries one of four states:

StateWhat it meansWhat it's based on
● workingTheir agent edited something in the last couple of minutes.An event just arrived.
◐ idleTheir session is still open, but nothing has happened for a while. Probably reading, thinking, or in a meeting.Silence, inside the idle window.
◌ silent — never said it finishedNothing for longer than the idle window, and the session never said goodbye. Not a lost connection — it is still open, and nothing is coming out of it. We don't know whether they're thinking or whether the laptop is shut, so the board stops claiming they're working.Silence, past the idle window.
○ session endedTheir Claude Code session ended and the hook said so.Reported, not guessed.

Why there is no heartbeat. Hooks only run when Claude Code does something. Between two edits ten minutes apart, no AgentMash code is running on that machine at all — the only way to change that is a background timer on a developer's laptop, which is a far bigger imposition than a hook and still says nothing when the machine is asleep. So the client reports what it can know for free (a session that ends in an orderly way) and the server infers the rest by decay on its own clock. A closed laptop, a killed terminal and a crashed process all send nothing; all three land in silent, which is exactly what we know about them. Nothing was added to the edit path: an edit is still one POST /events, and a pre-edit check is still one GET /check.

Clock skew. Clients send their own timestamps and the server is told to trust them, but never for presence. Every event is also stamped with the moment the server received it, and that stamp — not the client's — is what presence, the activity window and the dashboard's elapsed times are computed from. A timestamp from the future is clamped to receipt time, so a machine whose clock runs fast can't buy itself an extra half hour of looking busy. The dashboard ages the board on the server's clock too, so a viewer's own wrong clock doesn't empty the screen.

The advisory inherits this: instead of "alice is working in this file" twenty minutes after alice left, /check now returns a presence label per holder and the agent is told "alice has sent nothing for 22 min and appears to have stopped."

from README.md, “The live view: cursors on a codebase”