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.
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.
$ 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
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.
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.
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.
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.
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.
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 versioned JSON Schema, a validator and a reducer, checked in CI against a golden log and the three worlds it must produce.
Everything above the seam is a fact about the repository. Everything below it is a decision about pictures, and belongs to the client.
Immutable, timestamped domain events, each with a proof link.
work_item.openedThe log reduced to entities with state, at any moment.
GET /lot/world?at=Domain roles mapped to whatever gets drawn.
pull_request → crateAn SVG house, a 3D city, a phone, a terminal pane.
yoursThe 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.
Two clients over one log is the only real proof the contract holds, so the terminal, the medium furthest from a browser, came first.
One snapshot from a file or URL, schema-validated, with proof links.
A cutaway building, one room per subsystem, readable in a second.
The flagship three.js client: districts, buildings and rooms you walk through.
A thin client that asks for the world and draws it, with no reducer on the phone.
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.
npm ci installs the protocol package and the terminal client.npm run terminal -- clients/terminal/sample-world.jsonnpm run terminal -- http://127.0.0.1:3000/lot/worldThe 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
Simherd is early. The contract and the first client exist; the backends and the graphical clients are the next milestones.
JSON Schema, validator, reducer and golden fixtures, run in CI. A one-shot terminal snapshot viewer on top.
A seeded generator that serves plausible fleet activity over the four endpoints, so every client can be built without a real fleet.
The three.js world, the isometric lot, mobile, file playback, and opt-in local backends for real fleets and GitHub.
Follow the project page for the changelog as the generator and the first graphical client land.