# zoetrope
Your coding agent writes down everything it does. Every session, every subagent, every tool call, into a JSONL file under ~/.claude/projects/. It has been doing that the whole time you have been using it.
Almost nobody reads those files. They are not built to be read — one line per event, thousands of lines, no shape.
zoetrope reads them for you and draws the session as a graph: the main agent at the top, the subagents it spawned underneath, the tool calls under each of those, with the edges animating while an agent is working and settling when it finishes. It is MIT licensed, it needs no account and no API key, and it has no network code in it at all.
Here is the number that made me install it. I pointed it at one real session on this machine:
23 agent(s), 1375 tool call(s) · 32 queued · 12 file edit(s)
I had watched none of that happen. I had watched text scroll past.
Install it in one minute
brew install furkankly/tap/zoetrope
zoezoe with no arguments follows the current project's live session. That is the whole setup — the tap is three formulae and the binary is about 3 MB.
No Homebrew? cargo install zoetrope if you have a Rust toolchain, or take a prebuilt binary for your OS from the releases page — macOS on Apple Silicon and Intel, Linux musl on arm64 and x86_64, Windows x86_64 — and put zoe on your PATH.
Or install nothing at all. zoetrope.furkankly.dev/app is the same engine compiled to WebAssembly. Drop a .jsonl from ~/.claude/projects/ onto the page and you get the same graph, read in your own browser.
Start with `inspect`
Before you learn a TUI, run the headless one. It prints the session tree and exits:
ls -S ~/.claude/projects/*/*.jsonl | head -5 # your biggest sessions
zoe inspect <one of them>
You get the agent tree, each agent's model, its tool counts split into succeeded, failed and in-flight, and the prompt that spawned it:
◌ [main] main (idle)
model: claude-opus-5
tools: 336 (326✓ 10✗ 0⏳) tokens: 371007
✓ [subagent] general-purpose "Diagnose occlusion and ground contact" tools: 68
✓ [subagent] script-skeptic "Adversarial script check before voiceover" tools: 5
✓ [subagent] general-purpose "Autopsy the shipped SHADER video" tools: 76
One command tells you whether the graph is worth opening.
The four things it does that a log cannot
Agents as nodes. Every subagent gets its own card with a status, its current tool, a running tool count and its output tokens. Workflow groups nest their children underneath. In a log, a subagent's entire life collapses into one summary line.
Tool calls as chips. They surface beneath the agent that ran them — ⚒ bash ×5, or ⚒ bash 0.5s ticking during a single call — and resolve to a tick or a cross.
Time travel that is exact. One scrubbable timeline over both live and replayed sessions, indexed by event rather than wall-clock so a busy minute gets room instead of collapsing into a sliver. Seek backwards and you see the session exactly as it stood: agents un-finish, tool counts fall, the graph shrinks. That works because the model is a pure function of the events seen so far, not a mutable state that has already moved on.
A camera that follows the work. Press f and it glides to whichever agent just did something.
The claim worth checking yourself
The repo says: *"There is no HTTP client anywhere in the dependency tree, and tokio is pulled in without its net feature. cargo tree is the proof. This is a property you can check, not a promise."*
So check it:
git clone https://github.com/furkankly/zoetrope
cd zoetrope
cargo tree | grep -Ei 'reqwest|hyper|ureq|surf|isahc' || echo "no HTTP client in the tree"
That is a better kind of privacy claim than a policy page.
Three things it does not do
It is Claude Code only. It parses Claude Code's own transcript format. If you use Cursor, aider, Copilot or Codex, this does nothing for you — not less well, nothing. There is no adapter.
It is read-only. It never writes to your transcripts and cannot steer, retry or cancel a run. It is an instrument, not a controller. Records it does not recognise are skipped rather than treated as fatal, which keeps it working across Claude Code updates — but it also means a beat missing from the graph is not proof it did not happen.
It is not the only tool in this category. Several are bigger: claude-tap intercepts agent API traffic, claude-code-history-viewer is a desktop browser for conversation history, claude-code-viewer is a full web client, claude-replay converts sessions into a replayable format. They render the *conversation*. zoetrope renders the *topology*. Pick on which of those you actually want to look at.
Get the kit
Three files: the install and the six commands worth knowing, an honest page on what it cannot read including the cargo tree check, and watch-session.sh — a script that installs zoetrope if it is missing, then lists your recent sessions with their agent and tool counts so you can pick one to replay.
Or comment ZOE on the reel and I will send it to you.
The repo: github.com/furkankly/zoetrope — MIT, 598 stars in its first nine days.
