New
Apps 840Makers 839This week 840
Promote your app−30%
burnboard screenshot 1
0views in
the last 30 days

burnboard

Live and historical monitor for AI coding agent usage — Codex CLI and Claude Code, side by side

Built with Claude/Claude Code/Codex

by sondeinc · from USUnited States · added Oct 29, 2026
no ratings0 comments

A live and historical monitor for AI coding agent usage — OpenAI Codex CLI and Claude Code, side by side.

image

burnboard tails the JSONL session transcripts both tools write locally — Codex to ~/.codex/sessions/, Claude Code to ~/.claude/projects/ — and turns them into a local web dashboard. No account access, no API keys, nothing sent anywhere. One required dependency for local MessagePack caching; an optional tokenizer for offline text counts.

Every view carries an All agents / Codex / Claude Code toggle and its own repository picker: see one tool or one codebase in isolation, or everything together in a single combined view with each session badged by which agent ran it. Repository choices are independent per tab, so changing History does not silently change an Economy comparison.

  • Activity — one live panel per active agent, refreshed every ~2s, with a billed-token consumption chart, the current command history, per-command token deltas, and a quota/usage bar (weekly rate-limit % + tokens today/this week).
  • Subagent lineage — spawned-by chains up to the root prompt, including Codex's auto-approval guardian shown nested under the thread it's reviewing.
  • History — every past session, sortable, with prompt, model, effort, git branch, billed tokens and command count, filtered by clicking the period chart above it. Sessions that changed models show the exact usage attributed to each model instead of assigning the whole run to the first model seen.
  • Investigate — a local agent flight recorder with a selectable clock timeline, complete source-event inspection, cross-session search, evidence pins, saved investigations, notes, and editable handoffs. Its real-time Live Monitor is optional and off by default.
  • Attention + Worktrees — deterministic local findings for repeated failures, pending work, and stale validation, plus repository/worktree lanes, recorded edit overlaps, and evidence-linked outcome trails. Observations never stop or rerun an agent.
  • Spin watch — an Attention Brief rule for agents that are churning (review-round treadmills, merge-gate ceremony), fed by an optional always-on hook that runs inside Codex and Claude Code even when burnboard is closed, with a durable episode archive.
  • Trends — token consumption bucketed over time, split into two lists (by base command, by prompt); click a bar to drill into it, click a row to plot just that command or prompt.
  • Agents — the same spend cut by who spent it, so agent types can be compared on efficiency rather than volume.
  • Economy — a token-waste audit: which commands dump the most output back into context, truncation hits, polling/wait round-trips, and commands re-run unchanged — plus ranked findings on what to change, grounded in the tooling you actually have.

It also corrects for quirks the raw numbers don't show — Codex's token counter resetting on context compaction, total_token_usage under-counting long sessions, UTC timestamps, JS-wrapped tool calls, and (on both sides) separating a request's genuinely new tokens from the cached context resent on every turn.

Run

Requires Node ≥ 18. Run npm install before starting the monitor.

git clone https://github.com/sondeinc/burnboard
cd burnboard
npm install
node server.js            # -> http://localhost:4317

Options: --port 8080, --root /path/to/.codex, --claude-root /path/to/.claude, --no-ai, --local-tokens, --no-spin-check, --spin-check-only (see Installing the agent hooks).

--no-ai (or BURNBOARD_NO_AI=1) disables Dive deeper, the optional feature that runs a Codex or Claude Code agent to analyze the evidence behind a token-usage finding. Burnboard will not launch an agent or spend tokens on your behalf; the dashboard and its measured findings still work.

Optional offline text-token counting

npm install --ignore-scripts
node server.js --no-ai --local-tokens
node token-count.js --model gpt-5 /absolute/path/report.json
node token-count.js --encoding o200k_base /absolute/path/report.json

js-tiktoken@1.0.21 is an optional dependency with bundled encoding assets. Installing it requires the registry once; counting afterward requires no network, API key, inference or report upload. It works under --no-ai. Without it, the monitor still works. Installation with npm install --omit=optional installs the MessagePack cache dependency without the tokenizer.

