Model or dataset
furkankly/zoetrope avatar
furkankly/zoetrope

zoetrope: a terminal flow graph for Claude Code and Codex sessions

Watch a Claude Code session as a live flow graph, in your terminal or your browser.

874 stars57 forksRustMIT

At a glance

What is it?
zoetrope reads the transcript files that Claude Code and Codex already write and draws each session as a live agent-and-tool graph, either in the terminal or in a WASM build of the same binary. It is a read-only viewer, so its main constraint is that it can only show what the transcript contains.
Who is it for?
Adopt zoetrope if you already run Claude Code or Codex from a terminal and want to see subagent fan-out and tool timing without leaving it; the Homebrew tap and prebuilt release archives mean no Rust toolchain is required to try it. Skip it if you need a hosted dashboard or a viewer for agents other than Claude Code and Codex, because the supported-agent table lists only those two.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What zoetrope shows that a scrolling transcript does not

Claude Code and Codex write a transcript for every session. That file is linear: prompt, tool call, result, prompt again. When the main agent spawns subagents, their work is interleaved into the same stream, and reading it back means reconstructing which agent did what from text order alone. zoetrope takes that file and renders it as a graph instead. The README describes a node per agent: the main session, the subagents it spawned, and workflow groups with their children nested underneath. Tool calls appear as chips below their agent, such as a bash chip with a count, and each chip resolves to a check or a cross when the call finishes.

The audience is narrow and specific. This is for someone running Claude Code or Codex in a terminal who wants to watch a session unfold, or to replay a finished one and understand how the work was distributed. It is not a general observability platform. The README states plainly that it is read-only and that nothing leaves the machine, which matters if your transcripts contain prompts and file contents you would rather not upload anywhere.

How the transcript becomes a graph

The mechanism is file-driven. zoetrope reads a session from any of its files, and according to the README it tells the formats apart by content rather than by path, so a single file argument works for either agent and a session id is searched across both. Give it a file and it reads the whole transcript, then keeps watching for new lines appended to it. Give it a directory, or no argument at all, and it finds the newest session in that project and follows it live.

The timeline is indexed by event rather than wall-clock. That is a deliberate design choice with a visible consequence: a busy minute gets room on the scrubber instead of collapsing into a sliver. The cost is that the timeline no longer maps to real elapsed time, which is why the README also mentions optional gap compression, described as a way to skip dead air or keep faithful real-time pacing. Replay is paced by the session's own timestamps, so the event index and the pacing are separate concerns.

Seeking backwards is the part that follows from the data model. Because the graph is derived from a transcript, moving back in time reconstructs the session as it stood at that moment: agents un-finish, tool counts fall, the graph shrinks. That behaviour is only possible because the transcript is the source of truth and the view is rebuilt from it rather than mutated in place.

Install routes and the commands you actually type

There are four ways in. Homebrew on macOS and Linux uses brew install furkankly/tap/zoetrope. Cargo uses cargo install zoetrope and needs a Rust toolchain. Release archives carry prebuilt binaries for macOS on Apple Silicon and Intel, Linux musl on arm64 and x86_64, and Windows x86_64, with no toolchain required. Building from source means git clone, then cargo build --release, then ./target/release/zoe. Whichever route you take, the command is zoe.

The usage examples in the README cover the main modes. Running zoe with no argument follows the current project's live session. zoe <dir> follows another project's session. zoe <file.jsonl> replays a recording from the start, and the README notes that any file of a session works. zoe <id> replays by session id or a unique prefix of one. Two flags change the behaviour: --follow opens a recording at its live edge, and --speed N sets playback speed with a default of 8.0. If detection guesses wrong, --provider codex forces the format. For scripting or a quick check without the TUI, zoe inspect <file|id> prints the session tree and exits.

The browser build at zoetrope.furkankly.dev/app is the same binary compiled to WebAssembly via ratzilla. The README says you can open a session from disk or drop a transcript on the page, and that it stays local there too. If you use Herdr, the multiplexer integration is three commands: herdr integration install claude (and/or codex) so Herdr learns session ids, herdr plugin install furkankly/zoetrope/herdr-plugin, and herdr plugin action invoke setup-keys --plugin furkankly.zoetrope. After that, prefix+shift+z on a focused agent pane opens the graph over the pane and the same key closes it.

