npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

glassbox-trace

v0.11.1

Published

Other tools show what happened in a Claude Code session; Glassbox tells you what went wrong. Timeline, token and cost burn, auto-diagnostics with evidence and advice, session compare, live tail, a fleet view, a secrets scanner for transcripts (fence), a C

Readme

Glassbox for Claude Code

ci

Other tools show you what happened in a Claude Code session. Glassbox tells you what went wrong.

Drop a session .jsonl onto one HTML file. Get a timeline of every model call and tool call — subagents and Workflow agents included — where the tokens and money went, and a list of things a reviewer would flag — retry loops, failing tools, oversized results, context that cost you money, files every subagent re-read — each with the evidence and one line on what to do differently. Compare two sessions side by side. Watch one live while Claude Code writes it. Hand the findings back to the agent. Nothing leaves your machine, and no tokens are spent: every rule is mechanical.

Check an agent run like a test. glassbox check --fail-on warn exits 1 when a session looped, kept failing, or ran up context — so a claude -p job in CI can fail the build the way a test would (docs/CI.md).

Glassbox showing the trace of the session that built it

The demo built into the file is the trace of the session that built Glassbox, sanitised.

Why

Every Claude Code and Cowork session writes its full transcript to ~/.claude/projects/<project>/<session-id>.jsonl, with subagents in <session-id>/subagents/agent-*.jsonl and Workflow agents in <session-id>/subagents/workflows/<runId>/. The Agent SDK emits the same shapes as --output-format stream-json. Those files are the only complete record of what an agent did, and they're unreadable: one JSON object per line, assistant messages split one record per content block, usage duplicated across those records, tool calls joined to results only by id.

Agents can't see their own traces. Humans reviewing agent work can't either. Glassbox fixes both.

Use it

Fastest: npx glassbox-trace opens your newest Claude Code session in the browser.

npx glassbox-trace                    open the newest session (or `npm i -g glassbox-trace`, then `glassbox …`)
glassbox list --last 10               list sessions (id, time, size, project, title)
glassbox list --grep "npm test"       only sessions containing the text
glassbox open 81c4                    open a session by id prefix (or a .jsonl path)
glassbox open 81c4 --out trace.html   write a self-contained HTML you can send to someone
glassbox check                        print findings; exit 1 on any error-level finding
glassbox check --format md            the findings as Markdown written for the agent: evidence + what to do next time
glassbox check --fail-on warn --format json   stricter, machine-readable (CI, hooks, agents); add --redact before sharing
glassbox check --all --since 30d --redact --legend audit.legend.json --format json
                                      every session, counts only, files as keys; the legend (key → path) stays with you
glassbox reveal report.md --legend audit.legend.json   turn the keys in a report back into paths, on your machine
glassbox compare 81c4 9f0a            same task, two sessions: time, tokens, cost, tools and findings side by side
glassbox compare 81c4 9f0a --out cmp.html     …as one HTML with both sessions in it
glassbox watch                        live tail: the viewer follows the newest session as Claude Code writes it
glassbox collect ./reports --format md --out fleet.md
                                      one report from a folder of redacted check reports, one per machine
glassbox claims 81c4 --format md      said vs did: every claim the agent made about its own work, with the tool result behind it — or the gap
glassbox recall login redirect        what past sessions of this project asked, wrote, ran, committed and said about it
glassbox memory                       what the next session here will be told (hook --context), and the lessons behind it
glassbox memory audit                 everything loaded before the first prompt, its token cost, and what is dead or doubled
glassbox clean                        remove the temp files `open` and the hook leave behind

The npm package is glassbox-trace (plain glassbox was already taken); the command it installs is glassbox. Subagent transcripts next to the session are included automatically. GLASSBOX_HOME overrides ~/.claude; GLASSBOX_BROWSER names the command used to open HTML.

In CI: exit 0 clean, 1 on findings at/above --fail-on, 2 on a usage error; --format json carries glassbox (version) and schema (2 since 0.6.0: adds summary.files and evidence.files when a legend is used; schema-1 readers can ignore them); --redact blanks prompt text, tool inputs and quoted output. A GitHub Actions example for Agent SDK runs is in docs/CI.md.