The Economy view separates tokenized logged text from estimated outputs and reports UTF-8 bytes for each method. The pinned package's exact model map selects an encoding; unsupported, missing, Claude and future models retain the explicitly labeled characters/4 estimate. We do not infer an encoding from a model-name prefix. A package mapping is not verification of the live consumer: consumerMappingVerified stays false. In particular, this package does not map gpt-5.6-sol or gpt-6-astra; selecting gpt-5 to count their output would be misleading.

The file/stdin command emits a JSON measurement with tokens, UTF-8 bytes, text SHA256, encoding-asset SHA256, tokenizer version and mapping method. --encoding is an explicitly chosen encoding, not a verified model mapping. Input must be valid UTF-8, including any BOM and newlines; it is counted whole, with an 8 MiB limit and no silent truncation. Tool-output special-token spellings are counted as ordinary text. Exit 0 means tokenized, exit 2 means an explicit estimate, and exit 1 means invalid/unreadable/oversized input.

This measures logged text, not total request input, model output generation, image/audio tokens or billing. Recorded request usage and approximate per-command attribution remain unchanged. Codex's original-output truncation marker is retained separately from delivered-text counts. Parser measurements use the tool call's turn model, not the session's first model. Changing counting mode or tokenizer availability invalidates the rollup cache and rescans it. Local tokenization costs extra CPU/memory, so it is opt-in; logged texts over 8 MiB fall back to an explicitly labeled estimate. npm test runs the offline counter/parser and --no-ai server tests (install the optional dependency first).

The page is read fresh on every request, so UI changes only need a browser reload — but the server holds its routes in memory. After pulling a new version, restart the process, or a page built against new endpoints will sit waiting on routes the running server answers with 404.

Finding your data

On startup burnboard locates each agent's home directory and prints what it found. Either source can be absent — it just shows whichever it finds.

Codex CLI, in this order:

  1. --root <dir>
  2. $CODEX_HOME (the same variable Codex itself honours)
  3. $XDG_CONFIG_HOME/codex
  4. ~/.codex, then ~/.config/codex, then the OS app-support dir

It picks the first one containing a sessions/ directory.

Claude Code, in this order:

  1. --claude-root <dir>
  2. $CLAUDE_HOME
  3. ~/.claude

It reads the flat projects/<project-slug>/<session-id>.jsonl transcripts underneath.

What it shows

Seven tabs: Activity, History, Investigate, Worktrees, Trends, Agents, Economy.

Investigate

Open Investigate directly or follow an investigate → link from Activity. Burnboard builds a separate, disposable local index; it never modifies the Codex or Claude Code transcripts. Search messages, tool inputs and results, paths, and recorded identifiers, then filter by repository, worktree, agent, model, event type, or time. Open the exact original record, pin useful evidence, add notes, and preview an editable, size-bounded Markdown handoff.

The Live Monitor control is an explicit opt-in. When enabled, one localhost event stream indexes complete records appended to recently active logs. New arrivals update the timeline while preserving selection, focus, and reading position; following the newest event is a separate choice. Turning the monitor off closes the stream and stops continuous scanning.

Live Monitor does not launch Codex or Claude, call a model, consume model tokens, execute or rerun commands, stop an agent, or send a notification. The separate Dive deeper action in Economy is the only feature that can ask an installed assistant to interpret evidence, and it runs only after an explicit click. See docs/investigation.md for limits, privacy boundaries, API routes, and the reproducible performance fixture. Spin watch is a separate, optional hook that runs inside the agents; it is not part of Live Monitor.

Attention brief

Activity starts with a return brief covering activity since the previous visit or a selected 1-, 8-, 24-, or 72-hour interval. It groups the result by recorded repository and working directory, then shows the highest-priority twelve findings first. Show all reveals the rest of the bounded response.

The rules are deliberately narrow and deterministic:

  • spin watch: an agent kept a churn-like pattern over its last ~120 actions (see Spin watch);
  • the same normalized command produced an equivalent recorded failure more than once;
  • the same command and equivalent result repeated at least three times (which may be intentional polling, not a defect);
  • an identifiable tool call has had no paired result for at least two minutes;
  • a direct completion-like claim has no recorded successful validation, or a relevant edit was recorded after the latest successful validation; and
  • an explicit child session's latest recorded activity has no later acknowledgement recorded in its parent.

