snoop-cli 0.2.1__py3-none-win_arm64.whl

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.
Binary file
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joshua Alexander Zillwood
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,368 @@
1
+ Metadata-Version: 2.1
2
+ Name: snoop-cli
3
+ Version: 0.2.1
4
+ Summary: A terminal viewer for Claude Code sessions: follow one live, or see what any past one cost, changed and spent its time on.
5
+ License: MIT
6
+ Project-URL: Homepage, https://jzills.github.io/snoop/
7
+ Project-URL: Source, https://github.com/jzills/snoop
8
+ Classifier: Environment :: Console
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+
13
+ <h1>
14
+ <picture>
15
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jzills/snoop/main/site/static/mark-dark.svg">
16
+ <img src="https://raw.githubusercontent.com/jzills/snoop/main/site/static/mark-light.svg" alt="" height="28">
17
+ </picture>
18
+ snoop
19
+ </h1>
20
+
21
+ This is a fast terminal viewer for Claude Code session transcripts
22
+ (`~/.claude/projects/**/*.jsonl`). You can keep it open in a second terminal
23
+ next to `claude` to watch a session live, or browse past sessions to see what
24
+ each prompt cost, how full the context is, which files changed, what the
25
+ subagents did and where the time went. The documentation is at
26
+ https://jzills.github.io/snoop/.
27
+
28
+ ![snoop: the summary across sessions, a session's timeline with a turn's
29
+ waterfall, an expanded subagent, the Files tab and Stats](https://raw.githubusercontent.com/jzills/snoop/main/demo/demo.gif)
30
+
31
+ ## Install
32
+
33
+ ```
34
+ brew install jzills/tap/snoop # macOS and Linux
35
+ curl -fsSL https://jzills.github.io/snoop/install.sh | sh
36
+ npm install -g snoop-cli # or: pipx install snoop-cli
37
+ go install github.com/jzills/snoop/cmd/snoop@latest
38
+ ```
39
+
40
+ On Windows, use npm, PyPI or the PowerShell script:
41
+
42
+ ```
43
+ irm https://jzills.github.io/snoop/install.ps1 | iex
44
+ ```
45
+
46
+ Every method installs the same `snoop` command. On npm and PyPI the package
47
+ is named `snoop-cli`, since `snoop` was taken, and it carries the binary for
48
+ your platform, so nothing is downloaded or built when it installs. With
49
+ `uv`, run `uv tool install snoop-cli`.
50
+
51
+ The install script picks the build for your machine, checks it against the
52
+ release's `SHA256SUMS`, and installs it to `~/.local/bin` without sudo. To
53
+ install somewhere else, set `SNOOP_INSTALL_DIR`, and to install a given
54
+ release instead of the newest, set `SNOOP_VERSION`, such as `v0.1.0`. The
55
+ PowerShell script does the same on Windows, installing to
56
+ `%LOCALAPPDATA%\Programs\snoop` and adding it to your `PATH`.
57
+
58
+ You can also download a binary for Linux, macOS or Windows from the
59
+ [latest release](https://github.com/jzills/snoop/releases/latest). Each
60
+ archive holds the `snoop` executable, the license and this README.
61
+
62
+ Testing covers Claude Code 2.1.280 through 2.1.310. The transcript format is
63
+ undocumented and changes between versions. Records that snoop doesn't
64
+ recognize are ignored, so a new version may show less rather than break.
65
+ Please open an issue if something goes missing.
66
+
67
+ ## Use
68
+
69
+ ```
70
+ snoop # pick a session (all projects)
71
+ snoop --follow # follow the newest session for this directory, live;
72
+ # switches automatically when a new session starts
73
+ snoop --live # every session at work right now, across projects
74
+ snoop 64f3ec44 # open by session id prefix (or a .jsonl path)
75
+ snoop --project DIR # treat DIR as the current project
76
+ snoop hooks install # let the Diff tab send comments to the agent
77
+ snoop --version
78
+ ```
79
+
80
+ ## What you see
81
+
82
+ **Timeline:** The timeline shows every prompt, reply, thinking block and tool
83
+ call, one per line, with a blank line before each prompt so every turn
84
+ stands apart. A row in the same minute as the one above shows only its
85
+ seconds (`:42`). Tool rows show their duration and status (`✓` done, `✗`
86
+ error, `◌` running). Built-in tools (`▸`), skills (`✦`), MCP calls (`⇄`,
87
+ shown as `server·tool`) and subagents (`⤷`) each have their own color. The
88
+ right pane shows the selected item in full: Bash commands, Edit diffs, Write
89
+ content, agent prompts and results.
90
+
91
+ Each prompt row shows that turn's tokens, estimated cost (`≈`) and duration,
92
+ and compactions appear as `⟳ compacted (auto) 253k → 68k`. The header shows
93
+ how full the context window is (`ctx 142k/200k ▰▰▰▰▰▰▰▱▱▱ 71%`), turning to
94
+ the accent color at 70% and red at 90%. Selecting a prompt shows where its
95
+ turn's time went: totals, the five slowest tool calls, and a waterfall that
96
+ places each call by its start and end, so parallel calls overlap.
97
+
98
+ Pressing `x` on an Agent call expands its subagent inline, indented under a
99
+ `│` rule and kept live while it runs. Pressing `X` expands every subagent,
100
+ nested ones too. Search and filters reach into subagents, and a collapsed call
101
+ whose subagent has matches is kept and marked `●`.
102
+
103
+ **Tools:** The Tools tab groups every tool call by kind (built-in, skills,
104
+ MCP, subagents), then by name (tool, skill, MCP `server·tool`, subagent type),
105
+ then lists the individual calls, with counts, errors and average latency.
106
+ Selecting a group summarizes it in the right pane, and pressing `enter` on a
107
+ call jumps to it in the timeline.
108
+
109
+ **Files:** The Files tab lists every file the session and its subagents read,
110
+ edited or wrote, with read, edit and write counts and the lines added and
111
+ removed. Changed files come first, then files only read, each most recent
112
+ first. The right pane shows a file's history with every change as a diff,
113
+ which `n` and `N` step through, and pressing `enter` shows the latest change
114
+ in the timeline. Pressing `T` switches to a tree of folders, each with the
115
+ totals of its files. Changes made through Bash aren't tracked.
116
+
117
+ **Stats:** The Stats tab opens with the session's cost, duration, tokens (and
118
+ how many came from cache) and context. Below them, Turns lists each prompt's
119
+ time, tokens, cost and context, with a bar for its share of the cost and the
120
+ costliest prompt highlighted. Tools lists the tools used most, with errors
121
+ and average time, beside where the tokens went. Models lists each model with
122
+ its requests and cost.
123
+
124
+ Claude Code records a session's cost only when the session ends, so while it
125
+ runs, snoop estimates the cost from each request's tokens at the model's API
126
+ prices, and marks it `≈` and "estimated". Once the cost is recorded, snoop
127
+ splits each model's total across the prompts by token use, weighted by each
128
+ kind of token's price, so the prompt costs add up to the recorded total. The
129
+ estimate leaves out subagents' requests, and models without a known price
130
+ show tokens only.
131
+
132
+ ## Many sessions at once
133
+
134
+ **Live board:** The live board, opened with `snoop --live` or by pressing `w`
135
+ in the picker, lists every session written in the last 30 minutes, across
136
+ projects, most urgent first.
137
+
138
+ | State | Meaning |
139
+ | --- | --- |
140
+ | `? asking` | the session asks for permission to use a tool, which you can answer here |
141
+ | `◌ waiting` | a tool call has had no result for `--stall` (30s), usually a permission prompt |
142
+ | `✓ your turn` | the turn ended, or you interrupted it |
143
+ | `● working` | replying, or running a tool or subagent (shown underneath) |
144
+ | `· idle` | no prompts yet, or nothing written for 10 minutes |
145
+
146
+ The board's header counts the sessions waiting on you (`1 waiting on you`).
147
+ Each row shows the project, the session, how full its context is, its cost
148
+ and when it last wrote. Press `enter` to open a session and `esc` to come
149
+ back, or `o` and `O` to sort by another column. Only sessions on the board are read, and after the first read, only
150
+ what they add.
151
+
152
+ **Answer permission prompts:** With snoop's hooks installed (see
153
+ [Review and comment](#review-and-comment)), a session that asks for
154
+ permission shows as `? asking` on the board, with the request in full under
155
+ the list: the command, the edit's diff, or the tool's input. Press `A` to
156
+ allow it once, or `D` to deny it, optionally with a reason that Claude sees.
157
+ The same keys work in the session's own view, where its footer shows the
158
+ request. Claude Code's own prompt still appears in the session's terminal,
159
+ and whichever answer comes first wins.
160
+
161
+ The hook waits for an answer only while a live board or session view is
162
+ open, for at most 5 minutes (set with `snoop hooks install --ask-wait 10m`),
163
+ and answering in the terminal ends the wait at once. There is no "always
164
+ allow" here, so rules stay in Claude Code's own prompt.
165
+
166
+ **Find:** Pressing `f` in the picker finds sessions by a file they read or
167
+ changed, a command they ran, or a prompt, subagents included. Every word must
168
+ match the same file, command or prompt. Each result shows what matched, and
169
+ opening it searches its timeline for the same words. Sessions are indexed by
170
+ the same background scan as the summary and cached with it.
171
+
172
+ ## Review and comment
173
+
174
+ The Diff tab (`5`) shows the session's changes in one of two scopes, and `b`
175
+ switches between them. **Uncommitted** is `git diff HEAD`, with untracked
176
+ files shown as added. **Branch** is everything the branch changed since it
177
+ left its base, committed or not, which is what a pull request would show plus
178
+ the work in progress, so you can review an agent's whole branch without
179
+ opening a PR. Files with changes since the last commit are tagged
180
+ `uncommitted`. The tab opens in Branch when the branch has commits of its own.
181
+
182
+ Unless you choose one, snoop compares with the closest of `develop`, `main`,
183
+ `master` and `trunk`, preferring `origin/` copies, since a local one may be
184
+ out of date. The line at the top of the tab names the base. Press `B` to pick
185
+ another base, which is saved for the branch in its git config
186
+ (`branch.<name>.snoopBase`), or set `git config snoop.base` for a whole
187
+ repository.
188
+
189
+ Files the session changed come first, and files changed by you or another
190
+ agent are dimmed. The tab refreshes as the session edits files or runs a
191
+ command, and `r` reads the diff again.
192
+
193
+ Press `tab` to move into a file's lines, then `c` to comment on a line. Press
194
+ `v` and move to select a range first, or press `C` to comment on the whole
195
+ file. Press `e` or `x` to edit or delete the comment under the cursor.
196
+ Comments wait until you press `S`, which sends them all at once. Each comment
197
+ names the file and lines and quotes the code, so the agent doesn't have to
198
+ reread the file.
199
+
200
+ Sending needs Claude Code hooks, which you add once:
201
+
202
+ ```
203
+ snoop hooks install # in ~/.claude/settings.json
204
+ snoop hooks install --project # in ./.claude/settings.json instead
205
+ snoop hooks status # or uninstall
206
+ ```
207
+
208
+ The hooks run `snoop hook` after each tool call, when the agent tries to
209
+ finish, and when you submit a prompt. The agent sees your comments at the
210
+ first of these, so a working agent gets them mid-turn and an agent that has
211
+ finished keeps going. The footer shows when they are delivered. Without the
212
+ hooks, `S` copies the comments to the clipboard instead. A fourth hook runs
213
+ when a session asks for permission, so the live board can
214
+ [answer it](#many-sessions-at-once). If you installed the hooks before that
215
+ hook existed, `snoop hooks status` says so, and running `snoop hooks install`
216
+ again adds it.
217
+
218
+ The hooks are the only change snoop makes to Claude Code's settings, and
219
+ `snoop hooks uninstall` removes exactly those entries. Sent comments wait in a
220
+ `snoop/inbox` folder in your state directory (`~/.local/state` on Linux) until
221
+ a hook delivers them. Permission requests wait in `snoop/asks` beside it, and
222
+ open snoops refresh a small `snoop/listening` file every 2 seconds, which is
223
+ how the hook knows to wait. A session that was already running may need a restart
224
+ before it uses the hooks.
225
+
226
+ ## Summary across sessions
227
+
228
+ Pressing `s` in the session picker switches to a summary of the sessions
229
+ listed, so it follows `c` and the search. It shows sessions, prompts, tool
230
+ calls and the error rate, cost and tokens, a daily cost chart for the last 30
231
+ days, and the top tools, skills, MCP servers, subagent types and models with
232
+ their error rates. Every transcript is parsed in the background
233
+ (`scanning 12/48` in the header), and the results are cached in
234
+ `~/.cache/snoop/summaries.json` (the user cache directory), so later opens are
235
+ instant. Unreadable transcripts are counted and skipped.
236
+
237
+ ## Copy and export
238
+
239
+ Pressing `y` copies the selection to the clipboard over OSC 52, which works
240
+ over SSH, and in tmux with `set-clipboard on`. It copies the command for
241
+ Bash, the diff for edits, the content for Write, the full text of messages,
242
+ and the result for other tools. In the Files tab, it copies all of the file's
243
+ changes.
244
+
245
+ Pressing `e` exports the timeline as shown (search, filter, thinking and
246
+ expanded subagents included) to `./<session-id-8>-<YYYYMMDD-HHMM>.md`.
247
+ Prompts become headings, tool calls become collapsible `<details>` blocks,
248
+ and subagent events are quoted under their call. You can also export from the
249
+ shell:
250
+
251
+ ```
252
+ snoop export 64f3ec44 # whole session to stdout, without thinking
253
+ snoop export 64f3ec44 -o notes.md
254
+ ```
255
+
256
+ ## Alerts
257
+
258
+ While a session is receiving new lines, the header flags what needs your
259
+ attention:
260
+
261
+ | Alert | Raised when |
262
+ | --- | --- |
263
+ | `✗ error` | a tool call fails; the header counts unseen errors |
264
+ | `◌ waiting 30s on Bash` | a tool call has no result after `--stall` (default 30s), which may be a permission prompt, since those aren't recorded until answered |
265
+ | `✓ your turn` | Claude finishes |
266
+ | `⟳ compacted` | the context is compacted |
267
+ | `ctx 90%` | the context window passes 90% |
268
+ | `? Bash: npm test` | the session asks for permission (needs the hooks) |
269
+
270
+ Any key hides the alert, and pressing `!` jumps to it. Lines already in the
271
+ transcript when it opens never raise alerts.
272
+
273
+ ```
274
+ snoop --follow --bell # ring the bell on errors, turn ends and permission requests
275
+ snoop --live --notify # a desktop notification when any session needs you
276
+ snoop --follow --bell --alerts error,stall,turn,compact,ctx,ask
277
+ snoop --stall 2m # 0 disables the waiting alert
278
+ ```
279
+
280
+ The live board raises the same alerts for every session on it, prefixed with
281
+ the project (`api: ✓ your turn`).
282
+
283
+ With `--notify`, snoop sends a desktop notification naming the session and
284
+ what happened (`api · Fix the flaky test` / `Your turn · finished after
285
+ 2m10s`), so you can work elsewhere and come back when a session needs you. It
286
+ picks one way to deliver them:
287
+
288
+ | Where snoop runs | Notification |
289
+ | --- | --- |
290
+ | iTerm2, WezTerm, Ghostty, kitty | the terminal's own (clicking it focuses the tab) |
291
+ | over SSH | the terminal's own, so it shows on your machine, not the server |
292
+ | WSL | a Windows toast, through `powershell.exe` |
293
+ | macOS, other terminals | `osascript` |
294
+ | Linux desktop | `notify-send` |
295
+ | anywhere else | the terminal's own escape sequence (OSC 777) |
296
+
297
+ To override the choice, use `--notify=terminal` or `--notify=system`. In
298
+ tmux, let the terminal's own notifications through with
299
+ `set -g allow-passthrough on`.
300
+
301
+ Nothing is sent while snoop's window has focus (in terminals that report
302
+ focus). At most one notification goes out per session and alert a minute, and
303
+ several snoops watching the same session send one between them.
304
+
305
+ ## Keys
306
+
307
+ Press `?` anywhere for the keys of the current screen. The full list follows.
308
+
309
+ | Key | Action |
310
+ | --- | --- |
311
+ | `↑↓` / `j k`, wheel | move (the wheel over the right pane scrolls it) |
312
+ | `enter` / `tab` | focus the detail pane (zoom it on narrow terminals) |
313
+ | `J K` / `ctrl+d ctrl+u` | scroll the detail pane |
314
+ | `/` | search text, commands, paths and results (all words must match) |
315
+ | `f` / `F` | cycle the filter: all, chat, tools, skills, mcp, agents, errors |
316
+ | `t` | show thinking blocks |
317
+ | `n` / `N` | next / previous prompt |
318
+ | `x` / `X` | expand a subagent inline / expand or collapse all |
319
+ | `a` | open the subagent transcript for an Agent call (`esc` returns) |
320
+ | `g G` | top / bottom (bottom re-enables following) |
321
+ | `1 2 3 4 5`, `[ ]` | switch tabs |
322
+ | `esc` | clear the search or filter, then go back |
323
+ | `!` | jump to the latest alert |
324
+ | `A` / `D` | allow once / deny the session's permission request |
325
+ | `y` / `e` | copy the selection / export the view to Markdown |
326
+ | `?` | every key for the current screen |
327
+ | `q` | quit |
328
+
329
+ In the Tools tab, `space` expands or collapses a group, `enter` on a call
330
+ shows it in the timeline, and `←` and `→` collapse and expand (`←` on a call
331
+ moves to its group). Pressing `E` expands everything (press it again to
332
+ reset), and a `/` search keeps only matching calls with their groups opened.
333
+
334
+ In the Files tab, `T` switches between the list and a tree of folders. In
335
+ the tree, `space` and `enter` open or close a folder, `←` and `→` close and
336
+ open (`←` on a file moves to its folder), and `E` opens every folder (press
337
+ it again to reset).
338
+
339
+ In the Diff tab, `b` switches between the uncommitted changes and the whole
340
+ branch, and `B` picks the branch's base. Press `tab` to move between the
341
+ files and their lines, and `J` and `K` to jump between hunks. The keys `c`,
342
+ `v`, `C`, `e`, `x` and `S` work as described in
343
+ [Review and comment](#review-and-comment).
344
+
345
+ In the picker, `/` starts a fuzzy search and `f` finds across sessions, and
346
+ `esc` clears either. Pressing `c` toggles this project only, `s` switches to
347
+ the summary, and `w` opens the live board. On the picker and the live board,
348
+ `o` sorts by the next column and `O` reverses the order. Search results stay
349
+ best match first until you choose a column.
350
+
351
+ ## Notes
352
+
353
+ - The transcript format is undocumented and changes between Claude Code
354
+ versions. Unknown records are ignored, and bulky internal records
355
+ (`api-request*`, `attachment`, `file-history-*`) are skipped without being
356
+ decoded, so a 75 MB transcript loads in about 150 ms.
357
+ - It respects `CLAUDE_CONFIG_DIR`.
358
+ - Running `go run ./cmd/probe` parses every local transcript and reports
359
+ timings.
360
+ - The demo GIF is rendered from `demo/demo.tape` against fictional sessions
361
+ by `demo/render.sh`, which needs [vhs](https://github.com/charmbracelet/vhs).
362
+
363
+ This independent project isn't affiliated with or endorsed by Anthropic.
364
+ Claude and Claude Code are trademarks of Anthropic.
365
+
366
+ ## License
367
+
368
+ [MIT](https://github.com/jzills/snoop/blob/main/LICENSE)
@@ -0,0 +1,5 @@
1
+ snoop_cli-0.2.1.data/scripts/snoop.exe,sha256=IVvGg04Va5VYPlc6RZH-yznEY3bJPeItSBFP2nSUvJg,6198784
2
+ snoop_cli-0.2.1.dist-info/METADATA,sha256=p8hBjYN6Mo_kHh58FHl4OQuocpc5rrxiI5MNhmYNy9g,18123
3
+ snoop_cli-0.2.1.dist-info/WHEEL,sha256=GBN2EbvzoILK9l3i_NIZmpwZ2023qt8A87opqXiolII,101
4
+ snoop_cli-0.2.1.dist-info/LICENSE,sha256=zsxvwzMgztZJ-sC2i5FZJeDqx-am4du_DAZhYyb23XY,1082
5
+ snoop_cli-0.2.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: snoop scripts/wheels.py
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_arm64