Pulse and AgentLens
Local analytics over the logs coding agents already write: sessions, tokens, cost and failing tool calls, without storing a single prompt
- Role
- Sole designer and builder
- Status
- In personal use
- Period
- Sep–Oct 2026
- Stack
- Next.js 16, React 19, TypeScript
Problem
I run Claude Code, Codex and OpenCode every day, often in parallel. I could not answer basic questions about that work. What does it cost at API prices? Which tool calls fail, and how often? Which projects eat the tokens? Is my agentic workflow actually getting better, or does it just feel that way?
Each vendor shows its own slice, and none of them joins it with git. But every harness already writes detailed logs to disk. The data was there; nothing read it.
Two versions of one product
Pulse came first, in September 2026, to show me how I actually use AI: which tools, how much, at what cost, and against what output. It merged GitHub activity, local commits, writing in Markdown, and seven AI tools into one timeline with a yearly heatmap, streaks, day drilldowns, cost, and plan limits with a burn-rate projection. It runs as a web app, and I packaged it as a macOS desktop app.
AgentLens came in October, as a separate and narrower rewrite. It drops the contribution dashboard and goes deep on agents only: every request, every tool call with its outcome and duration, subagents, and a live panel. It reuses Pulse's rate card and, more importantly, Pulse's token accounting, which took the longest to get right.
Architecture
One parser per source turns a session file into rows: sessions, requests, tool calls, prompts and commits. Each session and its children are replaced inside one transaction, so a re-read never half-updates. A file is re-parsed only when its modification time or size changes; OpenCode is rebuilt only when its database changes; git is rescanned at most every ten minutes. While the dashboard tab is visible it triggers an ingest every 20 seconds.
The dashboard shows KPIs against the previous period, spend by day and model, a live panel of sessions active in the last 15 minutes, failing shell commands, a weekday by hour prompt heatmap, and drilldowns by session, tool and project. Commits with AI co-author trailers are attributed, and worktrees roll up to their main repository so one project is one project.
Pulse's desktop app runs the Next.js standalone server as a child process of Electron, on a random loopback port. The database and a generated session secret live in the OS user-data folder. A release workflow builds arm64 and x64 DMGs in GitHub Actions on a tag push and uploads them to Cloudflare R2, because a serverless function cannot stream a file of about 120 MB.
Key decisions
-
Never store what was said. Prompt text is not stored; AgentLens keeps a prompt's length. A tool call keeps its name and a short target, such as a file path or the first program in a shell command. Pulse's history backfill reads a session ID, timestamp and project, and never the prompt.
-
Cost at API prices, labelled as such. A subscription bill says nothing about what a session cost. Cost here is the API-equivalent price of the tokens from a rate card. A model missing from the card costs zero, not a guess. Cache savings are allowed to go negative, and the code comment calls that "honest, not a bug".
-
No native modules. AgentLens uses Node's built-in SQLite. Nothing to compile, nothing to break on the next Node release.
-
No auth in AgentLens. It runs on my machine and reads my files, so it has no login and its ingest endpoint is open. Pulse had signed-cookie auth and a setup flow because it could be deployed; AgentLens traded that away for simplicity.
What broke
Token accounting was the hard part, and every fix came from a number that looked wrong.
- Claude Code double-counted. Transcripts re-log the same message ID, so usage is now de-duplicated per message.
- Codex over-counted three ways. Resumed and forked sessions inherit the parent's cumulative counter, so totals now come from summing per-request deltas. Resuming replays a burst of token events within the same second, and those are dropped. Subagent forks collapsed onto one session ID until the first session metadata record was made to win.
- A CLI update removed the signal. Codex CLI 0.153 stopped writing user-message events, so prompts are now counted from task-start events.
- Rotated transcripts. Claude Code rotates old transcripts away; Pulse recovers their sessions from the history file.
- The packaged app crashed on boot. electron-builder silently dropped the standalone server's
node_modulesand Next.js's symlinks. An after-pack hook restores them. - Login looped forever on desktop. The session cookie was marked
Secureand the desktop app serves plain HTTP on loopback, so the browser never sent it back. Desktop mode drops the flag.
Results
At its last ingest on 12 October 2026, AgentLens held 612 sessions (329 Claude Code, 173 Codex, 110 OpenCode), 28,004 model requests, 32,719 tool calls and 683 commits. Its Claude cost estimate is within about 4% of Claude Code's own cost records. A first ingest takes about ten seconds and an incremental sync about 50 ms.
Pulse's history spans ten days. AgentLens landed in two commits on a single morning, because the hard part, understanding the logs, had already been done once.
What I'd change
- Tests for the parsers. Neither repository has any, and every bug above would have been a fixture.
- One product. Pulse's desktop packaging and AgentLens's depth belong together.
- Expire sessions in Pulse. The session token records when it was issued, and nothing checks it.