Every finding names its trigger, severity rationale, time interval, uncertainty, and supporting events. Investigate evidence opens those records in the flight recorder. Acknowledge, dismiss, snooze, and per-rule controls stay in browser storage; they do not change transcripts or agent behavior. “No acknowledgement recorded” never means Burnboard knows a result was ignored.

Spin watch findings sort to the top, and each churning session is one card: that session's other findings in the same time span (repeated commands, repeated failures, long waits, and so on) nest under it as supporting evidence. Sessions without a spin finding render as before. A spin card shows the plain-English reasons (for example “review round 23”, “5 heavy gate runs in 2 h”, “1 new file in the last 120 actions”, “same command 6 times in a row”), the score history, the archived evidence trail, nearby human messages, and the outcome: merged, converged, abandoned, or you called it out once the episode has ended. While it is still open, the card says active (the thread's last recorded action or message was at most 5 minutes ago, the same clock as the Activity tab's idle dot), idle since HH:MM (local time, with the date when it was not today), or abandoned after 12 hours with no activity. The label is worked out when the brief loads and updates while the page stays open; the outcome field in /api/spin/summary and the brief's findings uses the same words. Investigate evidence opens the session in the flight recorder.

The Since picker adds All time (archived), which lists every archived spin episode, including sessions whose transcripts are gone (Claude Code deletes transcripts after about 30 days); those cards say so and show the archived trail instead. A small Spin counter in the header, visible on every tab, counts unacknowledged spin findings from the last 24 hours and opens the brief filtered to spin. Spin settings sit under Rule controls next to the per-rule checkboxes.

Spin watch

Spin watch detects coding agents that are churning or spinning. Churn in long agent sessions is often review-round treadmills and merge-gate ceremony made of commands that succeed, so failures are not the signal. The scorer looks at the last ~120 actions and combines five signals, each ranked against reference distributions that ship in lib/spin-reference.json (so every live score uses the same 0–1 scale):

  • share of commands that are process ceremony (re-merging or rebasing on main, polling CI checks, regenerating files, lint-fix loops, review and receipt bookkeeping);
  • few new files touched;
  • the highest “round N” / “pass N” mentioned;
  • waiting per action (calls that wait on a helper agent or a still-running command); and
  • near-repeat commands (the same command with only numbers, paths, or ids changed).

The equal-weight mean is smoothed over the last three readings. Watch starts at 0.70 and alert at 0.85. Two extra rules apply: a review round of 40 or more is an alert (20 or more is a watch), and the same command five or more times back-to-back is an alert (repeated polling is reported as waiting instead). Claude Code is less calibrated and is capped at watch by default. The thresholds and reference distributions were calibrated on the author's own transcripts, so treat a finding as a prompt to look, not proof; recalibrate on your own hand-labeled sessions with scripts/spin-calibrate.js (and rebuild the reference with scripts/spin-reference.js).

The sensor is an optional hook. bin/spin-hook.js runs after each tool call (PostToolUse) inside Codex and Claude Code, even when burnboard is closed. It reads only the bytes appended to the transcript since its last run (on a first call into a very large transcript it starts from the last ~8 MB), always exits successfully, prints nothing unless it is nudging the agent, and logs its own errors to ~/.local/state/burnboard/spin/hook-errors.log. Typical runs take 50–70 ms. It never blocks or stops an agent.

It keeps its state under ~/.local/state/burnboard/spin/:

  • sessions/ — a small per-session state file (byte offset, the last ~200 compact actions, recent readings, last-notified levels);
  • events.jsonl — an append-only log of level changes, callouts, toasts, and nudges; and
  • episodes/ — the durable episode archive: one file per session with ids, repository, title or first request, parent/root ids, start/peak/end times, peak score and level, reasons, score history, a capped trail of ~120 actions (time, operation, command skeleton, outcome or first error line, file), nearby human messages (truncated), and the outcome. No full outputs are kept.

