Skip to content
Mark-LifePublic

About

Local, loopback-only inspector for Claude Code, Codex, Pi and OpenCode sessions: context-budget forensics, stats and Claude memory.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

Peektrace

See what your coding agent actually put in its context window.

Peektrace reads the sessions and memories that Claude Code, Codex, Pi and OpenCode scatter across your disk, and shows you where the tokens went: what the model was carrying at peak, when a session crossed into the dumb zone, which tool calls failed, and how much wall-clock time went to waiting.

It runs on 127.0.0.1, reads your files, and sends nothing anywhere.

Session context-budget forensics

curl -fsSL https://raw.githubusercontent.com/Mark-Life/peektrace/main/scripts/install.sh | sh
peektrace serve

# or, if you have Node
npx peektrace serve

Use

Install

The native installer pulls a prebuilt standalone binary from GitHub Releases with the inspector embedded, verifies its SHA-256, and needs no Node and no build step:

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/Mark-Life/peektrace/main/scripts/install.sh | sh
# Windows (PowerShell)
irm https://raw.githubusercontent.com/Mark-Life/peektrace/main/scripts/install.ps1 | iex

It installs to ~/.local/bin (macOS/Linux) or %LOCALAPPDATA%\peektrace\bin (Windows) and prints PATH guidance if needed. Pin a version with PEEKTRACE_VERSION=cli-v1.2.3 ($env:PEEKTRACE_VERSION on Windows); PEEKTRACE_INSTALL_DIR overrides the target directory. Later, peektrace upgrade replaces the binary in place, and peektrace upgrade --check only reports whether a newer release exists.

Binaries cover macOS (arm64, x64), Linux (x64, arm64) and Windows (x64). The Linux builds link glibc — on musl (Alpine) or anything else, build from source.

From npm

With Node already installed, npx runs the same binary without installing anything:

npx peektrace serve

npm install -g peektrace puts it on your PATH instead. Either way you get the peektrace wrapper, which pulls only the prebuilt binary matching your platform and skips the other four.

Update it with npm rather than peektrace upgrade. The upgrade command replaces the binary where it stands, which under npm means inside node_modules, and the next install undoes it.

CI publishes these packages with npm trusted publishing, so each one carries a provenance attestation tying the tarball to the commit and workflow that built it. Check yours with npm audit signatures.

If you see "could not locate a platform binary", your platform has no prebuilt binary: reinstall, or build from source. To run an explicit binary, set PEEKTRACE_BIN_PATH=/path/to/peektrace (on Windows, $env:PEEKTRACE_BIN_PATH pointing at peektrace.exe).

There is no desktop download yet. Anything claiming otherwise under the name peektrace is not published by this project.

Two front ends

peektrace serve starts the loopback server and opens the web app.

peektrace tui does the same but drives a terminal UI, with the web app served alongside it on the same port. Pass --no-open to skip the browser.

Terminal UI

Both read the same data through the same in-process core, so you can switch between them mid-investigation.

On a headless box, tunnel over SSH. Run peektrace serve --no-open on the box (loopback, no token needed) and forward the same port: ssh -N -L 4321:127.0.0.1:4321 user@host.

Direct network access is the second choice. peektrace serve --host 0.0.0.0 needs a token (printed in the URL) and is read-only unless you pass --allow-write. It is plain HTTP, so use a private network or a tunnel. The default is loopback only.

Sessions

Browse Claude, Codex, Pi and OpenCode sessions in the web app, filter by agent, then open one for the full context-budget breakdown: peak context against the window, the partition at peak including the hidden thinking band, a growth timeline marking the dumb-zone crossing and every compaction cliff, the artifacts injected on each turn, and searchable history.

Context growth timeline and loaded artifacts

Codex reports its context window authoritatively; for Claude it is inferred, and subagents fold into their parent session. History reads either as a table or as a chat, with per-turn context and inline diffs.

Transcript as a chat

Transcripts are secret-redacted by default. The reveal toggle is deliberate and per-session.

Stats

Rank what fails and what costs time across every session on the machine, not one at a time. Findings come sorted by cheapest fix first — one run caught 561 of 603 lint invocations piping into head, so the exit code belonged to the pipe and every failure read as a pass.

Flagged findings across every session

Named causes lead: an unquoted --include=*.ts that zsh aborted, a pkill -f that killed its own shell, a missing binary, a harness-blocked sleep. Each one counts the retries it caused (a failed call followed by a similar call that worked), the seconds and context tokens those retries re-read, and carries a one-line fix. When CLAUDE.md / AGENTS.md already states the rule and the cause still fires, it says so and names an env or prompt-level change instead of another memory line.

