agentop: top, for coding agents
Jul 2, 2026 · 5m read
You start a coding agent on a task, tab away, and come back to... what, exactly? Maybe it finished. Maybe it's been stuck in a loop for ten minutes. Maybe it force-pushed to main, or spent six dollars re-reading the same file. You have no idea until you scroll back through a wall of tool calls.
I wanted top for that. So I built agentop.
agentop # live dashboard
agentop stats # one-shot summary, no TUIIt reads Claude Code's local session transcripts and shows you every session at once: state, tool calls, tokens, cost — and it flags the sessions doing something you'd want to know about. If one's gone rogue, you can pause it or kill it without leaving the dashboard.
Where the data comes from
Claude Code already writes every session to disk as JSONL — one event per line, under ~/.claude/projects/. agentop doesn't need an API, a daemon, or a network connection. It tails those files.
The ingest layer is an offset-tracking file reader wrapped in an fsnotify watcher: on startup it reads recent sessions, then streams new lines live as the agent writes them. Each line is parsed into an agent-agnostic event — a message with token usage, a tool call, a title — behind an adapter interface. Claude Code is the only adapter today, but the core never sees its format; adding another harness later is one package, not a rewrite.
Everything downstream folds those events into per-session state: when it started, when it last did anything, which models it used, what it spent, every tool it called.
Honest numbers, or none
The one rule the whole thing is built around: never show a number I can't stand behind.
Cost is computed from a per-model pricing table with longest-prefix matching, so claude-opus-4-8 and a dated legacy snapshot resolve to the right rates. But if a session used a model the table doesn't know, agentop doesn't guess a plausible-looking dollar figure — it renders ~? and moves on. A session's total is only shown as exact when every model in it is known.
Same principle for the transcripts themselves. Real JSONL has malformed lines — truncated writes, format drift across Claude Code versions. agentop skips them, but it counts them and shows the count in the status bar. A silently-dropped line is a lie by omission; a visible "skipped: 3" is the truth.
Detect
A dashboard that only mirrors state is a fancier tail. The point is to surface the sessions worth looking at:
- Stalls — no activity for N minutes, alerted once per stall episode and re-armed when work resumes.
- Thrash — the same tool call three times in a row, the signature of an agent stuck in a loop.
- Risky actions — a rule engine over each tool call:
rm -rf,git push --force,curl | sh, publish/deploy commands, reads of.envand key files, and writes outside the session's own project directory. - Budget — per-session and per-day spend caps. Off by default (I don't want to invent your limits), calendar-day-aware when you turn them on.
Act
Detection without a lever is just anxiety. agentop has two, both opt-in.
Pause is enforced through Claude Code's own hook system. agentop hooks install adds a PreToolUse hook that reads a small policy file the dashboard writes. Pause a session in the UI, and its next tool call is blocked with a message the agent can read. The hook is built to fail open: any error in it — bad input, unreadable policy, anything — allows the tool call through. A monitoring tool that can brick the thing it monitors is worse than no tool. If you never install the hook, agentop is pure observation and touches nothing.
Kill terminates the process. Transcripts carry no PID, so discovery is a heuristic — match running claude processes, rank by working directory — and it's deliberately gated: you press K, the dashboard shows you the exact pid and command it's about to kill, and nothing happens until you confirm. Best-effort, but never silent.
Building it
The whole thing is Go — Bubble Tea and Lipgloss for the TUI, fsnotify for tailing, a single static binary via GoReleaser, the same release setup as yank. It ships for Linux, macOS, and Windows.
I built it as 16 small, test-first tasks, each written by one agent and reviewed by another before the next began — which is its own story, and caught bugs that every unit test missed.
What's next
v1 is Claude Code only and its "done" detection is conservative — it knows a session ended if it killed it, but a session that quietly finished on its own still reads as idle. Next up: a second harness adapter, richer end-of-session detection, and a recorded demo. It's a small tool. But I haven't run an agent without it since.