Your own callouts (“churning”, “spinning your wheels”, “going in circles”, “over and over”) are detected in your messages and recorded on the episode, which labels it “you called it out”. Instructions such as “keep churn to a minimum”, “PR churn”, and UI spinners are ignored. A callout with no episode is recorded as a miss. If you keep your own hand labels in ~/.local/state/burnboard/spin/seed-labels.json (or point BURNBOARD_SPIN_SEED_LABELS at a file), the backfill attaches them, with their notes, to the matching archived sessions; the calibration script reads the same file. Nothing is seeded without it.

Installing the agent hooks

Installing changes your Claude Code or Codex configuration, so it is a separate, explicit step. Run the installer from the burnboard checkout you intend to keep: each hook records the absolute paths of this checkout and its current Node binary. The first command in every path below is a dry run; it prints the exact JSON entry without changing anything. The --yes command makes a timestamped backup, writes the entry, and validates the resulting file. Each installed entry runs the sensor after every tool call with a five-second timeout.

Enable Spin watch for Codex
  1. From the burnboard checkout, preview and install only the Codex hook:

    node scripts/spin-install.js --only codex
    node scripts/spin-install.js --yes --only codex
    

    This adds one PostToolUse entry to ~/.codex/hooks.json. It preserves all existing hooks and does not edit ~/.codex/config.toml.

  2. Approve the exact hook definition. Start Codex in a terminal, even if you normally use Codex in Zed, VS Code, or another editor:

    codex
    

    At the Codex prompt, type /hooks. Find the new or changed PostToolUse entry from ~/.codex/hooks.json, inspect its absolute Node and spin-hook.js paths, and trust/enable it. Codex skips a new or changed non-managed hook until you do this. See the official Codex hook trust documentation. Type /quit when the hook shows as trusted.

  3. Fully restart every Codex process that should use the hook. If Codex runs inside an editor, restart the editor or its Codex host—not only the visible chat. Open a fresh Codex thread and ask it to perform one tool call, such as reading a file.

  4. Verify the Codex path:

    node server.js --spin-check-only
    

    The report should show the Codex hook installed, the Codex approval current, and Codex hook activity after that tool call. If Claude Code is installed but its hook is still missing, this command can exit non-zero even though the Codex lines are green. That is expected if you intentionally install only Codex on a machine that also has Claude Code; otherwise complete the Claude steps below.

Enable Spin watch for Claude Code
  1. From the same permanent burnboard checkout, preview and install only the Claude Code hook:

    node scripts/spin-install.js --only claude
    node scripts/spin-install.js --yes --only claude
    

    This adds one PostToolUse entry to ~/.claude/settings.json and preserves all existing settings and hooks. Claude Code does not use Codex's separate /hooks trust store.

  2. Quit and restart Claude Code so there is no ambiguity about whether the open session reloaded settings.json. Open a fresh Claude Code thread and ask it to perform one tool call, such as reading a file.

  3. Verify the Claude Code path:

    node server.js --spin-check-only
    

    The report should show the Claude Code hook installed and Claude Code hook activity after that tool call. It can still exit non-zero if Codex is installed but its hook or approval is missing.

Enable both agents in one pass

Instead of running the two --only paths, preview and install both hook entries together:

node scripts/spin-install.js
node scripts/spin-install.js --yes

Then complete Codex's /hooks approval, restart both agent hosts, make one tool call in each, and run node server.js --spin-check-only. When the full setup is healthy, the output shrinks to one Spin watch: ready line.

Enable notifications and agent nudges, not just scoring

Installing the hook starts local scoring, but it does not automatically send guidance to an agent. The default Agent nudge → Mode is shadow (log only). To deliver nudges, start burnboard, open Attention Brief → Rule controls → Spin watch settings, and set Agent nudge → Mode to nudge the agent.

With the defaults, Claude Code threads can never be nudged or notified: Claude Code at most is watch, while both Agent nudge → At and Desktop notifications → At start at alert only. Choose the behavior you want explicitly:

  • set Claude Code at most to alert to let Claude reach both alert-only channels; or
  • keep Claude capped at watch and set Agent nudge → At to watch or alert for agent nudges, Desktop notifications → At to watch or alert for Windows toasts, or both.

For actual agent nudges, Agent nudge → Mode must

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#usage · #monitor · #dashboard