Avoidable retries with rule checks

Subagent and workflow-agent transcripts count their own model calls, so their tokens, cost and retries are measured rather than read as zero. Reports from earlier versions showed their cost as about $0.

Underneath sit shell time by job type, error signatures grouped by shape, and a waiting panel that separates real work from parked polling.

Waiting and error clusters

Command text, error signatures and cluster labels are redacted before they are stored or shown. Every number ships with its caveats.

"Copy prompt", on the page and on each open row, hands an agent a short investigation prompt: the goal, that row's numbers, sample calls by transcript path and tool-use id, and the commands that pull more. stats prompt prints the same text in a terminal.

peektrace stats [--days 60] [--agent claude|codex|pi|opencode|all] [--limit 20]
peektrace stats refresh [--force]        # rescan and rebuild the cache
peektrace stats drill --fail <key>       # expand one row
peektrace stats drill --cause <id>       # failed → retry pairs behind a cause
peektrace stats prompt [--cause <id> | --fail <key> | --time <job>]  # agent prompt
peektrace stats usage [--by day|month|block] [--days N] [--tz IANA]  # tokens and cost over time

Memory

View, create, edit and delete Claude Code memories across all projects, with per-project drill-in. Alongside the CRUD sits the forensic surface: a MEMORY.md budget gauge against the 200-line / 25 KB cliff with below-fold entries flagged INVISIBLE TO CLAUDE, a type donut, an index ↔ files diff that catches orphans, and a [[wikilink]] graph.

Memory across projects

Writes go back to disk atomically — temp file plus rename, compare-and-swap on mtime.

Capabilities

A feature × agent matrix for Claude, Codex, Pi and OpenCode. Click a cell to see why a capability is supported, partial, planned or unsupported. In the web app, session browsing is live for all four. Context debugging is full on Claude and partial on Codex, Pi and OpenCode. Memory tooling is Claude-only. Open the matrix from Settings in the web app. The terminal UI keeps its own Capabilities screen.

Scripting

The same binary exposes one-shot commands, in-process or --remote <url> against a running server. Root flags go before the subcommand: --json (raw JSON instead of tables), --pretty (aligned instead of tab-separated), --read-only (refuse mutating commands), --remote <url>, --otel, --no-telemetry. --json and --read-only also work after the subcommand on sessions, memory and stats (not stats prompt). Put --remote before the subcommand.

peektrace sessions ls [--agent <id>] [--project <name>] [--since <when>] [--cwd <path>] [--limit <n>]
peektrace sessions search <text> [--agent <id>] [--project <name>] [--since <when>] [--limit <n>] [--no-redact]
peektrace sessions analyze [<session-id>] [--latest] [--cwd <path>]
peektrace sessions export [<session-id>] [--format html|md|json] [--out <file>] [--no-redact]
peektrace statusline [--timeout <ms>]            # Claude Code status line, reads stdin
peektrace memory ls [project]                    # --json for raw output
peektrace memory show <project> <name>
peektrace --read-only memory rm <project> <name> # refused, nothing written
peektrace doctor                                 # write a local support bundle

peektrace doctor collects recent local run-log events, recursively redacts them, and writes a JSON bundle to ~/.peektrace (or PEEKTRACE_DIR) for you to email. It is a diagnostics export, not a health check — nothing is uploaded.

peektrace sessions search "retry backoff" finds sessions whose text holds the phrase, newest first, with the matching line and a snippet. Snippets are redacted unless you pass --no-redact.

peektrace sessions analyze --latest scores the newest session of any agent. --cwd . limits it to sessions run in this directory or below.

peektrace sessions export --latest --out session.html saves one session as HTML, Markdown or JSON. Secrets and home paths are redacted unless you pass --no-redact.

To show context health in the Claude Code status line, add this to ~/.claude/settings.json. It prints ctx 42% Healthy, or ctx -- on any problem.

{ "statusLine": { "type": "command", "command": "peektrace statusline" } }

Full flag reference: apps/cli/README.md.

Desktop app

apps/desktop wraps the same binary in an Electron shell — native window, single-instance lock, auto-update from GitHub Releases — spawning the binary as a loopback sidecar and loading its URL.

It is not distributed yet. The workflow is manual-dispatch only until builds can be signed and notarized; Mac builds are currently unsigned (right-click → Open on first launch)..