Where the transcript-only design breaks down

Everything zoetrope draws comes from a file that another program wrote. That has a direct failure mode: if the agent changes its transcript schema, or writes to a different directory, the reader has nothing to parse. The README names two locations, ~/.claude/projects/ and ~/.codex/sessions/, and format detection is content-based, which helps with new fields but not with a renamed or restructured record. There is no mention of a schema version check or a compatibility fallback in the supplied material, so treat transcript-format drift as the main operational risk.

The second limitation is scope. The supported-agent table lists Claude Code and Codex only. If your work runs through a different harness, or through an editor extension that does not write one of those transcript formats, zoetrope has nothing to read. A hosted observability product that instruments the agent directly would not have that constraint, because it captures events rather than parsing files after the fact.

The third is depth. The README describes session info as mode and permission, and the agent inspection panel as provenance: the prompt that spawned the agent, the reasoning around it, its model, and every tool call with timings. It does not claim token accounting across a whole session, cost estimation, or cross-session aggregation. If you need to answer how much a week of agent work cost, this is the wrong tool.

Terminal multiplexer integration versus a general TUI dashboard

The closest comparison in the material is not another graph renderer but the integration path itself. Herdr is described as a terminal multiplexer built for running coding agents side by side, and it knows which agent occupies a pane and the id of the session running there. That is why the zoetrope plugin can open the exact session without you naming a file or an id. The plugin is a thin binding between Herdr's pane awareness and zoetrope's session lookup.

A general TUI dashboard or a log viewer takes the opposite approach. It reads files or streams you point it at and knows nothing about which pane produced them, so you supply the path or the id every time. That is more flexible across agents and less convenient inside a multiplexer. zoetrope sits between the two: it is a standalone binary that works with file and id arguments, and it gains pane awareness only when the Herdr plugin is installed. If you do not use Herdr, you are in the manual-argument mode, and the README's zoe <id> prefix matching is what saves you from typing full UUIDs.

Version, licence and what upgrading involves

The repository lists two releases: v0.1.0 on 2026-08-18 and v0.2.0 on 2026-09-10, with the last push to main on the same day as v0.2.0. That is a young project with a single minor version step between releases, and the supplied material gives no changelog, so there is no way to judge from here what v0.2.0 changed or whether it broke transcript parsing. Before upgrading, read the release notes for the version you are moving to.

Upgrade cost depends on the install route. Homebrew and Cargo upgrades are a single command each. The prebuilt archives are manual: you unpack a new archive and replace zoe on your PATH. If you built from source, a git pull followed by cargo build --release is the cycle, and it needs a working Rust toolchain at whatever minimum version the crate declares. The README shows an MSRV badge but does not state the number in the text, so check the crates.io page for it.

The licence is MIT. That permits use, modification and redistribution provided the copyright notice and permission notice are included, and it comes with no warranty. This is a general description of the licence, not legal advice; if you are redistributing zoetrope inside a product, read the LICENSE file in the repository and get your own advice. The browser build deserves a separate note: the README says it is the same binary compiled to WebAssembly and that it stays local, which is a claim about where the transcript is processed, not a statement about the hosting of the page itself.

Editorial conclusion

Adopt zoetrope if you already run Claude Code or Codex from a terminal and want to see subagent fan-out and tool timing without leaving it; the Homebrew tap and prebuilt release archives mean no Rust toolchain is required to try it. Skip it if you need a hosted dashboard or a viewer for agents other than Claude Code and Codex, because the supported-agent table lists only those two. Before relying on it, run zoe inspect on one of your own transcripts to confirm the session tree parses the way you expect, then check whether your future transcripts still land in ~/.claude/projects/ or ~/.codex/sessions/ after an agent update.

Official sources

  1. furkankly/zoetrope on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Community notes

Community notes