Early-stage · protocol first

Agent fleets, rendered as games.

A dozen coding agents produce facts faster than anyone reads them. Simherd turns those facts into a place you can read at a glance: subsystems become rooms, agents become residents, a pull request is something carried through the building.

Working today: world protocol, validator, terminal snapshot viewer

$ npm run -s terminal -- clients/terminal/sample-world.json
SIMHERD  SYNTHETIC  2026-08-22T11:04:11Z

CI and gates  failing  3 open
  actor  Margot Porter  working  CI and gates
  item   pr:212  checks_running  take upstream's pty fix
         proof: https://example.invalid/pull/212
Documentation  healthy  0 open
  No active actors or work items
Real output of the terminal viewer reading the checked-in synthetic sample world.
The idea

Facts in.
Any picture out.

The place can look like anything: an isometric lot, a 3D city, a phone screen, a terminal pane. So the backend serves domain facts and never learns what it is drawn as.

Facts, not metaphors

The wire carries subsystems, actors and work items with health, status and staleness. Whether a stale pull request is a dusty crate or a grey row is the client's call.

Proof on every fact

Every event links to the artifact that proves it: the pull request, the run, the commit. An event without proof is dropped, so nothing on screen is invented.

Deterministic replay

Events carry a sequence number and a stable id, and times come from the artifact, not a worker's clock. The same log always reduces to the same world.

Fidelity is always shown

Every world says whether it is live, recorded or synthetic, and clients display it. A demo can never pass itself off as your real fleet.

A terminal client, today

The viewer reads a world from a JSON file or an HTTP endpoint, validates it against the schema and prints subsystems, actors and work items with their proof links.

A contract with tests

A versioned JSON Schema, a validator and a reducer, checked in CI against a golden log and the three worlds it must produce.

The protocol

Four layers.
One seam.

Everything above the seam is a fact about the repository. Everything below it is a decision about pictures, and belongs to the client.

  1. 01

    The log

    Immutable, timestamped domain events, each with a proof link.

    work_item.opened
  2. 02

    The world

    The log reduced to entities with state, at any moment.

    GET /lot/world?at=
  3. 03

    The skin

    Domain roles mapped to whatever gets drawn.

    pull_request → crate
  4. 04

    The client

    An SVG house, a 3D city, a phone, a terminal pane.

    yours

The proposed surface serves the reduced world, the raw log as NDJSON, a live stream over SSE and WebSocket, and the schema itself, so a phone can stay thin while a browser scrubs the timeline locally.

Clients

One world.
Many ways to see it.

Two clients over one log is the only real proof the contract holds, so the terminal, the medium furthest from a browser, came first.

Working today

Terminal viewer

One snapshot from a file or URL, schema-validated, with proof links.

Planned

Isometric lot

A cutaway building, one room per subsystem, readable in a second.

Planned

3D world

The flagship three.js client: districts, buildings and rooms you walk through.

Planned

Native mobile

A thin client that asks for the world and draws it, with no reducer on the phone.

Try it

Read a world
in your terminal.

With Node 26 and a clone of the repository, the viewer builds and reads the synthetic sample in a few seconds. Point it at any server that implements the world endpoint to read that instead.

  1. Installnpm ci installs the protocol package and the terminal client.
  2. Read the samplenpm run terminal -- clients/terminal/sample-world.json
  3. Or read a servernpm run terminal -- http://127.0.0.1:3000/lot/world

The viewer makes one request and prints one snapshot. It does not start a backend or stream updates. The repository is private while the protocol settles.

# F=packages/protocol/fixtures
$ npm run -s terminal -- $F/world-0900.json
SIMHERD  SYNTHETIC  2026-08-22T09:00:00Z

CI and gates  healthy  0 open
  No active actors or work items

$ npm run -s terminal -- $F/world-1000.json
SIMHERD  SYNTHETIC  2026-08-22T10:00:00Z

CI and gates  healthy  1 open
  item   pr:212  open  Take upstream's pty fix
         proof: https://example.invalid/pull/212

$ npm run -s terminal -- $F/world-1100.json
SIMHERD  SYNTHETIC  2026-08-22T11:00:00Z

CI and gates  healthy  1 open
  item   pr:212  checks_running  Take upstream's pty fix
         proof: https://example.invalid/pull/212
Status

Honest about
how far along.

Simherd is early. The contract and the first client exist; the backends and the graphical clients are the next milestones.

Done

The contract

JSON Schema, validator, reducer and golden fixtures, run in CI. A one-shot terminal snapshot viewer on top.

Next

Synthetic backend

A seeded generator that serves plausible fleet activity over the four endpoints, so every client can be built without a real fleet.

Later

Graphics and live data

The three.js world, the isometric lot, mobile, file playback, and opt-in local backends for real fleets and GitHub.

Watch the work
like a place.

Follow the project page for the changelog as the generator and the first graphical client land.