elliot-stack 1.0.18 → 1.0.19
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 +11 -0
- package/bin/install.cjs +134 -49
- package/package.json +1 -1
- package/skills/estack-read-claude-session-history/SKILL.md +196 -0
- package/skills/estack-read-claude-session-history/references/jsonl-schema.md +126 -0
- package/skills/estack-read-claude-session-history/references/modes.md +366 -0
- package/skills/estack-read-claude-session-history/references/recipes.md +237 -0
- package/skills/estack-read-claude-session-history/scripts/lib/__init__.py +1 -0
- package/skills/estack-read-claude-session-history/scripts/lib/parser.py +460 -0
- package/skills/estack-read-claude-session-history/scripts/lib/paths.py +234 -0
- package/skills/estack-read-claude-session-history/scripts/lib/search.py +179 -0
- package/skills/estack-read-claude-session-history/scripts/lib/subagents.py +88 -0
- package/skills/estack-read-claude-session-history/scripts/lib/tools.py +144 -0
- package/skills/estack-read-claude-session-history/scripts/read_transcript.py +1448 -0
- package/skills/estack-read-claude-session-history/scripts/tests/conftest.py +40 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/README.md +20 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/all-noise.jsonl +4 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/basic-session.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/interrupted.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/multi-compact.jsonl +8 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/pending-user.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-no-meta/subagents/agent-aaa.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-no-meta.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent/subagents/agent-xyz123.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent/subagents/agent-xyz123.meta.json +1 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent.jsonl +4 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/time-spread.jsonl +6 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/timeline-day-test.jsonl +5 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/tool-zoo.jsonl +10 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/truncated.jsonl +3 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/unicode.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-advisor.jsonl +3 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-compact.jsonl +5 -0
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-thinking.jsonl +2 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_backup_roots.py +56 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_json_format.py +201 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_modes.py +199 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_parser.py +195 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_paths.py +133 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_search.py +78 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_subagents.py +43 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_timeline.py +175 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_timezone_and_project.py +212 -0
- package/skills/estack-read-claude-session-history/scripts/tests/test_tools.py +80 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# Mode reference
|
|
2
|
+
|
|
3
|
+
Every mode of `read_transcript.py`, with all flags, exit codes, and worked examples.
|
|
4
|
+
|
|
5
|
+
For the high-level decision tree, see `../SKILL.md`. For the JSONL schema, see `jsonl-schema.md`. For multi-step workflows, see `recipes.md`.
|
|
6
|
+
|
|
7
|
+
## CLI grammar
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
python read_transcript.py [--root <root>] [--cwd <path> | --all-projects | --project <name> | --file <path>]
|
|
11
|
+
[--since <spec>] [--until <spec>] [--tz <spec>]
|
|
12
|
+
--mode <mode> [mode-specific flags]
|
|
13
|
+
[--format json] [--exclude-current] [--include-subagents] [-n N]
|
|
14
|
+
[--force-dump]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Global flag notes:
|
|
18
|
+
- `--project <name>` — case-insensitive substring filter on project directory names (encoded or decoded form). Applies to `list`, `journal`, `search`, `count`, `find`, `timeline`. Exit 1 when nothing matches.
|
|
19
|
+
- `--tz <spec>` — display timezone: IANA name (`America/New_York`), `UTC`, or fixed offset (`+5`, `-4`, `+05:30`, `UTC-4`). Default is system local time. All displayed timestamps AND `--since/--until/--date` interpretation use this zone.
|
|
20
|
+
- `--format json` (alias `--json`) — structured output on every mode except the legacy `--list`/`--list-subagents` aliases. Shapes per mode are listed below.
|
|
21
|
+
|
|
22
|
+
Legacy flags are preserved unchanged:
|
|
23
|
+
- `--list` (alias for `--mode list` with the v1 column layout)
|
|
24
|
+
- `--list-subagents` (alias for `--mode subagent-list` with the v1 column layout)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Single-session modes
|
|
29
|
+
|
|
30
|
+
### `last`
|
|
31
|
+
|
|
32
|
+
Last N assistant text outputs.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python read_transcript.py --file <path> --mode last [-n 5]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- Default N = 5.
|
|
39
|
+
- With `--include-subagents`, appends each subagent's final assistant message tagged `[subagent <id-short> · <agentType>]`.
|
|
40
|
+
|
|
41
|
+
### `advisor`
|
|
42
|
+
|
|
43
|
+
All advisor responses (the contents of every `advisor_tool_result` block).
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python read_transcript.py --file <path> --mode advisor
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `pre-compact`
|
|
50
|
+
|
|
51
|
+
40 message-exchanges before the most recent `/compact`.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python read_transcript.py --file <path> --mode pre-compact
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If no `/compact` marker is present, falls back to `mode_last(10)` with a note.
|
|
58
|
+
|
|
59
|
+
### `dump`
|
|
60
|
+
|
|
61
|
+
Human-readable conversation dump (text only, last 80 messages by default).
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python read_transcript.py --file <path> --mode dump [--include-subagents] [--force-dump]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Size-aware fallback:** transcripts larger than 5 MB auto-degrade to `pre-compact` (or `last` if no compact marker), with a stderr note. Override with `--force-dump`.
|
|
68
|
+
|
|
69
|
+
### `debug`
|
|
70
|
+
|
|
71
|
+
Structural diagnostic — prints entry type distribution, content block types, advisor probe, compact-marker probe, and sample signal entries. Use this first when a mode returns empty/unexpected results.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
python read_transcript.py --file <path> --mode debug
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `brief`
|
|
78
|
+
|
|
79
|
+
6-line single-session summary. Designed for fan-out triage: 14 parallel `brief` calls reproduce a 14-subagent investigation deterministically.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python read_transcript.py --file <path> --mode brief [--include-subagents]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Output format:
|
|
86
|
+
```
|
|
87
|
+
<uuid> · <decoded-project> · <mtime> · <status> [*]<if current>
|
|
88
|
+
intent: <first user prompt, 200ch>
|
|
89
|
+
last: <last assistant text, 200ch>
|
|
90
|
+
edits: <N> files — <top-3 paths>
|
|
91
|
+
tools: Bash=X Edit=Y Read=Z …
|
|
92
|
+
subagents: <N> spawned [<agentType counts>]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
With `--include-subagents`, appends each subagent's final assistant message.
|
|
96
|
+
|
|
97
|
+
### `changelog`
|
|
98
|
+
|
|
99
|
+
`HH:MM:SS TOOL one-line-summary`, day-grouped.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python read_transcript.py --file <path> --mode changelog
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `file-edits`
|
|
106
|
+
|
|
107
|
+
Unique file paths touched, sorted alphabetically. Multiple operations on the same file get a count suffix.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
python read_transcript.py --file <path> --mode file-edits
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `tool-calls`
|
|
114
|
+
|
|
115
|
+
Timestamped per-call blocks, with formatted args.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
python read_transcript.py --file <path> --mode tool-calls [--tool Bash,Edit]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`--tool` filters to a comma-separated subset.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Discovery modes
|
|
126
|
+
|
|
127
|
+
### `list`
|
|
128
|
+
|
|
129
|
+
Enriched session table.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Single project
|
|
133
|
+
python read_transcript.py --cwd <path> --mode list [--since 7d] [--exclude-current]
|
|
134
|
+
|
|
135
|
+
# All projects
|
|
136
|
+
python read_transcript.py --all-projects --mode list [--since today]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Columns: marker (`[*]` if current), mtime, size, uuid-short, msg count, flags (`[C]`=compact, `[S]`=subagents), status (✓!?●), decoded project name (when multi-project), title.
|
|
140
|
+
|
|
141
|
+
For byte-identical v1 output, use the legacy `--list` flag.
|
|
142
|
+
|
|
143
|
+
### `lookup`
|
|
144
|
+
|
|
145
|
+
Resolve a UUID prefix to an absolute path.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
python read_transcript.py --mode lookup --uuid <prefix>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- Exit 0: prints absolute path.
|
|
152
|
+
- Exit 1: no match.
|
|
153
|
+
- Exit 2: ambiguous prefix — prints all matches.
|
|
154
|
+
|
|
155
|
+
### `find`
|
|
156
|
+
|
|
157
|
+
Search session metadata by title or first prompt.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
python read_transcript.py --mode find --title "supabase"
|
|
161
|
+
python read_transcript.py --mode find --first-prompt "fix the bug"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `resume-cmd`
|
|
165
|
+
|
|
166
|
+
Generate a `cd <cwd>; claude --resume <uuid>` snippet for a UUID prefix.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python read_transcript.py --mode resume-cmd --uuid <prefix>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The original CWD cannot be unambiguously recovered from the encoded directory name; the snippet includes a `<original cwd>` placeholder plus the decoded display name as a hint.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Search modes
|
|
177
|
+
|
|
178
|
+
### `search`
|
|
179
|
+
|
|
180
|
+
Cross-scope search with role + channel filters.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Single file
|
|
184
|
+
python read_transcript.py --file <path> --mode search --query "<q>"
|
|
185
|
+
|
|
186
|
+
# Whole project
|
|
187
|
+
python read_transcript.py --cwd <path> --mode search --query "<q>"
|
|
188
|
+
|
|
189
|
+
# All projects
|
|
190
|
+
python read_transcript.py --all-projects --mode search --query "<q>"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Flags:
|
|
194
|
+
- `--role {user,assistant,both}` (default `both`)
|
|
195
|
+
- `--in {text,tool_use,thinking,all}` (default `text`)
|
|
196
|
+
- `--since` / `--until`
|
|
197
|
+
|
|
198
|
+
`--in tool_use` searches the `name + JSON-stringified input` of every `tool_use` block — useful for finding "the session where I ran `git push --force`".
|
|
199
|
+
|
|
200
|
+
`--in thinking` searches `thinking` blocks (model reasoning).
|
|
201
|
+
|
|
202
|
+
### `count`
|
|
203
|
+
|
|
204
|
+
Count sessions matching a query.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python read_transcript.py --mode count --query "<q>" [--all-projects] [--since 30d]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
stdout: integer session count.
|
|
211
|
+
stderr: `<N> sessions, <M> total messages, <K> matches`.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Subagent modes
|
|
216
|
+
|
|
217
|
+
### `subagent-list`
|
|
218
|
+
|
|
219
|
+
List sibling subagents for a parent session.
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
python read_transcript.py --file <parent> --mode subagent-list
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Output: `mtime size agent-id type=<agentType> "<description>"`. The legacy `--list-subagents` flag preserves v1's simpler columns.
|
|
226
|
+
|
|
227
|
+
### `subagent-finals`
|
|
228
|
+
|
|
229
|
+
Every subagent's final assistant message, separated by `=== agent-<id> (<type>) ===` headers.
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
python read_transcript.py --file <parent> --mode subagent-finals
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### `subagent-tools`
|
|
236
|
+
|
|
237
|
+
Tool-call forensics on a single subagent (same output shape as `tool-calls`).
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
python read_transcript.py --mode subagent-tools --subagent <subagent-path>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `subagent-files`
|
|
244
|
+
|
|
245
|
+
Files touched by a single subagent (same output shape as `file-edits`).
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
python read_transcript.py --mode subagent-files --subagent <subagent-path>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Resume modes
|
|
254
|
+
|
|
255
|
+
### `resume-prev`
|
|
256
|
+
|
|
257
|
+
Banner + dump-style tail of the last 10 exchanges from the most-recent prior session in a project.
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
python read_transcript.py --cwd <path> --mode resume-prev [-n 10]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Aggregation modes
|
|
266
|
+
|
|
267
|
+
### `journal`
|
|
268
|
+
|
|
269
|
+
Per-session 5-line block: date·uuid·project / prompt / ended / edits / tools.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
python read_transcript.py --mode journal --since 7d [--cwd <path> | --all-projects | --project <name>]
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
JSON shape: array of session-summary objects (same fields as `list`).
|
|
276
|
+
|
|
277
|
+
### `timeline`
|
|
278
|
+
|
|
279
|
+
Block-grouped activity timeline across all sessions in a time window, with idle
|
|
280
|
+
gaps and active-time totals. Answers "where did my day go?" and "how much time on
|
|
281
|
+
X?". Defaults to all projects and today.
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Yesterday, everything
|
|
285
|
+
python read_transcript.py --mode timeline --date yesterday
|
|
286
|
+
|
|
287
|
+
# One project, today, stricter idle threshold
|
|
288
|
+
python read_transcript.py --mode timeline --project keel --date today --gap 5m
|
|
289
|
+
|
|
290
|
+
# Arbitrary window
|
|
291
|
+
python read_transcript.py --mode timeline --since 2026-06-01 --until 2026-06-03
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
How it works: every signal-message timestamp in the window is an activity event;
|
|
295
|
+
events across all sessions are merged chronologically and grouped into blocks
|
|
296
|
+
separated by gaps longer than `--gap` (default 15m). Each block lists the sessions
|
|
297
|
+
active in it with message counts; idle gaps are printed between blocks; a totals
|
|
298
|
+
line gives block count, summed active time, span, and session count.
|
|
299
|
+
|
|
300
|
+
Flags:
|
|
301
|
+
- `--date <spec>` — single-day window (midnight to midnight). Wins over `--since/--until`.
|
|
302
|
+
- `--since/--until` — arbitrary window (until defaults to now).
|
|
303
|
+
- `--gap <spec>` — idle threshold: `15m`, `20`, `1h`.
|
|
304
|
+
- `--cwd` / `--project` / `--all-projects` — scope (default: all projects).
|
|
305
|
+
- `--tz` — display timezone (timestamps render in it; the window is interpreted in it).
|
|
306
|
+
|
|
307
|
+
JSON shape: `{since, until, gap_minutes, blocks: [{start, end, duration_minutes,
|
|
308
|
+
sessions: [{uuid, project, title, path, events}]}], totals: {blocks,
|
|
309
|
+
active_minutes, sessions}}`.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Comparison modes
|
|
314
|
+
|
|
315
|
+
### `diff`
|
|
316
|
+
|
|
317
|
+
Timestamp-interleaved comparison of two sessions.
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
python read_transcript.py --mode diff --file-a <s1> --file-b <s2>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
For sibling-subagent comparison (when a fan-out spawned multiple agents with similar tasks):
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
python read_transcript.py --mode diff --subagents-of <parent>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Output is prefixed `A>` / `B>` (or with subagent id shorts).
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## JSON shapes per mode (`--format json`)
|
|
334
|
+
|
|
335
|
+
| Mode | Shape |
|
|
336
|
+
|---|---|
|
|
337
|
+
| `last` | `[{n_from_end, timestamp, text}]` |
|
|
338
|
+
| `advisor` | `[<advisor text>, …]` |
|
|
339
|
+
| `pre-compact` | `{found_compact, messages: [{role, timestamp, is_compact, text}]}` |
|
|
340
|
+
| `dump` | `[{role, timestamp, is_compact, text}]` |
|
|
341
|
+
| `debug` | `{entry_types, block_types, advisor_blocks, compact_markers}` |
|
|
342
|
+
| `brief` | session-summary object (+ `subagent_finals` with `--include-subagents`) |
|
|
343
|
+
| `list` / `journal` / `find` | array of session-summary objects |
|
|
344
|
+
| `lookup` | `{prefix, path, matches}` (same exit codes as text) |
|
|
345
|
+
| `resume-cmd` | `{uuid, path, project, encoded, command}` |
|
|
346
|
+
| `changelog` | `[{timestamp, tool, summary}]` |
|
|
347
|
+
| `tool-calls` / `subagent-tools` | `[{timestamp, tool, summary, input}]` |
|
|
348
|
+
| `file-edits` / `subagent-files` | `[{path, ops}]` |
|
|
349
|
+
| `search` | `[{session, mtime_iso, role, where, timestamp, window}]` |
|
|
350
|
+
| `count` | `{sessions, messages, matches}` |
|
|
351
|
+
| `subagent-list` | `[{id, agentType, description, path, size_kb, mtime_iso}]` |
|
|
352
|
+
| `subagent-finals` | `[{id, agentType, text}]` |
|
|
353
|
+
| `resume-prev` | `{session, path, mtime_iso, messages}` |
|
|
354
|
+
| `diff` | `{a, b, messages: [{source, role, timestamp, text}]}` |
|
|
355
|
+
| `timeline` | see the `timeline` section above |
|
|
356
|
+
|
|
357
|
+
Session-summary object fields: `path, uuid, mtime, mtime_iso, size, exists, title,
|
|
358
|
+
first_prompt, last_assistant, last_activity, msg_count, edit_count, tool_counts,
|
|
359
|
+
files_touched, subagent_count, subagent_types, has_compact, has_subagents, cwd,
|
|
360
|
+
decoded_project, status, is_current`.
|
|
361
|
+
|
|
362
|
+
## Exit codes
|
|
363
|
+
|
|
364
|
+
- `0`: success
|
|
365
|
+
- `1`: missing required flag, no match (including `--project` with zero matches), or file not found
|
|
366
|
+
- `2`: ambiguous result (e.g. UUID prefix matches multiple sessions)
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Recipes
|
|
2
|
+
|
|
3
|
+
Multi-step workflows. For per-mode flag reference, see `modes.md`. For schema, see `jsonl-schema.md`.
|
|
4
|
+
|
|
5
|
+
In all examples, `$PY` refers to:
|
|
6
|
+
```
|
|
7
|
+
C:\Users\2supe\.claude\skills\read-claude-session-history\scripts\read_transcript.py
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Post-`/compact` recovery
|
|
13
|
+
|
|
14
|
+
When `/compact` has rolled the conversation and you need what fell off the back end:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Step 1: Recover the long version of recent assistant output
|
|
18
|
+
python "$PY" --file <current-session.jsonl> --mode pre-compact
|
|
19
|
+
|
|
20
|
+
# Step 2: If advisor responses were involved, grab those separately
|
|
21
|
+
python "$PY" --file <current-session.jsonl> --mode advisor
|
|
22
|
+
|
|
23
|
+
# Step 3: If a search would be faster than reading the whole pre-compact section
|
|
24
|
+
python "$PY" --file <current-session.jsonl> --mode search --query "<keyword>"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `pre-compact` window is 40 message-exchanges before the most recent compact. If multiple `/compact` events fired, only the most recent is used as the anchor.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. Find-then-dump (resume work from a session you can't name)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Step 1: Find by partial title or first prompt
|
|
35
|
+
python "$PY" --mode find --title "supabase"
|
|
36
|
+
# → returns a list, including the full session UUIDs
|
|
37
|
+
|
|
38
|
+
# Step 2: Get a 6-line summary to confirm it's the right one
|
|
39
|
+
python "$PY" --file <picked-session>.jsonl --mode brief
|
|
40
|
+
|
|
41
|
+
# Step 3: Dump the recent context to ground yourself
|
|
42
|
+
python "$PY" --file <picked-session>.jsonl --mode dump -n 20
|
|
43
|
+
|
|
44
|
+
# Step 4: Get the resume command for that session
|
|
45
|
+
python "$PY" --mode resume-cmd --uuid <8-char-prefix>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 3. Fan-out triage (you spawned N parallel subagents and want every output)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Option A: Get all subagent finals in one shot, separated by headers
|
|
54
|
+
python "$PY" --file <parent-session>.jsonl --mode subagent-finals
|
|
55
|
+
|
|
56
|
+
# Option B: Triage with a brief that includes subagent finals folded in
|
|
57
|
+
python "$PY" --file <parent-session>.jsonl --mode brief --include-subagents
|
|
58
|
+
|
|
59
|
+
# Option C: List first to see what types of agents ran
|
|
60
|
+
python "$PY" --file <parent-session>.jsonl --mode subagent-list
|
|
61
|
+
|
|
62
|
+
# Drill into one specific subagent's tools / files
|
|
63
|
+
python "$PY" --mode subagent-tools --subagent <subagent-path>
|
|
64
|
+
python "$PY" --mode subagent-files --subagent <subagent-path>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The `brief --include-subagents` output is the densest form of the standard "what did all my agents do" question and was designed for fan-out reproduction (14 parallel briefs ≡ a 14-subagent investigation).
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 4. Deletion-incident recovery (March 2026 auto-update bug, GitHub #41591)
|
|
72
|
+
|
|
73
|
+
When a live `.jsonl` has been wiped but the backup is intact:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Step 1: Find what's missing — list live vs snapshot side by side
|
|
77
|
+
python "$PY" --root live --cwd "C:\Users\2supe\Other Claude Code" --list > live.txt
|
|
78
|
+
python "$PY" --root snapshot-24h --cwd "C:\Users\2supe\Other Claude Code" --list > snap.txt
|
|
79
|
+
diff live.txt snap.txt
|
|
80
|
+
|
|
81
|
+
# Step 2: For each missing UUID, locate it in the snapshot
|
|
82
|
+
python "$PY" --root snapshot-24h --mode lookup --uuid <prefix>
|
|
83
|
+
|
|
84
|
+
# Step 3: Read it directly from the snapshot path
|
|
85
|
+
python "$PY" --file <snapshot-path>.jsonl --mode brief
|
|
86
|
+
python "$PY" --file <snapshot-path>.jsonl --mode dump
|
|
87
|
+
|
|
88
|
+
# Step 4: If the 24h snapshot is also affected, walk back further
|
|
89
|
+
python "$PY" --root snapshot-1w --mode lookup --uuid <prefix>
|
|
90
|
+
python "$PY" --root snapshot-1mo --mode lookup --uuid <prefix>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The four backup roots (`mirror`, `snapshot-24h`, `snapshot-1w`, `snapshot-1mo`) are managed by the daily backup task documented in `reference_claude_backup_system.md`.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 5. Week-in-review journal
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Every session in every project from the last 7 days
|
|
101
|
+
python "$PY" --all-projects --mode journal --since 7d
|
|
102
|
+
|
|
103
|
+
# Single project, with a hard upper bound
|
|
104
|
+
python "$PY" --cwd "C:\Users\2supe\Other Claude Code" \
|
|
105
|
+
--mode journal --since 2026-05-13 --until 2026-05-20
|
|
106
|
+
|
|
107
|
+
# By project name instead of path
|
|
108
|
+
python "$PY" --project keel --mode journal --since 7d
|
|
109
|
+
|
|
110
|
+
# Count how many sessions touched a topic
|
|
111
|
+
python "$PY" --all-projects --mode count --query "linkedin"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The output is one 5-line block per session: `date·uuid·project` / first prompt / last assistant message / N files edited / top tools.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 5b. Day accounting ("where did my day go?")
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Block-grouped timeline of yesterday across ALL projects, with idle gaps
|
|
122
|
+
python "$PY" --mode timeline --date yesterday
|
|
123
|
+
|
|
124
|
+
# How much time on one project today
|
|
125
|
+
python "$PY" --mode timeline --project keel --date today
|
|
126
|
+
|
|
127
|
+
# Tighter idle threshold (treat >5m quiet as a break between blocks)
|
|
128
|
+
python "$PY" --mode timeline --date today --gap 5m
|
|
129
|
+
|
|
130
|
+
# Multi-day window
|
|
131
|
+
python "$PY" --mode timeline --since 2026-06-01 --until 2026-06-03
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Reading the output: each block is a contiguous stretch of activity (events ≤ gap
|
|
135
|
+
apart); the sessions inside it are listed with message counts; `── idle Xm ──`
|
|
136
|
+
lines mark the breaks; the totals line gives summed active time vs. span.
|
|
137
|
+
|
|
138
|
+
Caveat: this measures *Claude-visible* activity only — message timestamps, not
|
|
139
|
+
attention or time spent away from Claude.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 5c. Piping structured output into a next step
|
|
144
|
+
|
|
145
|
+
Every mode supports `--format json`. **Run pipe chains in Bash** (the Bash tool /
|
|
146
|
+
git-bash) — they work exactly as written:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Pull the paths of yesterday's sessions for batch processing
|
|
150
|
+
python "$PY" --mode list --all-projects --since yesterday --format json \
|
|
151
|
+
| python -c "import json,sys; [print(s['path']) for s in json.load(sys.stdin)]"
|
|
152
|
+
|
|
153
|
+
# Machine-readable day totals
|
|
154
|
+
python "$PY" --mode timeline --date yesterday --format json \
|
|
155
|
+
| python -c "import json,sys; t=json.load(sys.stdin)['totals']; print(t['active_minutes'], 'min across', t['sessions'], 'sessions')"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
PowerShell warnings (5.1):
|
|
159
|
+
- Piping between native commands injects a UTF-8 BOM and re-encodes through the
|
|
160
|
+
console codepage (can corrupt non-ASCII transcript content). If you must pipe
|
|
161
|
+
in PowerShell, read stdin as `utf-8-sig`:
|
|
162
|
+
`python -c "import io,json,sys; data=json.load(io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8-sig'))"`
|
|
163
|
+
- `>` redirection writes UTF-16 — read redirected files with `encoding='utf-16'`.
|
|
164
|
+
|
|
165
|
+
Prefer Bash for any JSON chaining; prefer either shell for plain single commands.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 6. Sibling-agent diff
|
|
170
|
+
|
|
171
|
+
When you ran two subagents on the same task and want to see where they diverged:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Auto-pick the first two subagents of a session
|
|
175
|
+
python "$PY" --mode diff --subagents-of <parent-session>.jsonl
|
|
176
|
+
|
|
177
|
+
# Explicit pairing
|
|
178
|
+
python "$PY" --mode diff \
|
|
179
|
+
--file-a <parent-uuid>/subagents/agent-aaa.jsonl \
|
|
180
|
+
--file-b <parent-uuid>/subagents/agent-bbb.jsonl
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Output is timestamp-interleaved, prefixed `A>` / `B>`. Use it to spot disagreement (e.g. one agent recommended X and the other recommended Y) without reading both transcripts in full.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 7. "What is this session actually for?" (cold open on a stale UUID)
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Single-shot orientation in under a second
|
|
191
|
+
python "$PY" --file <unknown-session>.jsonl --mode brief
|
|
192
|
+
|
|
193
|
+
# If you need more than 200 chars of context per line
|
|
194
|
+
python "$PY" --file <unknown-session>.jsonl --mode last -n 3
|
|
195
|
+
python "$PY" --file <unknown-session>.jsonl --mode changelog | tail -30
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`brief` is the recommended default for triaging a session you've never read.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 8. Tool-call forensics ("when did I last `git push --force`?")
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Find every tool_use whose JSON args contain a substring, across all sessions
|
|
206
|
+
python "$PY" --all-projects --mode search --query "git push --force" --in tool_use
|
|
207
|
+
|
|
208
|
+
# Get full forensics on the session that matched
|
|
209
|
+
python "$PY" --file <matching-session>.jsonl --mode tool-calls --tool Bash
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 9. Resume previous session in the current project
|
|
215
|
+
|
|
216
|
+
If you just `cd`'d into a project and want to pick up where you left off:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
python "$PY" --cwd "$(pwd)" --mode resume-prev -n 15
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Prints `--- Resuming from <uuid> (<mtime>) ---` then the last 15 exchanges.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 10. Schema drift / silent empty results
|
|
227
|
+
|
|
228
|
+
When a mode returns nothing and you don't know why:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
python "$PY" --file <session>.jsonl --mode debug
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Look for:
|
|
235
|
+
- Unfamiliar `type:` values appearing in the distribution (parser might be dropping them as noise).
|
|
236
|
+
- An absent `advisor_tool_result` block when you expected advisor output.
|
|
237
|
+
- Missing `compact` markers in a session you know got compacted.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Library modules for read_transcript."""
|