Feed it back to Claude. glassbox check --format md prints the findings the way an agent needs them: each one with the concrete tool calls and request numbers it is about, and a fixed "next time" line per rule. Paste it into the next session ("here's what went wrong last time"), pipe it into a file, or let the Stop hook below deliver it automatically.

Compare two sessions. glassbox compare A B (or Compare… in the viewer) lines up the same task done twice: wall and active time, requests, tool calls and errors, context served, peak prompt, cache hit, output, cost, findings — each with the change and who did better — plus tool use side by side and the findings that appear in only one of them. Handy for "did the new CLAUDE.md help?", "Sonnet vs Opus on this job", or "before and after I fixed that hook".

Watch a session live. glassbox watch serves the viewer from 127.0.0.1 and streams the transcript to it as it grows — new tool calls land on the timeline within a second, tiles and findings update, Follow keeps the right edge on now (pan or zoom and it lets go). Loopback only; nothing leaves the machine.

Let the agent read its own recorder. glassbox hook install adds a Claude Code Stop hook (the command it writes is npx -y glassbox-trace hook …, which resolves the package on each run; pass --command glassbox after npm i -g glassbox-trace@<version> to pin it, or use the plugin below, which runs its bundled copy): every session ends with a one-screen Glassbox summary (turns, tool calls, context peak, cost, top findings). Add --feedback and the findings — with their evidence and the "next time" advice — are handed back to the agent; it reads them and says, in a sentence, what it would do differently. Each finding is handed back once per session, it never loops (stop_hook_active is respected), never blocks a clean session, and glassbox hook uninstall removes it, with a .glassbox-backup of settings.json kept.

Feedback at the end of a session can only change that session's last reply. Add --context to carry it forward: the Stop hook keeps a memory of the project in <project>/.glassbox/ — git-ignored, owner-only, secrets masked — and a SessionStart hook gives the next session there the lessons that keep coming back, a line for each recent session, and what the agent said it would do differently. See Memory across sessions below.

Stop a loop before it happens. --guard adds a PreToolUse hook: when the agent is about to repeat a call that has already failed twice in a row, unchanged, in the current turn, it blocks the call and tells the agent why, with the last error, and to change something or ask you rather than try again. It is deliberately narrow. Anything that could change the outcome in between — an edit, another command, a success, a new prompt — resets it, so re-running the tests after a fix is never blocked; calls a person stopped don't count; it never approves anything, so your permission prompts are untouched. Replayed over 4,121 real tool calls it blocked none, so it stays out of the way until an agent is actually stuck. It runs before every tool call, so it needs an installed copy: --guard writes a direct node "…/bin/glassbox.mjs" hook … command (for the Stop hook too) and refuses to install from an npx cache, where each call would cost seconds. The plugin doesn't include the guard (why); if both are installed, the plugin sees the CLI hook and steps aside.

glassbox hook install --feedback --context --fail-on warn   # summary, feedback, and notes for the next session
glassbox hook install                                       # summary only
glassbox hook uninstall

npm i -g glassbox-trace                                     # the guard needs an installed copy, not npx
glassbox hook install --feedback --context --guard          # all of the above, plus the loop guard

Or install it as a Claude Code plugin — the same hooks plus /glassbox:check and a skill Claude uses when you ask "what went wrong in this session?", running the bundled code (no npx): /plugin marketplace add aldohushi1-stack/glassbox, then /plugin install glassbox@glassbox-trace. Feedback and context are opt-in plugin options. See docs/PLUGIN.md.

Many sessions at once. glassbox check --all --since 1h checks every session written in the last hour (or --all alone for all of them), one line each, exit 1 if any fails — for CI jobs that run several claude -p tasks. --rates rates.json (or GLASSBOX_RATES) pins a team rate card for check, compare and the hook: { "claude-opus-5": { "in": 5, "out": 25, "read": 0.5, "w5m": 6.25, "w1h": 10 } }, USD per million tokens, keyed by model-id prefix.

A whole team. Each machine writes one redacted report — glassbox check --all --since 30d --redact --legend audit.legend.json --format json > <share>/<name>.json — and glassbox collect <share> turns the folder into one fleet report: totals, which sessions carried the spend, every rule with how many sessions it hit and its "next time" line, one row per source, and the keyed files that were read too many times. Counts, keys and findings only; reports that were not made with --redact are skipped. --format md --out fleet.md for the readout, --since 14d to window it. A two-week, no-hooks pilot built on this is written up in docs/PILOT.md.

glassbox clean deletes what open and the hook leave in the temp folder (viewer files with the transcript inside, hook state).

In the browser: the viewer is one HTML file — open dist/glassbox.html (double-click, no server; the CLI, compare-from-terminal and live tail need Node 18+). It shows the demo session at rest. Then either drop your .jsonl (or the whole <session-id> folder for subagent lanes), or in Chrome/Edge click Open folder…, pick ~/.claude/projects, and choose a session from the list — the folder is remembered, so next time it's Recent. Finding the file by hand: ls -t ~/.claude/projects/*/*.jsonl | head on macOS/Linux, %USERPROFILE%\.claude\projects\ on Windows.

Cowork sessions that run in the cloud keep their transcript in the cloud workspace, not on your machine, and it goes away when the session ends. Before you finish, ask Claude to copy it to a folder you've connected ("save this session's transcript to my Glassbox folder"); it can read its own ~/.claude/projects/…/<session-id>.jsonl and write it out. Cowork sessions that run locally, and all Claude Code sessions, are already where glassbox list looks.

