agent-session-inspector 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -64
- package/VERSION +1 -1
- package/app/.next/BUILD_ID +1 -1
- package/app/.next/build-manifest.json +3 -3
- package/app/.next/prerender-manifest.json +5 -5
- package/app/.next/required-server-files.json +1 -1
- package/app/.next/server/app/_global-error.html +1 -1
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_not-found.html +1 -1
- package/app/.next/server/app/_not-found.rsc +16 -16
- package/app/.next/server/app/_not-found.segments/_full.segment.rsc +16 -16
- package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +19 -18
- package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -3
- package/app/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/app/.next/server/app/api/logs/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/app/.next/server/app/api/search/route.js.nft.json +1 -1
- package/app/.next/server/app/api/sessions/[provider]/[id]/reveal/route.js.nft.json +1 -1
- package/app/.next/server/app/api/sessions/[provider]/[id]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/app/.next/server/app/index.html +1 -1
- package/app/.next/server/app/index.rsc +18 -18
- package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +16 -16
- package/app/.next/server/app/index.segments/_full.segment.rsc +18 -18
- package/app/.next/server/app/index.segments/_tree.segment.rsc +3 -3
- package/app/.next/server/app/page.js.nft.json +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/sessions/[provider]/[id]/page.js.nft.json +1 -1
- package/app/.next/server/app/sessions/[provider]/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__0yxic1z._.js +3 -3
- package/app/.next/server/chunks/ssr/[root-of-the-server]__1ei65vj._.js +1 -1
- package/app/.next/server/chunks/ssr/_0f8nmc3._.js +1 -1
- package/app/.next/server/chunks/ssr/_0o294sf._.js +1 -1
- package/app/.next/server/chunks/ssr/_1-5v1mi._.js +1 -1
- package/app/.next/server/chunks/ssr/_12__495._.js +1 -1
- package/app/.next/server/chunks/ssr/src_app_page_tsx_1chiuah._.js +1 -1
- package/app/.next/server/chunks/ssr/src_app_sessions_[provider]_[id]_page_tsx_0uf635h._.js +1 -1
- package/app/.next/server/middleware-build-manifest.js +3 -3
- package/app/.next/server/pages/404.html +1 -1
- package/app/.next/server/pages/500.html +1 -1
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/043k5ranw7p1-.js +1 -0
- package/app/.next/static/chunks/{10x4j1wts3xx2.js → 0mihgzifdany7.js} +1 -1
- package/app/.next/static/chunks/{367imffzz5g8x.css → 0ua57-s0meis5.css} +2 -2
- package/app/.next/static/chunks/{31hdfb4m8lwzz.js → 1fe2mxakoweia.js} +1 -1
- package/app/.next/static/chunks/{1dz8a9ds45tdb.js → 1syzk-359a-tl.js} +1 -1
- package/app/.next/static/chunks/23pvfhng1yidh.css +1 -0
- package/app/.next/static/chunks/3-g9jvt_m-6_4.js +1 -0
- package/app/CONTRIBUTING.md +21 -2
- package/app/README.md +154 -64
- package/app/bin/agent-session-inspector.mjs +37 -11
- package/app/eslint.config.mjs +1 -0
- package/app/package.json +6 -2
- package/app/pnpm-lock.yaml +271 -0
- package/app/pnpm-workspace.yaml +1 -0
- package/app/scripts/build-cli.mjs +26 -0
- package/app/scripts/demo-data.mjs +48 -1
- package/app/scripts/deploy-docker.sh +6 -2
- package/app/scripts/package-release.sh +3 -1
- package/app/server.js +1 -1
- package/bin/agent-session-inspector.mjs +37 -11
- package/cli/cli.mjs +7610 -0
- package/package.json +5 -2
- package/app/.next/static/chunks/1g3ep2o7fhgpe.css +0 -1
- package/app/.next/static/chunks/2iedud09ou282.js +0 -1
- package/app/.next/static/chunks/2k65elb1vo-2z.js +0 -1
- /package/app/.next/static/{KFq9wlUt8U-Sma3McE5Jw → -wq1RTFV0ts5s-g4PiOpq}/_buildManifest.js +0 -0
- /package/app/.next/static/{KFq9wlUt8U-Sma3McE5Jw → -wq1RTFV0ts5s-g4PiOpq}/_clientMiddlewareManifest.js +0 -0
- /package/app/.next/static/{KFq9wlUt8U-Sma3McE5Jw → -wq1RTFV0ts5s-g4PiOpq}/_ssgManifest.js +0 -0
package/app/README.md
CHANGED
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
[](https://nodejs.org)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
See exactly where a coding-agent session's tokens and dollars went. A local
|
|
9
|
+
inspector for Claude Code, Codex, GitHub Copilot, Cursor, Gemini CLI, OpenCode
|
|
10
|
+
and Hermes transcripts: every prompt, thought, tool call and injected piece of
|
|
11
|
+
context in order, each with its own token count and cost.
|
|
12
|
+
|
|
13
|
+
It answers the questions a usage total cannot: why one session cost $12, which
|
|
14
|
+
turn blew up the context, how much of it was system prompt and tool results
|
|
15
|
+
rather than conversation, and which tool kept failing.
|
|
11
16
|
|
|
12
17
|
> **Your sessions never leave your machine.** The app collects nothing: no
|
|
13
18
|
> telemetry, no analytics, no account, no cloud. It reads the transcript files
|
|
@@ -58,6 +63,130 @@ rm -rf ~/.agent-session-inspector ~/.local/bin/agent-session-inspector
|
|
|
58
63
|
The install script needs bash, so it covers macOS, Linux and WSL. On Windows
|
|
59
64
|
use `npx`.
|
|
60
65
|
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
### Inspect one session
|
|
69
|
+
|
|
70
|
+
**Step-by-step timeline.** Prompts, reasoning, tool calls and their results in
|
|
71
|
+
order, with per-step token counts and cost. What the agent was given shows up
|
|
72
|
+
too: system prompt, tool catalog, MCP instructions and skill listings appear as
|
|
73
|
+
events with their size. Expand any event to see its content, or open the raw
|
|
74
|
+
record.
|
|
75
|
+
|
|
76
|
+
<picture>
|
|
77
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/timeline-dark.png">
|
|
78
|
+
<img alt="Event timeline showing user prompt, thinking, and Grep/Read tool calls" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/timeline.png">
|
|
79
|
+
</picture>
|
|
80
|
+
|
|
81
|
+
**Token Optimizer.** What the session cost by token class, model and turn, where
|
|
82
|
+
the context went (system prompt vs. tool results vs. replies), which tools ran
|
|
83
|
+
most, and hints for trimming expensive sessions.
|
|
84
|
+
|
|
85
|
+
<picture>
|
|
86
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/token-optimizer-dark.png">
|
|
87
|
+
<img alt="Token Optimizer: estimated cost by token class and model, and a cost-by-turn chart" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/token-optimizer.png">
|
|
88
|
+
</picture>
|
|
89
|
+
|
|
90
|
+
**Session health.** A score out of 100 and a grade for how smoothly the session
|
|
91
|
+
ran, with links to the failed tools, retry loops and interrupted turns that cost
|
|
92
|
+
it points. See [Session health](#session-health).
|
|
93
|
+
|
|
94
|
+
**Edits per turn.** A session's Edits tab lists each prompt with the files the
|
|
95
|
+
agent wrote, edited or patched in response, linked to the event in the timeline.
|
|
96
|
+
|
|
97
|
+
### Find the session worth inspecting
|
|
98
|
+
|
|
99
|
+
**Full-text search.** `⌘K` / `Ctrl+K` searches every transcript of every agent:
|
|
100
|
+
prompts, replies, reasoning, tool arguments and tool results, as well as titles,
|
|
101
|
+
repos and branches. Each hit shows the matching line and what kind of event it
|
|
102
|
+
came from.
|
|
103
|
+
|
|
104
|
+
**All sessions in one place.** Every session of every supported agent on the
|
|
105
|
+
machine, filterable by agent. Each card shows turns, tool calls, health grade,
|
|
106
|
+
cost and tokens in/out at a glance.
|
|
107
|
+
|
|
108
|
+
<picture>
|
|
109
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/sessions-dark.png">
|
|
110
|
+
<img alt="Session list with agent filters, search and per-session health, cost and token counts" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/sessions.png">
|
|
111
|
+
</picture>
|
|
112
|
+
|
|
113
|
+
**Analytics across sessions.** Cost, messages, tool calls and active time for
|
|
114
|
+
the selected range, with an activity calendar and filters for project, agent
|
|
115
|
+
and model.
|
|
116
|
+
|
|
117
|
+
<picture>
|
|
118
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/analytics-dark.png">
|
|
119
|
+
<img alt="Analytics tab: cost, session and token totals above an activity calendar" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/analytics.png">
|
|
120
|
+
</picture>
|
|
121
|
+
|
|
122
|
+
**Projects.** Sessions are grouped by the repository they ran in, so work
|
|
123
|
+
started from a subfolder or a git worktree lands in the same project. The
|
|
124
|
+
Projects tab lists each one with its sessions, cost and tokens, and picking a
|
|
125
|
+
project filters Analytics, Usage and Sessions together. Outside a repository,
|
|
126
|
+
the working directory is the project; the dated scratch folders the Codex app
|
|
127
|
+
creates for project-less chats count as one project.
|
|
128
|
+
|
|
129
|
+
**Activity.** One day at a time: how many sessions were working at once in each
|
|
130
|
+
15-minute slot, the agent time and cost of each session, and the day's split by
|
|
131
|
+
project, model and agent.
|
|
132
|
+
|
|
133
|
+
**Skills and MCP tools.** The Analytics tab counts which skills were loaded and
|
|
134
|
+
which MCP servers and tools were called, for the selected range.
|
|
135
|
+
|
|
136
|
+
> Screenshots use synthetic demo data. To reproduce them locally, see
|
|
137
|
+
> [CONTRIBUTING.md](CONTRIBUTING.md#demo-data).
|
|
138
|
+
|
|
139
|
+
## Terminal reports
|
|
140
|
+
|
|
141
|
+
The same numbers are available without the web UI. Each command reads the
|
|
142
|
+
transcripts, prints a report and exits:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx agent-session-inspector usage # tokens and estimated cost per day
|
|
146
|
+
npx agent-session-inspector stats # sessions, messages, tools and time, by agent
|
|
147
|
+
npx agent-session-inspector sessions # recent sessions with cost and health
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
$ npx agent-session-inspector usage --by model --all
|
|
152
|
+
Token usage · all time · by model
|
|
153
|
+
|
|
154
|
+
Model Sessions Input Output Cache read Cache write Total Est. cost
|
|
155
|
+
───────────────────────── ──────── ───── ────── ────────── ─────────── ────── ─────────
|
|
156
|
+
claude-opus-5-5 1 2.5K 3.4K 318.0K 23.1K 347.0K $0.26 ████████████████
|
|
157
|
+
claude-sonnet-5 1 2.0K 2.5K 235.1K 19.1K 258.8K $0.12 ███████▊
|
|
158
|
+
gpt-5.1 1 11.6K 1.6K 27.3K 0 40.5K $0.03 ██▏
|
|
159
|
+
───────────────────────── ──────── ───── ────── ────────── ─────────── ────── ─────────
|
|
160
|
+
Total 3 16.1K 7.5K 580.4K 42.2K 646.3K $0.41
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Reports cover the last 30 days unless `--days <n>` or `--all` says otherwise.
|
|
164
|
+
`--agent`, `--project` and `--model` narrow them, and `--json` prints the data
|
|
165
|
+
for scripts. `usage` groups by day by default; `--by` takes `week`, `month`,
|
|
166
|
+
`project`, `model` or `agent`. `sessions --sort cost` lists the most expensive
|
|
167
|
+
sessions first. `<command> --help` lists every option.
|
|
168
|
+
|
|
169
|
+
#### Scripting
|
|
170
|
+
|
|
171
|
+
The tables are for reading: values are rounded, and piping one drops the rules
|
|
172
|
+
and bars but keeps the rounding. For automation use `--json`, which prints exact
|
|
173
|
+
numbers under stable names:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npx agent-session-inspector usage --days 1 --json | jq '.total.costUSD'
|
|
177
|
+
npx agent-session-inspector sessions --sort cost --json | jq -r '.sessions[].id'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Every report carries `schemaVersion` (currently `1`) and `days` (`null` for all
|
|
181
|
+
time). New fields may appear within a version; a field is renamed or removed
|
|
182
|
+
only with a new one. Costs are US dollars, or `null` where no price is known.
|
|
183
|
+
|
|
184
|
+
| Command | Fields |
|
|
185
|
+
| ---------- | -------------------------------------------------------------------------------------------------------- |
|
|
186
|
+
| `usage` | `by`, `rows[]`, `total`, `unpricedModels`. A row has `key`, `sessions`, `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `totalTokens`, `costUSD`; `total` has the same without `key`. |
|
|
187
|
+
| `stats` | `totals`, `messagesPerSession`, `agents[]`, `projects[]`, `tools[]`, `skills[]`, `mcpServers[]`, `unpricedModels`. |
|
|
188
|
+
| `sessions` | `sort`, `total` (matches before `--limit`), `sessions[]`. A session has `agent`, `id`, `title`, `project`, `model`, `createdAt`, `updatedAt`, `userMessages`, `toolCalls`, `inputTokens`, `outputTokens`, `estimatedCostUSD`, `health`. |
|
|
189
|
+
|
|
61
190
|
## Supported agents
|
|
62
191
|
|
|
63
192
|
| Agent | Reads from | Session titles | Logs |
|
|
@@ -69,18 +198,26 @@ use `npx`.
|
|
|
69
198
|
| OpenAI Codex CLI | `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl` | `session_index.jsonl` | no |
|
|
70
199
|
| OpenCode | `~/.local/share/opencode/opencode.db` | `session` table | no |
|
|
71
200
|
| Hermes Agent | `~/.hermes/state.db` | `sessions` table | no |
|
|
201
|
+
| Gemini CLI | `~/.gemini/tmp/<project>/chats/session-*` | session summary | no |
|
|
202
|
+
| Cursor | `<Cursor>/User/globalStorage/state.vscdb` | chat name | no |
|
|
72
203
|
|
|
73
|
-
`<Code>` and `<
|
|
74
|
-
Support/…` on macOS, `%APPDATA%\…` on Windows,
|
|
75
|
-
Insiders is read too. The
|
|
204
|
+
`<Code>`, `<Claude>` and `<Cursor>` are the desktop apps' data folders:
|
|
205
|
+
`~/Library/Application Support/…` on macOS, `%APPDATA%\…` on Windows,
|
|
206
|
+
`~/.config/…` on Linux. VS Code Insiders is read too. The SQLite stores are
|
|
207
|
+
opened read-only.
|
|
76
208
|
|
|
77
|
-
|
|
209
|
+
Three things differ from the CLIs that log every request:
|
|
78
210
|
|
|
79
211
|
- **Copilot Chat** meters a whole request, and its prompt count is that of the
|
|
80
212
|
last model round. For a request that called tools, input tokens and cost are a
|
|
81
213
|
floor.
|
|
82
214
|
- **Hermes** counts tokens per session, so its usage appears as one checkpoint at
|
|
83
215
|
the end of the timeline rather than per message.
|
|
216
|
+
- **Cursor** rarely writes token counts to disk, so most of its sessions show the
|
|
217
|
+
timeline, tools and timing but no tokens or cost. Only the chat table of
|
|
218
|
+
`state.vscdb` is read. A session that is not in it, such as one from the
|
|
219
|
+
Cursor CLI, is read from the plainer transcript under `~/.cursor/projects`,
|
|
220
|
+
which has no tool results and is timed to the minute.
|
|
84
221
|
|
|
85
222
|
Whichever directories exist on the machine show up; the rest are hidden.
|
|
86
223
|
|
|
@@ -105,64 +242,15 @@ You don't have to take this on trust. The code is open, and the browser's
|
|
|
105
242
|
Network tab shows every request going to `localhost` and nowhere else; the app
|
|
106
243
|
works the same with the network disconnected.
|
|
107
244
|
|
|
108
|
-
##
|
|
109
|
-
|
|
110
|
-
**Analytics across sessions.** Cost, messages, tool calls and active time for
|
|
111
|
-
the selected range, with an activity calendar and filters for project, agent
|
|
112
|
-
and model.
|
|
113
|
-
|
|
114
|
-
<picture>
|
|
115
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/analytics-dark.png">
|
|
116
|
-
<img alt="Analytics tab: cost, session and token totals above an activity calendar" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/analytics.png">
|
|
117
|
-
</picture>
|
|
118
|
-
|
|
119
|
-
**All sessions in one place.** Every session of every supported agent on the
|
|
120
|
-
machine, filterable by agent and searchable by title, repo, branch or id.
|
|
121
|
-
Each card shows turns, tool calls, health grade, cost and tokens in/out at a
|
|
122
|
-
glance.
|
|
123
|
-
|
|
124
|
-
<picture>
|
|
125
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/sessions-dark.png">
|
|
126
|
-
<img alt="Session list with agent filters, search and per-session health, cost and token counts" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/sessions.png">
|
|
127
|
-
</picture>
|
|
245
|
+
## How it compares
|
|
128
246
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
</picture>
|
|
137
|
-
|
|
138
|
-
**Token Optimizer.** What the session cost by token class, model and turn, where
|
|
139
|
-
the context went (system prompt vs. tool results vs. replies), which tools ran
|
|
140
|
-
most, and hints for trimming expensive sessions.
|
|
141
|
-
|
|
142
|
-
<picture>
|
|
143
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/token-optimizer-dark.png">
|
|
144
|
-
<img alt="Token Optimizer: estimated cost by token class and model, and a cost-by-turn chart" src="https://raw.githubusercontent.com/kishanmundha/agent-session-inspector/main/docs/screenshots/token-optimizer.png">
|
|
145
|
-
</picture>
|
|
146
|
-
|
|
147
|
-
**Projects.** Sessions are grouped by the repository they ran in, so work
|
|
148
|
-
started from a subfolder or a git worktree lands in the same project. The
|
|
149
|
-
Projects tab lists each one with its sessions, cost and tokens, and picking a
|
|
150
|
-
project filters Analytics, Usage and Sessions together. Outside a repository,
|
|
151
|
-
the working directory is the project; the dated scratch folders the Codex app
|
|
152
|
-
creates for project-less chats count as one project.
|
|
153
|
-
|
|
154
|
-
**Activity.** One day at a time: how many sessions were working at once in each
|
|
155
|
-
15-minute slot, the agent time and cost of each session, and the day's split by
|
|
156
|
-
project, model and agent.
|
|
157
|
-
|
|
158
|
-
**Edits per turn.** A session's Edits tab lists each prompt with the files the
|
|
159
|
-
agent wrote, edited or patched in response, linked to the event in the timeline.
|
|
160
|
-
|
|
161
|
-
**Skills and MCP tools.** The Analytics tab counts which skills were loaded and
|
|
162
|
-
which MCP servers and tools were called, for the selected range.
|
|
163
|
-
|
|
164
|
-
> Screenshots use synthetic demo data. To reproduce them locally, see
|
|
165
|
-
> [CONTRIBUTING.md](CONTRIBUTING.md#demo-data).
|
|
247
|
+
[AgentsView](https://github.com/kenn-io/agentsview) and
|
|
248
|
+
[ccusage](https://github.com/ryoppippi/ccusage) read the same transcript files.
|
|
249
|
+
AgentsView is an archive and search tool across all your sessions; ccusage
|
|
250
|
+
prints usage and cost reports in the terminal. This project is for the step
|
|
251
|
+
after that: opening one session to see what the agent was given, what it did
|
|
252
|
+
with it, and what each step cost. It keeps no database and makes no outbound
|
|
253
|
+
requests.
|
|
166
254
|
|
|
167
255
|
## How it works
|
|
168
256
|
|
|
@@ -184,6 +272,8 @@ src/lib/providers/
|
|
|
184
272
|
codex.ts ~/.codex adapter
|
|
185
273
|
opencode.ts OpenCode's opencode.db
|
|
186
274
|
hermes.ts Hermes Agent's state.db
|
|
275
|
+
gemini.ts Gemini CLI: replays the session logs under ~/.gemini/tmp
|
|
276
|
+
cursor.ts Cursor's state.vscdb, else its ~/.cursor/projects transcripts
|
|
187
277
|
index.ts registry: listSessions / getSession / listLogs across providers
|
|
188
278
|
```
|
|
189
279
|
|
|
@@ -7,17 +7,30 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import net from "node:net";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
11
|
|
|
12
12
|
const NAME = "agent-session-inspector";
|
|
13
13
|
const MIN_NODE = [22, 13];
|
|
14
14
|
const PKG_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
15
|
const SERVER = path.join(PKG_DIR, "app", "server.js");
|
|
16
16
|
|
|
17
|
+
// Report commands print to the terminal instead of starting the server; they
|
|
18
|
+
// live in the bundle scripts/build-cli.mjs writes to <package>/cli/.
|
|
19
|
+
const CLI = path.join(PKG_DIR, "cli", "cli.mjs");
|
|
20
|
+
const COMMANDS = ["usage", "stats", "sessions"];
|
|
21
|
+
|
|
17
22
|
const HELP = `Usage: ${NAME} [options]
|
|
23
|
+
${NAME} <command> [options]
|
|
24
|
+
|
|
25
|
+
Browse Claude Code, Codex, Copilot, Cursor, Gemini CLI, OpenCode and Hermes
|
|
26
|
+
session transcripts in a local web UI, or print a report in the terminal.
|
|
27
|
+
|
|
28
|
+
Commands:
|
|
29
|
+
usage Tokens and estimated cost by day, model, project or agent
|
|
30
|
+
stats Sessions, messages, tool calls and time, by agent
|
|
31
|
+
sessions Recent sessions with their cost and health
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
local web UI.
|
|
33
|
+
Run a command with --help for its options.
|
|
21
34
|
|
|
22
35
|
Options:
|
|
23
36
|
-p, --port <port> Port to listen on (default: 3000, or the next free one)
|
|
@@ -118,7 +131,12 @@ function openBrowser(url) {
|
|
|
118
131
|
.unref();
|
|
119
132
|
}
|
|
120
133
|
|
|
121
|
-
const
|
|
134
|
+
const argv = process.argv.slice(2);
|
|
135
|
+
const command = COMMANDS.includes(argv[0]) ? argv[0] : null;
|
|
136
|
+
if (!command && argv[0] && !argv[0].startsWith("-")) {
|
|
137
|
+
fail(`unknown command ${argv[0]}\n\n${HELP}`);
|
|
138
|
+
}
|
|
139
|
+
const opts = command ? null : parseArgs(argv);
|
|
122
140
|
|
|
123
141
|
// npx only warns about package.json "engines", and the app needs node:sqlite.
|
|
124
142
|
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
@@ -126,6 +144,21 @@ if (major < MIN_NODE[0] || (major === MIN_NODE[0] && minor < MIN_NODE[1])) {
|
|
|
126
144
|
fail(`Node.js ${MIN_NODE.join(".")} or newer is required (found ${process.version}).`);
|
|
127
145
|
}
|
|
128
146
|
|
|
147
|
+
// node:sqlite still announces itself as experimental on Node 22; not useful here.
|
|
148
|
+
const emitWarning = process.emitWarning;
|
|
149
|
+
process.emitWarning = (warning, ...rest) => {
|
|
150
|
+
if (String(warning).includes("SQLite is an experimental feature")) return;
|
|
151
|
+
emitWarning.call(process, warning, ...rest);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
if (command) {
|
|
155
|
+
if (!existsSync(CLI)) {
|
|
156
|
+
fail(`no command bundle found at ${CLI}\nRun \`pnpm cli ${command}\` from a checkout.`);
|
|
157
|
+
}
|
|
158
|
+
const { run } = await import(pathToFileURL(CLI).href);
|
|
159
|
+
process.exit(run(command, argv.slice(1)));
|
|
160
|
+
}
|
|
161
|
+
|
|
129
162
|
if (!existsSync(SERVER)) {
|
|
130
163
|
fail(`no build found at ${SERVER}\nRun scripts/package-release.sh and use dist/${NAME}/bin/${NAME}.mjs.`);
|
|
131
164
|
}
|
|
@@ -142,13 +175,6 @@ process.env.NEXT_TELEMETRY_DISABLED = "1";
|
|
|
142
175
|
process.env.PORT = String(port);
|
|
143
176
|
process.env.HOSTNAME = opts.host;
|
|
144
177
|
|
|
145
|
-
// node:sqlite still announces itself as experimental on Node 22; not useful here.
|
|
146
|
-
const emitWarning = process.emitWarning;
|
|
147
|
-
process.emitWarning = (warning, ...rest) => {
|
|
148
|
-
if (String(warning).includes("SQLite is an experimental feature")) return;
|
|
149
|
-
emitWarning.call(process, warning, ...rest);
|
|
150
|
-
};
|
|
151
|
-
|
|
152
178
|
// server.js is CommonJS and starts listening on load.
|
|
153
179
|
createRequire(import.meta.url)(SERVER);
|
|
154
180
|
|
package/app/eslint.config.mjs
CHANGED
package/app/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-session-inspector",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "See where a coding-agent session's tokens and dollars went: a local inspector for Claude Code, Codex, GitHub Copilot, Cursor, Gemini CLI, OpenCode and Hermes sessions, with a step-by-step timeline, per-step cost and analytics.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
7
7
|
"ai-agent",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
"copilot-chat",
|
|
13
13
|
"vscode",
|
|
14
14
|
"codex",
|
|
15
|
+
"cursor",
|
|
16
|
+
"gemini-cli",
|
|
15
17
|
"opencode",
|
|
16
18
|
"hermes",
|
|
17
19
|
"llm",
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
"build": "next build",
|
|
38
40
|
"start": "next start",
|
|
39
41
|
"lint": "eslint",
|
|
42
|
+
"cli": "node scripts/build-cli.mjs && node bin/agent-session-inspector.mjs",
|
|
40
43
|
"deploy:docker": "./scripts/deploy-docker.sh",
|
|
41
44
|
"package": "./scripts/package-release.sh"
|
|
42
45
|
},
|
|
@@ -65,6 +68,7 @@
|
|
|
65
68
|
"@types/node": "^22.20.4",
|
|
66
69
|
"@types/react": "^19",
|
|
67
70
|
"@types/react-dom": "^19",
|
|
71
|
+
"esbuild": "^0.28.2",
|
|
68
72
|
"eslint": "^9",
|
|
69
73
|
"eslint-config-next": "16.3.0",
|
|
70
74
|
"tailwindcss": "^4",
|