workstate

view-only · live · local-first

See what your agents are doing, as it happens.

workstate is a live dashboard for agent work. Projects hold tasks, tasks hold steps, steps hold subtasks. Every node carries a state and a color, and every change is pushed to the page over server-sent events. Agents write; people watch. There is nothing to click.

Ship the legend editor
/p/3f0c…a91e
In work
  • ✓ schema Completed
  • ✓ api Completed
  • ◑ dashboard In work
  • ◔ dashboard/legend Planning
  • ○ e2e Not started

01Install

git clone https://github.com/nvanderploeg/work-state
cd work-state && scripts/install.sh

The installer adds the workstate skill and MCP server to your agent setup. Pass flags after the script:

--with-server
Start a local tracker with docker compose on :3280.
--replace
Back up and replace existing skills and MCP entries.
--allow-tools
Allowlist the workstate MCP tools in Claude Code.

Dashboards live at /p/<projectId>. Anyone with the link can watch; only a write key can change anything.

02How agents connect

The workstate skill tells an agent when to open a task and report progress. It does that through five MCP tools:

  • start_taskOpen a task on this repo’s project, with optional steps. Returns the task and dashboard URL.
  • update_stepUpsert a step or subtask by path (chunk-2, chunk-2/tests): state, note, tags, position.
  • update_taskChange the task’s title, summary, state or note.
  • get_taskRead a task and its nodes back.
  • configureRead, replace or patch the project’s states, colors and theme.

On each task start the client looks for a server in this order and uses the first that answers:

  1. WORKSTATE_URL when set, only this server is tried
  2. localhost:3280 the local docker compose tracker
  3. workstate.nanzero.com the hosted tracker

If none responds, the agent continues untracked. A missing tracker never interrupts the work.

03API reference

JSON in and out. Errors are { "error": "…" }. Rows marked with a key need Authorization: Bearer <writeKey>.

MethodPathPurpose
GET/api/healthService status and version.
GET/api/presetsAvailable state presets.
POST/api/projectsCreate a project. Returns id, write key (once), url.
GET/api/projects/:idSnapshot: project, tasks, nodes, lastSeq.
PUT/api/projects/:id/configkeyReplace the project config.
PATCH/api/projects/:id/configkeyMerge states by key; replace other fields.
POST/api/projects/:id/taskskeyCreate a task, optionally with steps.
GET/api/tasks/:taskIdA task and its nodes.
GET/api/tasks/:taskId/eventsEvent history, optionally for one node path.
PATCH/api/tasks/:taskIdkeyUpdate title, summary, state, note.
PUT/api/tasks/:taskId/nodes/<path>keyUpsert a step or subtask.
GET/api/projects/:id/streamServer-sent events; resume with Last-Event-ID or ?since.

Stream

GET /api/projects/:id/stream sends frames as id: <seq>, event: config | task | node, and a JSON data line. Reconnect with Last-Event-ID to replay missed events. A : ping comment keeps the connection warm; an idle event ends it after a quiet period.

Default states

The build-it preset. A project starts in queued.

StateKeyColorKindMotion
○ Not startedqueued#9ca3afpendingnone
◔ Planningplanning#f97316activeshimmer
◑ In workin_work#eab308activepulse
◕ Testingtesting#a855f7activepulse
! Needs inputneeds_input#ef4444blockedblink
✕ Failedfailed#ef4444failednone
✓ Completeddone#22c55edonenone