Read top to bottom: stats → timeline (with minimap, search, fit-to-turn) → context & cost → findings → tools → turns. Click anything for detail. Every selection is a permalink (#req=17, #tool=…, #find=3, #turn=2).

Keyboard: Tab into the timeline, ←/→ previous/next call, ↑/↓ change lane, Enter opens detail, Esc closes it; + − 0 zoom, Shift+←/→ pan, / search, ? help. Touch: drag to pan, pinch to zoom.

Findings → Copy / Copy all / Export report give you Markdown to paste into an issue or back into the agent — the exported report is the same agent-ready format as check --format md. Compare… loads a second session next to this one; Swap puts it on the timeline.

Share mode blanks every prompt, tool input, result and assistant text in the view; Export redacted downloads a structure-only .jsonl that keeps timestamps, usage and tool names — safe to post publicly.

Accessibility: WCAG 2.2 AA contrast in both themes, full keyboard operation with roving focus on the timeline and chart, screen-reader names on every span and row, live announcements on load and search, focus-managed detail panel, reduced-motion respected. npm run audit re-checks all of it with axe-core and fails the build on regressions.

Secrets in transcripts — glassbox fence

Every session transcript is plain text, and everything the agent read is in it: the .env it opened to find a port, the token git remote -v printed, the key you pasted. fence scans them and tells you what is there — never the value itself:

glassbox fence                         every session under ~/.claude — exit 1 if a credential was found
glassbox fence 81c4cbfd                one session (and its subagents)
glassbox fence ./archive               every .jsonl under a folder
glassbox fence --format md --out fence.md
glassbox fence --shred                 overwrite each value in place with [FENCED:<rule>:<fingerprint>]
glassbox fence --sessions-only         transcripts only (the default sweep also covers prompt history, paste cache, file history, debug logs, shell snapshots)
glassbox fence --key team.key          one shared fingerprint key for a fleet
Glassbox fence · 34 sessions under /home/aldo/.claude/projects · 212 MB
  3 error · 1 warn · 2 info · 3 distinct secrets in 2 of 41 files

  /home/aldo/.claude/projects/-home-aldo-api/7c1e…jsonl
    ERROR anthropic-key   line   212  sk-a…oP (62 chars)  ×2  — tool result · Read /home/aldo/api/.env
    ERROR github-token    line   340  ghp_…r8 (40 chars)      — tool input · Bash
    INFO  credential-file-read line 211  /home/aldo/api/.env  — tool input · Read

Each row is a masked preview and a fingerprint (first 8 hex of HMAC-SHA256 under a key that stays on the machine, so even a weak password's fingerprint can't be guessed against) — enough to know which key it is and to see the same key across sessions, never enough to use it. A sweep of the whole home also covers the other places Claude Code keeps text: prompt history, the paste cache, file-history snapshots, debug logs and shell snapshots. error is a credential whose format identifies it (AWS, GitHub, Anthropic, OpenAI, Slack, Stripe, Google, npm, SendGrid, a private key block, a database URL with its password); warn is a secret named by its context (password=, api_key:, Bearer …, a URL with credentials, a JWT), kept only when the value has the entropy of a real one and is not a placeholder; info is a read of a credential file (.env, .npmrc, .netrc, ~/.aws/credentials, id_rsa, *.pem …) whose contents are now in the transcript whether or not a rule recognised them. A secret that reached a transcript reached a disk, and whatever backs that disk up: rotate it, then --shred. Shredded transcripts still open and check. It verifies nothing against any provider (no network), and a password in prose with no context word passes through — it is a net, not a guarantee. Details in docs/FENCE.md.

Is my CLAUDE.md doing anything? — glassbox adhere

Every rule in the project's instruction files, judged against every session of that project, per occasion, with evidence:

glassbox adhere                        the project in the current folder
glassbox adhere --project ~/code/api --since 30d --format md --out adhere.md
glassbox adhere --fail-under 80        exit 1 below that rate
Glassbox adhere · /home/aldo/api
  11 rules · 9 checkable · 2 not checkable yet · 34 sessions · obeyed 212 of 301 occasions (70%)

  IGNORED        prefer-tool       0/38   0%  Use rg rather than grep.  (CLAUDE.md:11)
                   ↳ 535876c9 t3  "Continue from where you left off."  →  grep -n "^export" src/cli.mjs | sed -n 1,80p
  IGNORED        ask-before        0/1    0%  Ask before committing.  (CLAUDE.md:7)
  OBEYED         never-touch       8/8  100%  Never edit files in dist/ by hand.  (CLAUDE.md:5)

Nine rule shapes are checkable from tool calls — run X before commit/push, run X after changes, use A not B, never run, never touch, ask before, read before edit, commit message format, no new docs — and everything else is listed as not checkable yet with its line number, so the report never claims more than it measured. Commands are judged on their shell surface (a git push --force inside a document being written is not a force push). The first real run, on the session that built it, scored 22%. Details and the honest caveats in docs/ADHERE.md.

Said vs did — glassbox claims

Every sentence in which the agent told you what it did — "all 76 tests pass", "committed as 753be02", "live on npm", "nothing changed" — matched to the tool result that should be standing behind it, or to the gap where one should be:

glassbox claims                        the newest session (subagents included)
glassbox claims 81c4 --format md --out claims.md
glassbox claims --fail-on unverified   exit 1 on any claim without a receipt (default: contradicted only)
Glassbox claims · 38f81247
  69 claims · 61 verified · 7 declared · 1 unverified · 0 contradicted

  UNVERIFIED   test     t23  Your folder is as I left it: `master` is GitHub's `main` plus the loop guard and Action commit,…
               ↳ no test, build, validate or CI result in the window
  VERIFIED     test     t3   58 of 58 pass.
               ↳ 58 passed, 0 failed (1 call)
  VERIFIED     ship     t4   I committed it as `753be02` on branch `wait-aware-findings`: 6 files, 117 lines added and 6 rem…
               ↳ ship result in the window (1 call)
  DECLARED     declared t3   Not verified: the browser e2e test (`test/browser.e2e.mjs`) didn't run because Playwright isn't…
               ↳ the agent said so

Six kinds of claim (tests pass, shipped, verified, fixed, nothing changed, file written), judged on the same agent's tool calls in that turn: a test claim needs a test run after the last edit — from Bash, PowerShell or Cowork's device_bash — with its counts read and compared; a shipped claim needs the commit, push, publish or upload result, carrying the sha or version the sentence names; "nothing changed" needs a git status after the thing that could have changed it. An agent that says "not verified" gets a declared row and no finding. The same ledger runs inside check as three rules — contradicted-claim (error), unverified-claim (warn), stale-claim (info) — so the Stop hook hands the sentence back to the agent that wrote it. On sixteen real sessions (367 claims; three of them checked by hand first) the ledger found one unverified sentence — "the tests still pass", 24 minutes after the last run — five fixes never re-run after their edit, and no contradictions. A verdict is about the sentence, never the code. Details in docs/CLAIMS.md.

Memory across sessions — glassbox recall and glassbox memory

A Claude Code session starts knowing nothing about the last one, and Claude Code deletes transcripts after 30 days by default. With --context (or the plugin's context option), the Stop hook keeps <project>/.glassbox/memory.json: a digest of each of the project's last 50 sessions — what was asked, the files written, the checks and pushes that ran and how they ended, the commits with their shas, the agent's last words, the findings — and lessons: findings counted across sessions by what they are about (retry-loop · Bash npm test, failed-tool · Edit, unverified-claim · test). The next session starts with this note (≤ 8,000 characters, under Claude Code's 10,000 cap):

## Recurring in this project (worst first)

- retry-loop · Bash npm test — in 3 of the last 12 sessions, last 2026-10-09: Bash called 3× with identical input, e.g. `npm test -- auth`. Next time: When a call fails, change something before calling again: …

## Recent sessions (newest first)

- 2026-10-09 14:02 · a1b2c3d4 · "fix the login redirect" — wrote src/auth.js, test/auth.test.js · ran npm test (passed, last of 3) · committed 1a2b3c4 "fix: login redirect loop" · pushed

A lesson is handed on until ten sessions in a row go by without it, then it retires (and comes back if it fires again). Each session that started with a lesson is counted, so glassbox memory can say what nobody could before: told in 9 sessions, came back in 1. Everything is copied or counted from the transcripts — no model call, no tokens — and whatever a fence detector recognises as a secret is masked before it is written.

glassbox recall login redirect        sessions of this project that mention it, best match first: asked / said / wrote / ran / commit
glassbox recall "dark mode" --since 30d --format md      a quoted phrase is one term; --format md for pasting to an agent
glassbox recall                       no words: the latest sessions, one line each
glassbox memory                       what the next session will be told, and every lesson: sessions, told, came back, quiet
glassbox memory forget retry-loop     drop a lesson (by rule or key); it starts over if it fires again
glassbox memory clear                 delete the project's memory
glassbox memory audit                 everything loaded before the first prompt, and what it costs

recall works without the hook: it reads the project's transcripts still on disk, and the ledger supplies the sessions whose transcripts are gone. Every word must match; a word that isn't in a transcript's raw text skips parsing it. The plugin's skill tells Claude to run it before re-investigating something a past session may already have settled.

glassbox memory audit lists what Claude Code loads into every session before the first prompt — managed, user, parent-directory and project CLAUDE.md files, CLAUDE.local.md, unscoped .claude/rules/, @imports (four hops, relative to the importing file), the first 200 lines or 25 KB of the auto-memory MEMORY.md, and Glassbox's own note — with an estimated token cost (characters ÷ 4, HTML comments stripped as Claude Code strips them), then flags what a mechanical reader can: imports that load nothing, backticked paths and npm run scripts that don't exist, the same line in two places, rules that pull opposite ways (use pnpm here, use npm, not pnpm there — the same parser as adhere), files over the 200 lines Claude Code's docs recommend, and MEMORY.md lines past the cut-off that never load. --fail-on warn for CI. Details in docs/MEMORY.md.

What it flags

| rule | fires when | |---|---| | context-bloat | prompt size ≥ 120k tokens (error at 170k), with the request that first crossed it and the dollars spent on requests above it | | retry-loop | same tool with identical input ≥ 3× in one turn, returning the same result with nothing changed in between (error if ≥ 2 failed, whatever the results) | | failed-tool | a tool fails ≥ 2 times and ≥ 20% of its calls (error at ≥ 50% of ≥ 3); denied or interrupted calls don't count | | duplicate-subagent-read | the same file read by ≥ 3 agents, each paying for it in its own context | | oversized-result | a tool result ≥ 20k chars (error at 60k); one line per tool when it happens ≥ 3 times | | orphan-tool | a tool call with no result (abort, crash, or still running) | | exploration-run | ≥ 8 read-only calls in a row with no write, exec or MCP action (warn at 15) | | image-heavy | screenshots / image reads totalling ≥ 0.5 MB (warn at 2 MB) — they're tokens on every later request | | cache-churn | a request read back ≥ 20k fewer cached tokens than the previous one had cached — something early in the prompt changed | | idle-cache-expiry | the same kind of miss after a gap longer than the cache lifetime (5 min or 1 h) | | low-cache-hit | < 50% of input served from cache over ≥ 5 requests | | slow-model | ≥ 60 s for a response under 1,500 tokens (latency / rate limit / stall) | | long-generation | ≥ 60 s for a big response streamed below 15 tok/s | | missing-final-usage | subagent responses whose final usage record never reached the transcript — the cost shown is a floor, with an estimate of the gap (info; a Claude Code bug, #93620, not the agent's doing) | | slow-tool | a tool call ≥ 60 s (warn at 5 min); one line per tool when repeated; blocking TaskOutput waits roll up per background task as info; time spent on the human (questions, permission prompts) is excluded | | permission-denied | tool calls the human rejected, a permission rule or auto mode blocked, or an interrupt stopped (info) | | max-tokens, api-error, hook-error, compaction, thinking-heavy, subagent-share, long-turn | what they say (long-turn: ≥ 30 tool calls after one prompt in the main conversation) | | contradicted-claim, unverified-claim, stale-claim | the agent told the human something the transcript contradicts (error), has no receipt for (warn), or checked before its last edit / only partly (info) — see glassbox claims above |

Identical findings print once with a ×N count in check. All mechanical, no AI. The thresholds were tuned on a corpus of 33 real sessions (481 findings → 142, median 2 per session); node scripts/corpus-audit.mjs re-runs that audit on your own sessions and prints counts only. Thresholds are in TraceCore.DEFAULTS and can be overridden when calling diagnose(trace, opts). Every rule has a one-line "next time" in TraceCore.ADVICE, which is what the Markdown report and the Stop hook hand back to the agent.

Token and cost accounting

  • Usage is counted once per API request (assistant records sharing a requestId), not once per record. Subagent transcripts rewrite output_tokens while a response streams, so the largest value across the request's records is used. Since Claude Code ~2.1.278 many subagent responses never get their final record written at all (every record has stop_reason: null and a partial count — anthropics/claude-code#93620); those output tokens are not on disk anywhere, so Glassbox counts the responses, shows the cost as ≥ $X (a floor) and estimates the gap from the median of the session's own complete subagent tool-use responses (needs five). Compare with Claude Code's own total (/cost, the status line) before budgeting from a floor.
  • Context size = uncached input + cache read + cache write — the prompt the model actually saw.
  • Thinking tokens are part of output tokens; shown as a share, never added twice.
  • Cost is estimated from an editable rate card (defaults from the Claude pricing page, 2026-09-05; prefix-matched so dated model ids resolve). A stream-json result record with total_cost_usd overrides the estimate. Unknown models show "—" rather than a wrong number.

Formats

Claude Code transcripts (main + subagents + meta.json), Agent SDK / claude -p --output-format stream-json output, and plain Messages-API [{role, content}] arrays. Malformed lines are reported and skipped, never fatal.

Develop

npm test          # unit tests (node:test) — parser, every diagnostic rule, cost, redaction, report, compare, tailer + SSE server, CLI, real fixtures
npm run build     # dist/glassbox.html (standalone) + dist/glassbox.artifact.html (fragment)
npm run e2e       # Playwright: demo in light+dark, tiles vs core, keyboard nav, drawer focus, search, clipboard, permalinks, compare, live tail
npm run audit     # axe-core + contrast + keyboard reachability + responsive + 16 MB stress run; fails on regressions

Layout:

src/trace-core.js     pure engine: parseTrace · diagnose · estimateCost · redact  (no DOM, no deps)
src/viewer.html       the UI; the build inlines trace-core and the demo
src/cli.mjs           CLI library (session discovery, embed, check, compare, hook); bin/glassbox.mjs is the entry point
src/tail.mjs          live tail: byte-offset tailer + loopback SSE server for `glassbox watch`
src/guard.mjs         the PreToolUse loop guard (`hook --guard`)
src/claims.mjs        said vs did: claims out of the agent's text, judged against the tool calls (`claims`, and three `check` rules)
scripts/build.mjs     build
scripts/sanitize.mjs  turn a real transcript into a shareable fixture (demo or structure mode)
scripts/corpus-audit.mjs  run every rule over your local sessions; counts only (--baseline to diff two runs)
test/                 unit, e2e and audit harnesses, fixtures
DESIGN.md             design doc — data model, rules, thresholds, UI, privacy
STUDY.md              accessibility & ease-of-use study that drove v0.2
STUDY-IMPLEMENTATION.md  adoption study (solo dev, Cowork/SDK, CI, feedback loop) that drove v0.4.1
docs/                 CI recipe, plugin, feedback-loop study protocol, launch kit, Community Extensions PR, post copy
scripts/feedback-study.mjs      measures with/without --feedback session groups
scripts/feedback-study-run.mjs  runs that study with `claude -p` (plan only unless --run)
.claude-plugin/ hooks/ skills/  the Claude Code plugin: manifest + marketplace, Stop/SessionStart hook, skills

Use the engine on its own:

const { parseTrace, diagnose, estimateCost, reportMarkdown, compare } = require('./src/trace-core.js');
const trace = parseTrace([{ name: 'session.jsonl', text: fs.readFileSync(p, 'utf8') }]);
const findings = diagnose(trace), cost = estimateCost(trace);
console.log(trace.totals, findings, cost.total);
console.log(reportMarkdown(trace, findings, cost));          // the agent-ready report
console.log(compare({ trace, findings, cost }, other));      // other = the same three for a second session

Privacy

Your context is private — by construction, not by promise.

  • Nothing leaves. The viewer makes no network requests at all — fonts, scripts and the demo are inside the one file, and the test suite fails if a build references anything outside it. The CLI sends nothing anywhere. glassbox watch binds to 127.0.0.1 only and stops with the command. The one network activity is installation: npx fetching the package, or the plugin marketplace fetching this repo.
  • What it touches. It reads ~/.claude/projects/** and writes only what you ask for: open writes a self-contained HTML to your temp folder (transcript included — delete it when done, or use --out), hook install edits ~/.claude/settings.json with a backup beside it, --context writes <project>/.glassbox/last-session.md and memory.json (owner-only, git-ignored, secrets masked; they quote prompts and commands), --legend writes the legend. The full inventory — files, processes, hooks, network, uninstall — is in docs/IT.md, written for whoever has to approve it.
  • Counts, not text. Transcripts contain everything the agent saw; that's why share mode and --redact exist. Redacted output keeps tool names, numbers, timings and cost and drops every string — prompts, commands, results, titles. Where a finding would quote something it says «240 chars».
  • What is already on disk. glassbox fence finds credentials that reached a transcript (known key formats, secrets named by context, credential-file reads), reports them masked and fingerprinted, and --shred overwrites them in place. See above.
  • The shape, not the names. A redacted report still needs to say "this one file was read 48 times and 6 of those failed". check --redact --legend audit.legend.json replaces every path with a keyed hash (file:b94b1a35, HMAC-SHA256 with a random salt) and writes the key → path map to the legend file, which stays on your machine. The redacted JSON carries summary.files (reads, writes, failures, agents, chars per key) and evidence.files on findings; duplicate-subagent-read keeps its sentence with the key in it. glassbox reveal report.md --legend audit.legend.json turns the keys back into paths for you. Re-using the legend keeps keys stable across runs; two machines with two legends produce different keys for the same file. Treat the legend like a password file: local, git-ignored, never attached to the same email as the report. Design notes in DESIGN.md §12.

Source: github.com/aldohushi1-stack/glassbox · MIT © Aldo Hushi, Adelaide · npm: glassbox-trace · Claude Code cost audit

Security

Found a way Glassbox could leak, run something it shouldn't, or be tampered with? Please report it privately — see SECURITY.md.