Privacy posture

  • Loopback by default. The server binds 127.0.0.1. A non-loopback --host needs a token and is read-only unless --allow-write.
  • Secret redaction on by default for every rendered or exported transcript.
  • No model ever sees your data. The core reads bodies itself; no transcript and no memory is sent to an LLM.
  • Safe writes. Atomic temp-write plus rename, compare-and-swap with a per-file lock, and a compile-time read-only filesystem layer behind --read-only. Editing is enabled only where the capability registry says the agent supports it.
  • Local run log, on by default, never sent anywhere. Each invocation appends one wide event to a SQLite file under ~/.peektrace (or PEEKTRACE_DIR). It makes no network calls. Opt out with --no-telemetry or PEEKTRACE_NO_TELEMETRY=1. peektrace doctor is the only way this data leaves your machine, and only if you email the redacted bundle yourself.
  • One outbound call, at startup. peektrace serve fires a best-effort, non-blocking GET at the GitHub releases API to see whether a newer cli-v* exists, and prints one hint line if so. The result caches for ~24h, so it hits the network at most once a day, and it never delays the server. It sends nothing about you. Disable with PEEKTRACE_NO_UPDATE_CHECK=1.

Develop

Prerequisites

  • Bun >=1.3.0 — runtime and package manager.
  • Node.js >=20.9.0 — required by some workspace tooling.

Run from source

bun install
bun run serve      # build the inspector, then serve on 127.0.0.1
bun run tui        # same, into the terminal UI

Both scripts build apps/inspector first. To skip the rebuild and pass flags straight through:

bun run --filter=inspector build          # emit apps/inspector/dist once
bun run apps/cli/src/index.ts serve --port 4321

Dev vs prod transport is explained in apps/inspector/README.md.

Layout

Path Role
packages/core Effect services: agents · capabilities · sessions · memory · stats · fs · watch
packages/rpc Effect-RPC contract, handlers, typed client
packages/viz Shared chart primitives
packages/ui shadcn/ui component library
apps/cli the peektrace binary: one-shot commands, serve, tui
apps/inspector Vite + React + Effect-Atom web UI
apps/desktop Electron shell around the compiled binary
apps/web Next.js marketing site, independent of the inspector

apps/web and its oRPC packages/api are a separate concern from Peektrace itself. The site runs behind portless at https://web.localhost:8443 — automatic HTTPS on an unprivileged port, so it never needs sudo. For plain http://localhost:3000, run bun run dev:app in apps/web.

Commands

Command Description
bun dev Start all apps in dev mode
bun run build Build every app and package
bun run typecheck tsc --noEmit per package
bun run check Lint and format check (Ultracite / Biome)
bun run fix Auto-fix lint and formatting
bun run desktop:dev Run the Electron shell unpackaged
bun run desktop:package Build an unsigned macOS .dmg

Typecheck with bun run typecheck only. Never tsc -b or bare tsc — build mode emits .js and .d.ts next to sources and pollutes the tree.

Add shadcn components to the shared package, then import from @workspace/ui:

bunx shadcn@latest add button -c packages/ui

Editor setup

Open the repo in VS Code or Cursor and accept the recommended extensions (.vscode/extensions.json): Biome as the default formatter, Tailwind IntelliSense inside cn / cva / tv, the Bun debugger, and Pretty TypeScript Errors. Format-on-save, import organization and lint auto-fix run through Biome on every save; .editorconfig covers other editors.

Release

apps/cli compiles to a standalone executable with the inspector embedded:

bun run --filter=peektrace build:binary

The result serves with zero external files. Linux builds strip debug info from OpenTUI's native library (needs llvm-strip, or GNU strip on a same-arch Linux host; see docs/binary-size.md). CI publishes it on cli-v* tags, feeding the installers in scripts/ and the npm packages. The same binary is the sidecar inside the undistributed desktop app.

npm gets six packages per release: the peektrace wrapper plus one @peektrace/cli-<platform>-<arch> per binary, published over OIDC with no stored token. See the header of .github/workflows/publish-cli.yml.

The GitHub Release body is the matching ## cli-vX.Y.Z section of CHANGELOG.md. A tag with no section gets generated notes instead.


Author

Andrey Markin (@Mark-Life).

License

MIT © Mark-Life Ltd and Andrey Markin. The licence sits at the repo root and covers the whole workspace — every package under packages/ and apps/, and the standalone peektrace binary built from apps/cli.

About

Local, loopback-only inspector for Claude Code, Codex, Pi and OpenCode sessions: context-budget forensics, stats and Claude memory.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages