Skip to content

yrstm/agentdash

Repository files navigation

agentdash

w, but for AI coding agents. agentdash prints a table of the agent processes on a Linux box: what each one is working on, what model it is on, how full its context is, and whether it is blocked waiting on you. -w turns the table into a small interactive TUI.

It is a single static binary with zero runtime dependencies, reading the session files agent CLIs already write locally (Claude Code and Codex are supported; adding another agent is a small parser, see CONTRIBUTING.md) and /proc directly. No daemon, no server, no API calls, no telemetry, no file watcher, and it never launches or manages sessions. Watch mode samples foreground state on the TUI refresh tick, like w or htop. I wrote it because I kept losing track of agents across tmux sessions; maybe it is useful to you too. Linux only.

demo

Install

curl -fsSL https://raw.githubusercontent.com/yrstm/agentdash/main/install.sh | sh

or grab the binary directly:

curl -fsSLo ~/.local/bin/agentdash https://github.com/yrstm/agentdash/releases/latest/download/agentdash-linux-amd64
chmod +x ~/.local/bin/agentdash

or with Homebrew (this also works on Linux), or go install:

brew install yrstm/agentdash/agentdash
go install github.com/yrstm/agentdash/cmd/agentdash@latest

It is a single static binary with zero runtime dependencies. Optional: tmux (pane jumping, attachment glyphs), docker (sandbox section, skipped if absent), jq (only for the integrations). The auditable v1 bash version lives in legacy/ and keeps working.

Usage

agentdash              print the table once
agentdash -w [secs]    watch mode (default 5s), keys below
agentdash -a           expand collapsed rows and healthy sections
agentdash -l           long view: adds PID, TTY, UP columns
agentdash -t           tree view: group agents under the wrapper that spawned them
agentdash --json       machine-readable output (schema_version 1)
agentdash --plain      no color, no glyphs; NO_COLOR is honored
agentdash --any-waiting   exit 0 if anything needs you

agentdash go [row|pid]     jump to that agent's tmux pane
agentdash show <row|pid>   drill-down with recent turns and resume command
agentdash why <row|pid>    where every value on the row came from
agentdash label <row|pid> "text"   pin a task label
agentdash resume <row|pid> print the resume command for a session
agentdash recap [4h]       what changed since you last looked

Watch mode keys

Watch mode has a cursor (); keys act on the selected row. Panels open over the board and any key returns to it.

j/k or arrows   move the cursor
tab             switch between Agents and History
g               jump to the agent's tmux pane
s               drill-down panel: recent turns, session path, resume command
y               provenance panel: where each value on the row came from
L               edit the task label
r               show the resume command
/               filter rows across task, cwd, model, status (Esc clears)
o               cycle sort: urgency, last-write, tokens, uptime
History view: s details, r resume, i read/command disclosure
t               toggle tree view        l   toggle long view
a               toggle expanded view    ?   help
mouse           wheel scrolls, click selects (off under --plain)
q               quit

The board refreshes on foreground TUI ticks. Process starts and exits are picked up by a cheap /proc scan every second (AGENTDASH_PROC_TICK); the full board and History view resample on the watch interval.

The table

devbox 14:02 · 2 need you · 3 working · 6 idle · 8m ctx held idle · load 0.27

  AGENT    LAST  MODEL      TOKENS     CTX        ACT      STATUS     CWD        TASK
▸ claude ○ 4m    opus-4-8   34m/359k   ▓▓▓░░  45%   ▅▂▁    waiting    ~/c/api    settlement reconciliation
  claude ● 12s   fable-5    18m/285k   ▓▓░░░  35%   ▆█▇▅   working    ~          migrate the queue
  + 2 wrappers · 1 unmatched (-a to list)

  ok: tmux ×4 · logins ×2 · sandboxes ×3 · ports ×4 · no zombies

Rows sort by urgency and keep their order between refreshes. Healthy sections collapse into the ok: line and expand only when something is flagged; pass -a (or set AGENTDASH_EXPAND=1) to always expand everything. Defunct (zombie) processes and orphaned wrapper processes — a bash -c/nohup launcher still running with no controlling tty after its agent has exited — surface in a ZOMBIES & ORPHANS section when present. Glyphs: tmux attached, detached; a red means the agent is waiting and nobody is attached.

