DEV Community

Kosta Stamboldzhiev
Kosta Stamboldzhiev

Posted on Fully Autonomous

Your Claude Code session as a 25-second timelapse (and the timestamp that lied)

Claude Code writes every session to disk as JSONL: one line per message, tool call and result, and a separate file for every subagent. I have been building a read-only viewer for those files that draws a session as a pixel-art office — each agent is a person at a desk. This week it learned to export a session as a GIF:

a nine-minute Claude Code session with 24 subagents as a 25-second timelapse

That is a staged session, so nothing private is in it: an orchestrator sends six scouts to map a billing service, hands eight changes to eight builders, and puts a verifier on each. One verifier comes back REFUTED, so a ninth builder goes to fix it and a ninth verifier checks the fix. Every frame is the real renderer replaying transcript events — the same code path as a real session.

To make one from your own latest session:

npx https://github.com/Kostakurta8/roundtable/releases/latest/download/roundtable.tgz --gif
Enter fullscreen mode Exit fullscreen mode

It writes roundtable-<session>.gif where you ran it, in a few seconds, and sends nothing anywhere. By default it shows the task, the agent names and what they said, so look before posting; --bare draws the same run with none of that text.

Three things were harder than they looked.

1. A real session is mostly waiting

The first version sampled the session at even intervals and produced a still photograph with a few seconds of movement in it. Agents spend most of their time inside a tool call — a nine-minute build, a long read — and nothing moves.

So time is compressed before it is sped up. Every silence between two events is clamped to a beat (2.5 s, tightened down to 0.5 s for a busy session), and only then is the whole thing played faster to fit the clip. A session still too long at that point becomes its busiest stretch instead, scored by what a viewer can see: an agent arriving is worth 12, leaving 6, a file edit 2, a token count moving 0.

The wall clock in the office keeps the real time, so the cuts are visible: it jumps where the session waited.

2. One timestamp in the pipeline was lying

The first full render of the staged session reported it as six days long. It is nine minutes.

The observer attaches each subagent's name from a sidecar file next to its transcript, and it stamped that event with the moment it read the file, not the moment the agent started. The live viewer never noticed, because it processes events in arrival order. The clip sorts by timestamp, so every agent's name landed at the moment I ran the command — after all of them had already left the building, and six days after the session ended.

The fix pins each name to that agent's first transcript line. There is a test that fails if the staged session comes out longer than fifteen minutes.

3. I wrote the GIF encoder instead of installing one

The office is drawn with filled rectangles into a 480×270 RGBA buffer by a small software rasteriser that the visual-regression tests already use, so the missing piece was only the file format. It is about three hundred lines:

  • One palette for the whole clip, cut by median cut from a histogram of every frame, so a colour cannot shimmer between two indices from frame to frame.
  • Each frame carries only what changed: cropped to the bounding box of the changed pixels, with unchanged pixels inside the box written as the transparent index. An office where two people are walking is two small rectangles, not a whole room.
  • Scaling after indexing: the buffer is blown up 2× nearest-neighbour after the palette lookup, which is how the browser shows pixel art anyway, and LZW eats the repeated pixels.

The tests decode every frame back with a decoder written from the spec and compare pixel for pixel, including a 256×256 noise frame that fills and clears the LZW code table many times over — the path where encoders usually break.

A 25-second, 25-agent clip at 960×562 comes out at about 3 MB, and a whole render takes a few seconds.


It is also a live viewer on localhost where you can scrub back to any second of a session and see what each agent cost. Read-only, MIT, no account, no API calls: github.com/Kostakurta8/roundtable

If you run --gif on one of yours, I would like to know what it got wrong.

Top comments (0)