Visualize AI context & traces.
41
stars
68
commits
TypeScript
primary language
Sep 6, 2026
updated
Quickstart | AI SDK DevTools | Viewer | For Agents | Skills | Trace Formats
unbox-ai turns an AI agent trace into something you can read. One command opens a local visualization of the run; the same binary doubles as a bounded, read-only trace explorer for coding agents.
--json, no accidental servers.npx unbox-ai trace.json
Agent traces are unreadable raw. Every generation resends the full context, so a 16-generation trace holds hundreds of duplicated messages, and in a typical run ~90% of input tokens are the system prompt and tool definitions, paid again on every request. unbox-ai makes that visible.
npx unbox-ai trace.json
That's it. A local server starts and your browser opens the viewer. Works with gateway exports, opencode session exports, and AI SDK devtools databases (see Trace Formats).
--json machine-readable output
--by <key> summary aggregation: model | agent | segment
--port <n> server port (view default 4177, devtools default 4983)
--no-open start the server without opening a browser
unbox-ai devtools is a drop-in replacement for the
@ai-sdk/devtools viewer:
same capture setup, this viewer instead. Instrument your app exactly as the
AI SDK documents it:
import { registerTelemetry } from "ai";
import { DevToolsTelemetry } from "@ai-sdk/devtools";
registerTelemetry(DevToolsTelemetry());
Then, instead of npx @ai-sdk/devtools, run:
npx unbox-ai devtools
Every generateText / streamText call streams into the viewer live - token
treemap, cache-hit attribution, latency waterfall, and diffed messages update
as your agent runs. Every run gets its own entry in the sidebar run list, with
nested agent runs (tools that call the AI SDK again) indented under their
parent; the viewer follows the newest run until you pin an older one, and
concurrent streams stay individually visible. The static commands work on the
database file too: unbox-ai summary .devtools/generations.json.
The run list is not devtools-only - unbox-ai view a.trace.json b.trace.json
opens several trace files (any mix of formats) as one run list.
unbox-ai view a.json b.json opens one tab per file; the
sidebar run list scopes to the active tab. Tabs close (x), and the + button
or dropping a .json anywhere opens more traces without restarting the
server.Token attribution is estimated (character-proportional, scaled to the reported per-generation totals) and labeled as such.
The same binary is a bounded, read-only trace explorer - safe to allowlist:
unbox-ai runs trace.json # multi-run sources: one line per run, then scope with --run
unbox-ai summary trace.json # totals + one line per generation
unbox-ai summary trace.json --by model # totals grouped by model
unbox-ai events trace.json # table: tokens, latency, cost, tool calls
unbox-ai event trace.json 5 # one generation, new messages only
unbox-ai tools trace.json # every tool call: status, time, size, args
unbox-ai messages trace.json --grep "error" --role assistant --limit 10
unbox-ai get trace.json 'events[5].messages[10].tool_calls[0]'
unbox-ai compare a.json b.json # A/B two runs: metric deltas + system prompt / tool diff
compare is built for prompt and model A/B: it prints token / cost / time /
cache deltas, a diff of the task (differing tasks make every delta
misleading), per-tool usage deltas (which tools each run leaned on), then a
line diff of the system prompt and the tool-set changes - added / removed
names plus, per changed tool, what changed (description or schema) and the
definition diff ("what changed and what did it buy"). Add
--trajectory for a content-aligned action table (LCS over tool sequences,
so an extra step in one run offsets nothing) that marks exactly which steps
differ. Two runs of one file: unbox-ai compare db.json --run 0 --run 1. The viewer has the same thing interactively: a compare button
(2+ runs) opens a side-by-side trajectory where each aligned generation
expands into both runs' messages.
In the viewer, copy for agent (header, top right) copies the exact
summary command for the run on screen - paste it into your agent to hand
over what you're looking at.
Every command caps its output; truncations print the exact get invocation
that returns the rest. --json gives machine-readable output. When stdout is
not a TTY, bare unbox-ai trace.json prints the summary instead of starting a
server, so agents never spawn one by accident.
An agent skill ships in skills/unbox-ai/ with the
full workflow and analysis recipes. Install it into your agent (Claude Code and
friends) via the skills CLI:
npx skills add tester-army/unbox-ai -g
Or copy skills/unbox-ai/ into your agent's skills directory manually
(e.g. ~/.claude/skills/unbox-ai/). Prefer zero setup? Drop this in your
AGENTS.md:
To inspect AI trace files, use `npx unbox-ai` (read-only, bounded output):
`unbox-ai summary <trace>`, then `unbox-ai event <trace> <idx>` to drill in,
`unbox-ai messages <trace> --grep <re>` to search, and the printed `get`
pointers to fetch full values.
events[] of generation entries
carrying model, metrics (latency, tokens, cost), available_tools, and
cumulative messages snapshots. Conversation resets and multi-agent
interleaving are detected and shown as segments.{info, messages[{info, parts}]}) - adapted
automatically. Real cache read/write tokens and per-tool execution times
carry over. Note: opencode exports omit the system prompt and tool
definitions, so token attribution assigns their weight to the conversation.{runs[], steps[]},
.devtools/generations.json written by @ai-sdk/devtools) - adapted
automatically, and served live by unbox-ai devtools. Cache-read tokens
carry over; the AI SDK reports no cost or TTFT, so those show as zero/absent.
Tool definitions arrive without their JSON schemas, so the treemap's tools
group reflects names and descriptions only.There is no universal AI-trace standard yet; the closest are the OpenTelemetry
GenAI semantic conventions, OpenInference, and OpenLLMetry (all span-based).
Adapters for those are welcome contributions: implement TraceAdapter
(detect + adapt) in src/core/adapters/<name>.ts and register it in
src/core/adapters/index.ts - src/core/adapters/opencode.ts is the
reference. unbox-ai summary prints which format was detected.
PRs welcome, especially trace-format adapters. The published CLI runs on Node >=18; developing and releasing need Node >=22.21 (what CI uses). To develop locally:
npm install
UNBOX_TRACE=path/to/trace.json npm run dev # viewer with live reload
npm run build # dist/viewer + dist/cli
node dist/cli/index.js summary path/to/trace.json
npm run check # lint (biome) + typecheck + tests (vitest)
npm run release (from main, clean tree) runs release-it: version inferred from conventional commits, CHANGELOG.md updated, git tag + GitHub release + npm publish. The GitHub token comes from gh auth token (or a GITHUB_TOKEN you export); npm needs npm login once. Preview with npm run release -- --dry-run --ci.
MIT
Built with ❤️ by TesterArmy
67 commits
1 commits
TypeScript
92.2%
CSS
7.7%
Visualize AI context & traces.
41
stars
68
commits
TypeScript
primary language
Sep 6, 2026
updated
Quickstart | AI SDK DevTools | Viewer | For Agents | Skills | Trace Formats
unbox-ai turns an AI agent trace into something you can read. One command opens a local visualization of the run; the same binary doubles as a bounded, read-only trace explorer for coding agents.
--json, no accidental servers.npx unbox-ai trace.json
Agent traces are unreadable raw. Every generation resends the full context, so a 16-generation trace holds hundreds of duplicated messages, and in a typical run ~90% of input tokens are the system prompt and tool definitions, paid again on every request. unbox-ai makes that visible.
npx unbox-ai trace.json
That's it. A local server starts and your browser opens the viewer. Works with gateway exports, opencode session exports, and AI SDK devtools databases (see Trace Formats).
--json machine-readable output
--by <key> summary aggregation: model | agent | segment
--port <n> server port (view default 4177, devtools default 4983)
--no-open start the server without opening a browser
unbox-ai devtools is a drop-in replacement for the
@ai-sdk/devtools viewer:
same capture setup, this viewer instead. Instrument your app exactly as the
AI SDK documents it:
import { registerTelemetry } from "ai";
import { DevToolsTelemetry } from "@ai-sdk/devtools";
registerTelemetry(DevToolsTelemetry());
Then, instead of npx @ai-sdk/devtools, run:
npx unbox-ai devtools
Every generateText / streamText call streams into the viewer live - token
treemap, cache-hit attribution, latency waterfall, and diffed messages update
as your agent runs. Every run gets its own entry in the sidebar run list, with
nested agent runs (tools that call the AI SDK again) indented under their
parent; the viewer follows the newest run until you pin an older one, and
concurrent streams stay individually visible. The static commands work on the
database file too: unbox-ai summary .devtools/generations.json.
The run list is not devtools-only - unbox-ai view a.trace.json b.trace.json
opens several trace files (any mix of formats) as one run list.
unbox-ai view a.json b.json opens one tab per file; the
sidebar run list scopes to the active tab. Tabs close (x), and the + button
or dropping a .json anywhere opens more traces without restarting the
server.Token attribution is estimated (character-proportional, scaled to the reported per-generation totals) and labeled as such.
The same binary is a bounded, read-only trace explorer - safe to allowlist:
unbox-ai runs trace.json # multi-run sources: one line per run, then scope with --run
unbox-ai summary trace.json # totals + one line per generation
unbox-ai summary trace.json --by model # totals grouped by model
unbox-ai events trace.json # table: tokens, latency, cost, tool calls
unbox-ai event trace.json 5 # one generation, new messages only
unbox-ai tools trace.json # every tool call: status, time, size, args
unbox-ai messages trace.json --grep "error" --role assistant --limit 10
unbox-ai get trace.json 'events[5].messages[10].tool_calls[0]'
unbox-ai compare a.json b.json # A/B two runs: metric deltas + system prompt / tool diff
compare is built for prompt and model A/B: it prints token / cost / time /
cache deltas, a diff of the task (differing tasks make every delta
misleading), per-tool usage deltas (which tools each run leaned on), then a
line diff of the system prompt and the tool-set changes - added / removed
names plus, per changed tool, what changed (description or schema) and the
definition diff ("what changed and what did it buy"). Add
--trajectory for a content-aligned action table (LCS over tool sequences,
so an extra step in one run offsets nothing) that marks exactly which steps
differ. Two runs of one file: unbox-ai compare db.json --run 0 --run 1. The viewer has the same thing interactively: a compare button
(2+ runs) opens a side-by-side trajectory where each aligned generation
expands into both runs' messages.
In the viewer, copy for agent (header, top right) copies the exact
summary command for the run on screen - paste it into your agent to hand
over what you're looking at.
Every command caps its output; truncations print the exact get invocation
that returns the rest. --json gives machine-readable output. When stdout is
not a TTY, bare unbox-ai trace.json prints the summary instead of starting a
server, so agents never spawn one by accident.
An agent skill ships in skills/unbox-ai/ with the
full workflow and analysis recipes. Install it into your agent (Claude Code and
friends) via the skills CLI:
npx skills add tester-army/unbox-ai -g
Or copy skills/unbox-ai/ into your agent's skills directory manually
(e.g. ~/.claude/skills/unbox-ai/). Prefer zero setup? Drop this in your
AGENTS.md:
To inspect AI trace files, use `npx unbox-ai` (read-only, bounded output):
`unbox-ai summary <trace>`, then `unbox-ai event <trace> <idx>` to drill in,
`unbox-ai messages <trace> --grep <re>` to search, and the printed `get`
pointers to fetch full values.
events[] of generation entries
carrying model, metrics (latency, tokens, cost), available_tools, and
cumulative messages snapshots. Conversation resets and multi-agent
interleaving are detected and shown as segments.{info, messages[{info, parts}]}) - adapted
automatically. Real cache read/write tokens and per-tool execution times
carry over. Note: opencode exports omit the system prompt and tool
definitions, so token attribution assigns their weight to the conversation.{runs[], steps[]},
.devtools/generations.json written by @ai-sdk/devtools) - adapted
automatically, and served live by unbox-ai devtools. Cache-read tokens
carry over; the AI SDK reports no cost or TTFT, so those show as zero/absent.
Tool definitions arrive without their JSON schemas, so the treemap's tools
group reflects names and descriptions only.There is no universal AI-trace standard yet; the closest are the OpenTelemetry
GenAI semantic conventions, OpenInference, and OpenLLMetry (all span-based).
Adapters for those are welcome contributions: implement TraceAdapter
(detect + adapt) in src/core/adapters/<name>.ts and register it in
src/core/adapters/index.ts - src/core/adapters/opencode.ts is the
reference. unbox-ai summary prints which format was detected.
PRs welcome, especially trace-format adapters. The published CLI runs on Node >=18; developing and releasing need Node >=22.21 (what CI uses). To develop locally:
npm install
UNBOX_TRACE=path/to/trace.json npm run dev # viewer with live reload
npm run build # dist/viewer + dist/cli
node dist/cli/index.js summary path/to/trace.json
npm run check # lint (biome) + typecheck + tests (vitest)
npm run release (from main, clean tree) runs release-it: version inferred from conventional commits, CHANGELOG.md updated, git tag + GitHub release + npm publish. The GitHub token comes from gh auth token (or a GITHUB_TOKEN you export); npm needs npm login once. Preview with npm run release -- --dry-run --ci.
MIT
Built with ❤️ by TesterArmy
67 commits
1 commits
TypeScript
92.2%
CSS
7.7%