Columns: LAST is time since the session file was written. TOKENS is cumulative input/output, where input includes cache reads and writes (it measures context fill, not billing). CTX is the last request against the model's context window, yellow at 70%, red at 85%. ACT is bytes appended per refresh over the last 8 intervals. TASK is your label, else the session's summary, else the first prompt; a trailing ? means the process-to-session pairing was heuristic.

Colors carry one meaning each: green working, yellow worth a look, red needs you now, dim ignorable. A healthy board is almost colorless.

Tree view (-t, or t in watch mode) regroups the rows so an agent sits under the wrapper process that spawned it, found by walking the ppid chain. Urgency order still applies to the top level.

Design notes

agentdash started life as a bash script with an embedded stdlib-only Python parser: session files are JSONL with nested, escaped content (prompts hold quotes, unicode, pasted code), which bash regex cannot parse correctly, and jq would have been a lateral dependency swap that loses the stateful incremental scan. v1 proved the heuristics in bash+python; v2 compiles them. The genre's reference tools (w, htop) are compiled C for a reason: the Go version reads /proc and the session files directly, drops the procps/iproute2/python3 dependencies entirely, and keeps watch mode as a foreground sampler with no daemon, listener, or file watcher. The v1 script is preserved, working, in legacy/agentdash.sh; tools/parity.sh holds the two implementations to identical --json output. The only socket the tool will ever open is the local docker unix socket for the sandboxes section, and CI enforces that with strace.

The scanner is incremental by byte offset: each render stats every paired session file and parses only the bytes appended since the last look, folding them into a cached per-session entry. Only complete lines are consumed, since an agent may be mid-write; a partial tail line waits for the next refresh. That is why a board over gigabytes of session history costs milliseconds once the cache is warm.

Pairing a pid to a session file never guesses silently. A five-tier evidence chain runs from exact to heuristic, records which tier fired, and anything below the confident tiers is marked with a ? on the board. agentdash why <row> prints the recorded evidence for every value on the row.

Performance

Measured with the reproducible suite in bench/ (4-core container, 25 MB session corpus, methodology and caveats in docs/benchmarks/):

metric v1 (bash+python) v2 (Go)
one-shot render, warm cache 174 ms 15 ms
one-shot render, cold cache (25 MB) 562 ms 368 ms
idle watch CPU, 10 min avg 3.65 % 0.29 %
session write to screen ~2.3 s ~80 ms
peak memory (PSS), cold render 38 MB 17 MB
dependencies on a clean box bash python3 procps iproute2 none

How values are derived

Pairing a process to a session file walks an evidence chain: an open fd in /proc, then a unique session file in the project dir for the process cwd, then a first-entry timestamp within 5 minutes of process start, then a sticky previous guess, then the newest unclaimed recent file (the last two are heuristic and marked ?). Codex sessions record their cwd and start time in the rollout file, which pairs them directly. agentdash why <row> prints which tier applied.

Status: file written under 60s ago is working; over 10 minutes quiet is idle; in between, waiting if the last entry is an assistant turn, else it is graded by how long it has been quiet on a user/tool entry: busy? (dim) under AGENTDASH_STUCK_SECS (default 90s) — likely a slow tool call, not alarming — and stuck? (red) past it. This grading replaces the old flat "silent over a minute = stuck?" false positive. respawn ×N means three or more fresh pids on one session file within 10 minutes. Thresholds are configurable via AGENTDASH_WORKING_SECS, AGENTDASH_STUCK_SECS and AGENTDASH_IDLE_SECS.

Context windows come from ~/.config/agentdash/context-windows.conf (<model-id-substring> <window-tokens>, first match wins), then built-in defaults, then self-correction: if observed context exceeds the assumed window, the larger tier is adopted and written back to the conf.

Port flags: NEW is first seen since the previous run, dup-cwd is two listeners in one project directory, no-agent is a tty-less listener in a project directory no agent or tmux pane is using.

Privacy

The TASK column shows prompt text and the cache at ~/.cache/agentdash/usage.json persists it (mode 0600). Mind screen-sharing and log shipping.

License

MIT.

About

w for your AI agents - a terminal table of every coding agent on a box and whether it needs your input

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors