x‑hakt

Every project a ship

control

svgnextjstypescript

The dashboard has known for a while which projects have an working on them, because every Claude or Codex session sends small events as it goes: started, working on this task, committed, finished. For a while that turned into a list of lanes, one per session, with timestamps. Accurate and completely dead to look at. The work was happening and the page made it look like a spreadsheet was happening.

A harbour instead of a table

So the activity page became a harbour town. Every project in the fleet is a ship. The ones with work going on are tied up along the quay; the quiet ones ride at their moorings out in the bay, so the whole fleet is on screen at once and you can see at a glance which hulls have crew aboard. Each ship’s hull colour, sail colour and Jolly Roger come from a style seed from the project’s name, so a project looks the same every time you load the page without anyone having to pick colours for twenty ships.

the quay: ships with crew aboardSalty MegOne-Eyed Jincrate going upthe bay: quiet projects at their mooringstavernfinished crewsship’s log newest first14:02 Salty Meg commit ×1213:48 One-Eyed Jin started
Every project is on screen at once. Crew aboard means work happening; the bay is everything else.

Each agent session is a sailor, and sailors get names. Not “Claude” and “Codex”, which made every deck look like a staffing agency, but generated pirate names from the same kind of seed, stable for the life of the session, so the one hauling cargo up the gangplank on one project is recognisably the same one who wanders off to the tavern when it finishes. A sends a crate up the gangplank and down the hatch. A sailor who’s done goes into The Plastered Bastard. A session that’s gone quiet for too long falls asleep sitting up against the mast, which took two attempts, because the first version had him lying on his side and it looked like a crime scene.

event from the sessionwhat the harbour showsstarteda sailor walks up the gangplankworking on a taskstays on deck, task on the cardcommita crate goes up and down the hatchfinishedoff to the tavernquiet too longasleep sitting up against the mast
The events were already being sent. The harbour only changed how they look.

Underneath the harbour runs the ship’s log, one line per event, newest at the top, repeats folded together so twelve commits in a row read as one line with a count. Clicking a ship zooms the harbour in on it and opens a card with the crew and what they’re working on.

The same port, seen from the street

The fun part was making it public. x-hakt.com/crew shows the same scene, embedded from the dashboard, and the dashboard itself stays behind a login. The public feed is built from a whitelist rather than a filter: every field that goes out is chosen on purpose, times are rounded, task keys and host names never leave, and a project only appears under the alias I’ve approved for it. Down here, it’s our time, and you can watch it, but you can’t read the charts. The sizes itself by a postMessage from the embed, checked against the and the source window before the page believes a word of it, and there’s a full width button and a full screen one, because a harbour crammed into a blog column looks like a harbour seen through a keyhole.

dashboardbehind a loginfull eventswhitelistchosen fields onlytimes roundedapproved aliasesno task keys, no hostspublic feedsame harbour,less saidx-hakt.com/crewiframe embedpostMessage: my heightbelieved only if originand source window match
Built from a list of what may leave, not a list of what may not.

None of it does anything useful that the old lanes didn’t. It’s just that I now leave it open on the second screen, and I never once left the lanes open. Fair winds.

-x