chsum 3.0.2__tar.gz → 3.0.4__tar.gz

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.
Files changed (35) hide show
  1. chsum-3.0.4/PKG-INFO +643 -0
  2. chsum-3.0.4/README.md +632 -0
  3. {chsum-3.0.2 → chsum-3.0.4}/chsum/checkpoints.py +139 -75
  4. {chsum-3.0.2 → chsum-3.0.4}/chsum/core.py +1119 -38
  5. {chsum-3.0.2 → chsum-3.0.4}/pyproject.toml +1 -1
  6. chsum-3.0.4/skills/chsum/SKILL.md +120 -0
  7. chsum-3.0.4/skills/chsum/references/checkpoints.md +45 -0
  8. chsum-3.0.4/skills/chsum/references/debugging.md +9 -0
  9. chsum-3.0.4/skills/chsum/references/naming.md +12 -0
  10. chsum-3.0.4/skills/chsum/references/noting.md +29 -0
  11. chsum-3.0.4/skills/chsum/references/recap.md +15 -0
  12. chsum-3.0.4/tests/test_branches.py +192 -0
  13. chsum-3.0.4/tests/test_handbacks.py +190 -0
  14. chsum-3.0.4/tests/test_undo.py +366 -0
  15. {chsum-3.0.2 → chsum-3.0.4}/tests/test_views.py +1 -1
  16. chsum-3.0.2/PKG-INFO +0 -1068
  17. chsum-3.0.2/README.md +0 -1057
  18. chsum-3.0.2/skills/chsum/SKILL.md +0 -185
  19. chsum-3.0.2/skills/chsum/references/checkpoints.md +0 -54
  20. chsum-3.0.2/skills/chsum/references/debugging.md +0 -13
  21. chsum-3.0.2/skills/chsum/references/naming.md +0 -14
  22. chsum-3.0.2/skills/chsum/references/noting.md +0 -54
  23. chsum-3.0.2/skills/chsum/references/recap.md +0 -30
  24. {chsum-3.0.2 → chsum-3.0.4}/.gitignore +0 -0
  25. {chsum-3.0.2 → chsum-3.0.4}/CONTRIBUTING.md +0 -0
  26. {chsum-3.0.2 → chsum-3.0.4}/LICENSE +0 -0
  27. {chsum-3.0.2 → chsum-3.0.4}/chsum/__init__.py +0 -0
  28. {chsum-3.0.2 → chsum-3.0.4}/chsum/__main__.py +0 -0
  29. {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/__init__.py +0 -0
  30. {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/claude.py +0 -0
  31. {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/codex.py +0 -0
  32. {chsum-3.0.2 → chsum-3.0.4}/chsum.py +0 -0
  33. {chsum-3.0.2 → chsum-3.0.4}/tests/harness.py +0 -0
  34. {chsum-3.0.2 → chsum-3.0.4}/tests/test_checkpoints.py +0 -0
  35. {chsum-3.0.2 → chsum-3.0.4}/tests/test_codex_source.py +0 -0
chsum-3.0.4/PKG-INFO ADDED
@@ -0,0 +1,643 @@
1
+ Metadata-Version: 2.5
2
+ Name: chsum
3
+ Version: 3.0.4
4
+ Summary: Work logs and reload-ready context from coding-agent conversations. Deterministic: no model, nothing invented.
5
+ Author: InDate
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: claude,claude-code,context,transcripts,work-log
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Chat Summary (chsum)
13
+
14
+ Pick up from where you left off with deterministic summaries of previous
15
+ sessions. Replay the last 10 messages, or a range of specific messages between
16
+ you and the agent, or get a digest of everything you typed with the tools used
17
+ and files changed. This rehydrates context surgically.
18
+
19
+ ```sh
20
+ chsum digest --last # everything you typed, tools used, files changed
21
+ chsum digest --last --messages -10 -1 # the last 10 messages
22
+ chsum digest --last --messages 3 10 # a range of them
23
+ ```
24
+
25
+ I've turned off auto-compact and use all my context tokens, knowing I can start
26
+ the next session with one command: `chsum digest --last`.
27
+
28
+ chsum also:
29
+
30
+ - **Undo a change inside a session**, one change at a time, no matter the tool
31
+ used to change the file. To use it: when chsum is first loaded into a
32
+ git-enabled repo, the agent asks if you want checkpointing enabled. See the
33
+ [implementation details](#checkpoints-and-undo) below.
34
+ - **Load back an abandoned path.** Started a session, then rewound to a
35
+ specific spot to continue along another path? chsum makes it easy to load
36
+ back the other, "abandoned" path with `chsum digest --branches`. See the
37
+ [implementation details](#branches) on how this works.
38
+ - **See what a subagent is doing** before its report arrives. A session
39
+ launches an agent and cannot get its details without overloading its own
40
+ context. chsum works around that by sharing condensed updates of the files
41
+ being edited, with just the short prose an agent normally outputs between
42
+ them. The session can easily see whether the agent has sidetracked, and give
43
+ clear nudges to correct it, or stop it. See the
44
+ [implementation details](#subagents) for how this works.
45
+ - **Mark a moment to get back to.** Something interesting happened during a
46
+ session and you want to get back to it easily? Use `chsum mark "<reason>"`
47
+ inside the conversation, and the previous reply is included in the digests.
48
+ See the [implementation details](#marks) for how this works.
49
+
50
+ It reads Claude Code and Codex CLI sessions alike.
51
+
52
+ Run `chsum` to list this project's sessions:
53
+
54
+ ```
55
+ Sessions — chsum
56
+ 5 sessions · 1 with no activity
57
+
58
+ Fri 02 Oct 2026 dur prompts files agents branches notes digest recap
59
+ ch_92e5397d588f409d6ca4b843317d4f97 2h37m 57 8 - 3 - - -
60
+ ↳ Commit staged changes
61
+ ch_34fa3ce4453202d47be9c173100427ef 1h00m 11 1 - 2 - - -
62
+ ↳ Fitness landscape digest --branches feature
63
+
64
+ Fri 25 Sep 2026
65
+ ch_c4e516f02a4084eb9e1daf3bc2b1ab85 1h10m 19 3 - 2 - - -
66
+ ↳ Chsum digest output formatting
67
+ ch_f111160d4a5e2b477d689babcba77d35 1m 1 0 - - - - -
68
+ ↳ Bench screenshots during recording
69
+ ch_3f91d2af6f621b4b61790a280fafb5e3 1s 0 0 - - - - -
70
+ ↳ (untitled)
71
+
72
+ Read one: `chsum digest <ref> --stdout` Most recent real session: `chsum digest --last --stdout`
73
+ ```
74
+
75
+ ## What to run
76
+
77
+ | You want | Run |
78
+ |---|---|
79
+ | What we did yesterday, or to pick up where we left off | `chsum digest --last` |
80
+ | The context of an old session in a new one | `chsum digest <ref> --stdout` |
81
+ | What Claude did with each thing you said | `chsum recap` |
82
+ | What Claude has done so far, from a second terminal | `chsum recap` |
83
+ | Which session it was, and which went anywhere | `chsum` |
84
+ | A session by what was said in it | `chsum find "…"` |
85
+ | The exact command Claude ran, or its output | `chsum digest <ref> --commands`, `--call <id>` |
86
+ | A subagent's report, or everything it did | `chsum digest --agents`, `<ref>/<agent-id>` |
87
+ | The raw record behind `01a0acf9:31` | `chsum where 01a0acf9:31` |
88
+ | This session's ref | `chsum here` |
89
+ | The path a rewind left behind | `chsum digest <ref> --branches` |
90
+ | A change Claude made, taken back | `chsum undo` |
91
+ | The moment that mattered, findable later | `chsum note "…"` |
92
+ | A session titled for what it became | `chsum name "…"` |
93
+ | This week's work, across projects | `chsum --since 7d --all -n 0` |
94
+ | Your notes in claude-history's viewer | [`chsum annotations`](#chsum-annotations) |
95
+
96
+ Coming from 2.x: [what changed](#upgrading-to-30).
97
+
98
+ ## Install
99
+
100
+ As a Claude Code plugin, which brings the skill, the hooks and the code:
101
+
102
+ ```
103
+ /plugin marketplace add InDate/indate-tools
104
+ /plugin install chsum@indate-tools
105
+ ```
106
+
107
+ The hooks run the `chsum.py` beside them, so nothing needs to be on `PATH`.
108
+ For a `chsum` command of your own, link that file once:
109
+
110
+ ```sh
111
+ ln -s ~/.claude/plugins/cache/indate-tools/chsum/<version>/chsum.py ~/.local/bin/chsum
112
+ ```
113
+
114
+ Working on chsum itself: `pipx install --editable .` from the checkout.
115
+
116
+ Requirements:
117
+
118
+ - Python 3.10+. No third-party packages, no network.
119
+ - [`claude-history`](https://github.com/raine/claude-history) on `PATH`, for
120
+ `chsum find` only.
121
+ - `claude` on `PATH`, for `chsum recap`'s timeline only.
122
+
123
+ ### Letting Claude run it
124
+
125
+ `! chsum …` runs it yourself. For Claude to run it unprompted, allow it in
126
+ `~/.claude/settings.json` or a project's `.claude/settings.local.json`:
127
+
128
+ ```json
129
+ { "permissions": { "allow": ["Bash(chsum:*)"] } }
130
+ ```
131
+
132
+ chsum reads transcripts you already have and writes to its own store (see
133
+ [Where chsum writes](#where-chsum-writes)); `undo` and `redo` also write the
134
+ files they restore. A plugin cannot grant itself this permission.
135
+
136
+ ## Picking a conversation, and a window of it
137
+
138
+ `recap` and `digest` take the same selectors:
139
+
140
+ ```sh
141
+ chsum digest # the session you are in
142
+ chsum digest ch_3654a13c # by the ref the listing prints
143
+ chsum digest --last # the newest session other than this one
144
+ chsum digest --last 2 # the one before that
145
+ chsum digest --file path/to/session.jsonl
146
+ chsum digest --messages 3 10 # your turns 3 to 10
147
+ chsum digest --messages -1 # your last turn, and everything after it
148
+ chsum digest ch_da4e…/a728cd49… # one subagent, as <parent-ref>/<agent-id>
149
+ ```
150
+
151
+ A turn is one thing you typed, or one answer you picked from a question, and
152
+ everything up to your next. `1` is your first and `-1` your last; two numbers
153
+ name a run, both ends included. The header states what they resolved to:
154
+ `-10 -1 — your turns 45–54 of 54`.
155
+
156
+ `--last` orders by last activity. Everything scopes to the current project;
157
+ `--all` widens it.
158
+
159
+ ## `chsum`
160
+
161
+ The project's sessions, newest activity first:
162
+
163
+ ```
164
+ Thu 06 Aug 2026 dur prompts files agents branches notes digest recap
165
+ ch_c120431a267b202aebf0b38f6c3c1b69 5h38m 78 14 - - ⚑2 current 3/12 · 2h ago
166
+ ↳ Plan the import pipeline from the sample files
167
+
168
+ Wed 05 Aug 2026
169
+ ch_da4e99d42e5efab11ebdedc22fb65145 3h03m 30 12 2 2 - stale -
170
+ ↳ Set up the dev server
171
+ a43c4ff4401ca693e Quieten the test suite
172
+ a81d77b6cba4a46b3 Fix the retry backoff
173
+ ```
174
+
175
+ ```sh
176
+ chsum # the five most recent
177
+ chsum -n 25 # more; 0 for all
178
+ chsum --since 7d # the last week
179
+ chsum --all # every project, with a project column
180
+ ```
181
+
182
+ - **Dead ends are listed**, since "that went nowhere" is often the answer. The
183
+ header counts them: one prompt, no files, no agents.
184
+ - **Subagents are named**, with the id `chsum digest <ref>/<id>` takes.
185
+ - **`branches`** counts the paths a rewind left; `chsum digest <ref> --branches`
186
+ lists them.
187
+ - **`digest`** is `current`, `stale` (the transcript has grown since) or `-`.
188
+ - **`recap`** is turns recapped over turns there are, and when.
189
+ - **`✎`** marks a title you gave with `chsum name`.
190
+
191
+ ## `chsum recap`
192
+
193
+ What Claude did with what you said. Each of your turns quoted, then everything
194
+ before you spoke again: files touched, commands, agents and failures, computed
195
+ from the transcript, and beneath them a timeline written by
196
+ `claude -p --model haiku` from that turn's events alone.
197
+
198
+ ```sh
199
+ chsum recap # this session, since the last recap
200
+ chsum recap --last # the previous session
201
+ chsum recap ch_3654a13c --messages 3 10 # turns 3 to 10 of a session
202
+ chsum recap --full # the whole session
203
+ chsum recap --messages 3 10 --dry-run # the cost, no model call
204
+ chsum recap --messages 3 10 --invalidate # summarise again, replacing what's stored
205
+ chsum recap --messages 3 10 --no-cache # neither read nor write the store
206
+ ```
207
+
208
+ ```
209
+ ### You said (21:43)
210
+
211
+ > ok
212
+
213
+ - **21:45** Created a new `is_typed_prompt()` helper that filters out
214
+ `<bash-…>` records, and updated five call sites to use it.
215
+ - **21:47** Tested the fix against a live session; chsum now reports
216
+ `prompts: 0` for the dead 2-second session and skips it.
217
+ ```
218
+
219
+ ### The bare run
220
+
221
+ `chsum recap` with nothing after it is the running session since your last
222
+ prompt, failures first. Run it from a second terminal while Claude works; there
223
+ it lists the project's recent sessions and Enter takes the newest.
224
+
225
+ ### Cost
226
+
227
+ Each turn is its own small `claude -p` call, run in parallel, with Claude Code's
228
+ system prompt and tools stripped to about 158 tokens of fixed cost. `--dry-run`
229
+ prices a window without calling; after a real run one line on stderr gives what
230
+ it cost:
231
+
232
+ ```
233
+ haiku: 5,974 in (5,042 cache read) · 4,866 out · 56.0s · extract estimated ~3,211, harness ~2,763
234
+ ```
235
+
236
+ A turn's bullets are stored once its gap closes, so recapping a window twice
237
+ costs nothing the second time. They are reused only while the instructions, the
238
+ model and the turn's events are unchanged. `0 calls would be made` means the
239
+ window is already stored.
240
+
241
+ ### Files touched
242
+
243
+ Each turn's files come from a git checkpoint where one exists (every change,
244
+ current line ranges) and from the transcript otherwise (`Edit`, `Write` and
245
+ `MultiEdit` only). The recap counts which: `4 of 6 turns from a checkpoint`.
246
+ Checkpoints are opt-in; see [`chsum hook`](#chsum-hook).
247
+
248
+ ## `chsum digest`
249
+
250
+ One conversation: your prompts in order, the files changed and commands that did
251
+ something, the last exchange, and the `sed` line that opens any row. It writes a
252
+ file and prints the path; `--stdout` prints the document instead. Every view
253
+ below follows that rule.
254
+
255
+ https://github.com/user-attachments/assets/93f3cdac-cf82-403a-8333-5c8e42159fd7
256
+
257
+ ```sh
258
+ chsum digest # this session
259
+ chsum digest <ref> --stdout # that one, printed
260
+ chsum digest <ref>/<agent-id> # one subagent
261
+ chsum digest --list # this project's digest files; --all every project
262
+ ```
263
+
264
+ | Section | Source |
265
+ |---|---|
266
+ | Frontmatter: ref, title, project, branch, start, duration, counts | computed |
267
+ | **Notable**: your `chsum note`s | copied |
268
+ | **What I asked for**: your prompts, each with its row and what the turn did | copied |
269
+ | **Files changed** / **Commands run** | parsed from tool calls |
270
+ | **Delegated**: each subagent and its address | parsed from sidecars |
271
+ | **Where I left off**: last prompt and last reply | copied |
272
+ | **Drill down**: transcript paths and the `sed` that opens a row | computed |
273
+
274
+ ```
275
+ > when I do --list on a note, it prints out the entire directory which looks terrible
276
+
277
+ *`49932ac7:37` · 19s · 2 commands · 1 reply*
278
+ ```
279
+
280
+ - **A row is an address.** `1f271ca8:441` is line 441 of that session's
281
+ transcript; `1f271ca8/a190d601:87` is line 87 of a subagent's.
282
+ - **Cuts are marked.** `[+N chars, sed the row below]` and `…and N more` say
283
+ when you are reading a fragment.
284
+ - **"Where I left off" is two scans.** The last prompt and the last reply may be
285
+ far apart.
286
+ - **A subagent's work counts toward the turn that launched it**; files only an
287
+ agent touched are marked `(agent)`.
288
+
289
+ ### The row views
290
+
291
+ ```sh
292
+ chsum digest <ref> --messages # every message whole, each call a line between
293
+ chsum digest <ref> --tools # every tool call
294
+ chsum digest <ref> --commands # every Bash call
295
+ chsum digest <ref> --call <id> # one call and its output, whole
296
+ chsum digest <ref> --agents # every subagent and its report
297
+ chsum digest <ref> --writes # each turn's file changes, from the checkpoints
298
+ chsum digest <ref> --branches # the paths a rewind left; --branches <n> resumes one
299
+ chsum digest <ref>/<agent-id> --messages # everything that agent said and called
300
+ ```
301
+
302
+ Each writes `<uuid>-<view>.md` beside the digest. Rows run in time order across
303
+ the transcript and its sidecars, each opening with its call id and a
304
+ `<session>:<line>` locator, grouped under turn headings:
305
+
306
+ ```
307
+ *turn 8 · 16m · 6 tool calls · 5 files · 108 commands · 12 replies*
308
+ ```
309
+
310
+ Numbers after `--messages`, `--tools` or `--commands` narrow to a window of your
311
+ turns; there `--tools` and `--commands` print their rows whole:
312
+
313
+ ```sh
314
+ chsum digest --last --messages -1 # your last turn
315
+ chsum digest <ref> --tools -5 -1 # calls across your last five turns
316
+ chsum digest <ref>/<agent-id> --tools 2 -1 # an agent's own turns
317
+ ```
318
+
319
+ - **Each message is labelled by its sender**: `user`, `assistant`,
320
+ `agent … returned`, `message from <session>`, `coordinator`. Only what you
321
+ typed opens a turn.
322
+ - **Skipped rows are named** inside a window: `⋯ 4 rows not in this view`, each
323
+ with its locator.
324
+ - **`## Sources`** at the top maps every locator to its file.
325
+
326
+ ## `chsum where`
327
+
328
+ A locator chsum printed, turned into the command that prints that record:
329
+
330
+ ```
331
+ $ chsum where 01a0acf9:31
332
+ sed -n '31p' ~/.local/share/chsum/translated/codex/…/01a0acf9-….jsonl | jq
333
+ ```
334
+
335
+ | You have | You type |
336
+ |---|---|
337
+ | one row | `chsum where 01a0acf9:31` |
338
+ | a run of rows | `chsum where 01a0acf9:31-40` |
339
+ | a subagent's row | `chsum where 01a0acf9/a9f0f78b:3` |
340
+ | a session | `chsum where 01a0acf9` |
341
+ | a tool call id | `chsum where toolu_01V7rDx5Le` |
342
+
343
+ The command alone goes to stdout, so `chsum where 01a0acf9:31 | sh` runs it.
344
+ `--git` gives the checkpoint that call wrote and the `git diff` for it.
345
+
346
+ ## `chsum undo` and `chsum redo`
347
+
348
+ Take back a change made this session, file by file or step by step. A step is
349
+ one tool call's change to the tree; each file of a step is lettered.
350
+
351
+ ```
352
+ $ chsum undo
353
+ 28 steps in place, newest first
354
+ 1 chsum/core.py:7109-7110
355
+ 2 a chsum/core.py:7076
356
+ b tests/test_undo.py:63-66
357
+ 3 chsum/checkpoints.py:65
358
+ ```
359
+
360
+ ```sh
361
+ chsum undo 1 # reverse the newest step; again for the one before
362
+ chsum undo 2b # one file of step 2
363
+ chsum undo 1-3 # the three newest
364
+ chsum undo 2 --detail # the step's diff; nothing changes
365
+ chsum undo --detail # every step's diff; --reverse puts the newest last
366
+ chsum undo README.md # that file's changes, numbered 1 newest
367
+ chsum undo README.md 2 # reverse change 2 to it alone
368
+ chsum redo 1 # put back the last undo
369
+ ```
370
+
371
+ - **Ask Claude to undo**, and Claude Code shows the reversed diff under the call.
372
+ - **Numbers shift after every change**, since 1 is always the newest. Act on a
373
+ list you just printed.
374
+ - **A change that no longer applies is refused whole.** A later edit on a line
375
+ next to it blocks it, and nothing is written. A range stops there.
376
+ - **A file name finds its path.** `chsum undo SKILL.md` finds
377
+ `skills/chsum/SKILL.md` when only one changed file ends that way.
378
+ - **The oldest step includes what was uncommitted** when the session began; the
379
+ list notes it.
380
+
381
+ Each undo and redo is itself a checkpoint, so both lists survive restarts. Both
382
+ need checkpointing on and act on the running session only.
383
+
384
+ ## `chsum find`
385
+
386
+ A conversation, or a note, by what it said. The one command that runs
387
+ `claude-history`.
388
+
389
+ ```sh
390
+ chsum find "playback rate pitch shift" # by meaning
391
+ chsum find "ENOENT" --lexical # identifiers, filenames, errors: sub-second
392
+ chsum find --notes "backoff" # your notes
393
+ chsum find "…" --all # every project
394
+ ```
395
+
396
+ The default search takes tens of seconds, and minutes the first time while its
397
+ index builds. Where ranking could not run, it says so:
398
+ `8 hits ranked by position only`.
399
+
400
+ Every listing prints padded colour columns on a terminal and markdown anywhere
401
+ else, so a pipe or a model reads whole records.
402
+
403
+ ## `chsum note`
404
+
405
+ Marks the moment that mattered, so the digest says which part was the point.
406
+
407
+ ```sh
408
+ ! chsum note "the backoff approach, after two dead ends"
409
+ ```
410
+
411
+ It prints nothing and never writes the transcript. The note leads the digest
412
+ under **Notable**, counts as `⚑` in the listing, and is searchable with
413
+ `chsum find --notes`.
414
+
415
+ An earlier moment, by id or by phrase:
416
+
417
+ ```sh
418
+ ! chsum note --recent 20 # recent messages and calls, with ids
419
+ ! chsum note --at be74e21f "the thundering-herd point" # by id, or a row number
420
+ ! chsum note --match "where it dies" "the timeout gap" # by something it said
421
+ ```
422
+
423
+ Matching ignores case, punctuation and markdown; several matches list the
424
+ candidates and file nothing.
425
+
426
+ While you are talking to an agent, `!` goes to the agent. Note its words
427
+ afterwards with `--match`, or ask the agent to note as it works; its notes fold
428
+ into the parent, tagged `agent <id>`.
429
+
430
+ ```sh
431
+ ! chsum note --list # this project's notes; --all every project; --full whole text
432
+ ! chsum note --show dde43c3c#1 # where it landed, with --context N around it
433
+ ! chsum note --delete dde43c3c#2 # several ids at once
434
+ ! chsum recap --list # the bullets recap wrote, same ids
435
+ ```
436
+
437
+ ## `chsum name`
438
+
439
+ Claude Code titles a session from its first question. `chsum name` titles it for
440
+ what it became, in chsum and in `/resume`:
441
+
442
+ ```sh
443
+ chsum name "retry: design + build" # this session
444
+ chsum name ch_3654a13c "retry: design + build" # another
445
+ chsum name --list # renamed sessions; --all every project
446
+ chsum name --clear # back to Claude Code's title
447
+ chsum name --no-resume "…" # chsum only
448
+ ```
449
+
450
+ It appends one `ai-title` record, the shape Claude Code appends itself, and
451
+ keeps the name in chsum's store. Claude Code re-titles a running session as it
452
+ grows, so `/resume` can drift back; chsum keeps yours.
453
+
454
+ ## `chsum annotations`
455
+
456
+ The wire [claude-history](https://github.com/raine/claude-history) calls to read
457
+ and write notes. Register it in `~/.config/claude-history/config.toml`:
458
+
459
+ ```toml
460
+ [annotations]
461
+ write_to = "chsum"
462
+
463
+ [annotators.chsum]
464
+ command = "chsum annotations"
465
+ ```
466
+
467
+ Notes and recap bullets then show at their rows in its viewer and match in
468
+ `claude-history agent search`; a note typed there (`a`) or deleted there (`d`)
469
+ goes through chsum.
470
+
471
+ <img src="https://raw.githubusercontent.com/InDate/chsum/main/meta/chsum_notes_in_claude-history.webp" alt="chsum notes shown at their rows in claude-history's viewer" width="800" />
472
+
473
+ ## `chsum hook`
474
+
475
+ What the plugin's hooks run; not a command you type. It writes git checkpoints:
476
+ one commit per tool call that changed the tree, which `recap`, `--writes`,
477
+ `where --git` and `undo` read.
478
+
479
+ ```
480
+ chsum hook post-tool-use # after each tool call: checkpoint the tree
481
+ chsum hook session-start # at session start: raise the opt-in, once
482
+ ```
483
+
484
+ - **Opt-in per project.** Nothing is recorded until `.git/chsum-checkpoint`
485
+ reads `enabled`. Where it is absent, Claude asks you once at session start.
486
+ - **Your repo is untouched.** Checkpoints chain under `refs/chsum/<session>`,
487
+ built without touching `HEAD`, your index, your working tree or your commit
488
+ hooks. `git log`, `git status` and `git branch` show nothing.
489
+ - **`git show <checkpoint>`** is one call's change.
490
+ - **Kept until dropped.** A ref survives `gc` and worktree removal.
491
+
492
+ ```sh
493
+ chsum checkpoints # the chains, and whether it is on
494
+ chsum checkpoints --enable # on for this project; --disable off
495
+ chsum checkpoints --prune 30d # drop chains older than 30 days; --dry-run first
496
+ chsum checkpoints --migrate # rebuild 2.x reflog checkpoints as chains
497
+ ```
498
+
499
+ ## Upgrading to 3.0
500
+
501
+ - **Every view writes a file and prints its path.** Add `--stdout` where a
502
+ script read the document from stdout:
503
+ `chsum digest <ref> --messages --stdout > out.md`.
504
+ - **Checkpoints are kept until dropped.** 2.x left them in the reflog to expire;
505
+ 3.0 chains them under refs. `chsum checkpoints --prune 30d` is the old
506
+ retention, and `--migrate` moves 2.x checkpoints onto chains.
507
+
508
+ ## Which tools' sessions it reads
509
+
510
+ Claude Code (`~/.claude/projects`) and Codex CLI (`~/.codex/sessions`), together
511
+ in every listing, digest and search. `chsum --source codex` narrows to one; a
512
+ `source` column appears where both are present.
513
+
514
+ A Codex rollout is translated once into Claude Code's record shape under
515
+ `<data dir>/chsum/translated/codex/`, so its locators name that file. Three
516
+ things in the output come from Codex itself:
517
+
518
+ - **No titles.** Rows read `(untitled)` until `chsum name`.
519
+ - **`0s` durations** on imported threads, which carry one timestamp throughout.
520
+ - **Compressed rollouts** (`.jsonl.zst`, older than seven days) are skipped:
521
+ reading them needs a zstd decoder outside the standard library.
522
+
523
+ A third tool is one file in `chsum/sources/`.
524
+
525
+ ## Where chsum writes
526
+
527
+ ```
528
+ <data dir>/chsum/
529
+ digests/<uuid>.md a digest (`--out` to change)
530
+ digests/<uuid>-<view>.md a row view
531
+ names.json your session names
532
+ turns/<project>/<turn-uuid>.json recap bullets and notes, per turn
533
+ translated/<tool>/…/<id>.jsonl another tool's sessions, translated
534
+ ```
535
+
536
+ The data dir is `$CHSUM_DIR`, else `$XDG_DATA_HOME/chsum`, else
537
+ `%LOCALAPPDATA%\chsum` on Windows and `~/.local/share/chsum` elsewhere.
538
+
539
+ Beyond that: `chsum name` appends one `ai-title` record to a transcript, the
540
+ hook writes refs under `refs/chsum/`, and `undo` and `redo` write the files they
541
+ restore.
542
+
543
+ ## Which version am I running
544
+
545
+ ```
546
+ $ chsum --version
547
+ chsum 3.0.3 (15f423c) · python 3.10.11 · darwin
548
+ ```
549
+
550
+ The commit beside the version is what built it. After a version bump an
551
+ editable install's metadata goes stale; the line says so and names the fix,
552
+ `pipx install --editable . --force`.
553
+
554
+ ## Reporting something that looks wrong
555
+
556
+ Add `--debug` to the command and paste the block it prints beneath the output:
557
+ what the run read, ran and resolved, ending with `reproduce` lines. It names
558
+ records without copying their text, so it is safe to share and readable on the
559
+ machine that made it.
560
+
561
+ ```
562
+ --- chsum debug ---
563
+ invocation: chsum digest ch_8b0a671d… --stdout --debug
564
+ files (1)
565
+ ch_8b0a671d… meta,turns 947.1K 671 recs …/9a9e9ac5-….jsonl
566
+ steps (3)
567
+ resolve_ref via=argv ref=ch_8b0a671d…
568
+ reproduce
569
+ chsum digest ch_8b0a671d… --stdout
570
+ --- end chsum debug ---
571
+ ```
572
+
573
+ ## Prose, and where it's allowed
574
+
575
+ `recap`'s timeline is the one model-written output, through `claude -p --model
576
+ haiku` with your existing Claude Code login. Any summariser gets the extracted
577
+ material only, and its output sits beneath the verbatim record so each sentence
578
+ can be checked against it.
579
+
580
+ ## Implementation details
581
+
582
+ ### Transcripts and digests
583
+
584
+ Claude Code writes every session to disk as a transcript, one record per line:
585
+ each message, each tool call and its result, and a link from each record to the
586
+ one before it. A subagent writes a transcript of its own beside its parent's.
587
+ chsum reads these files directly. Codex CLI records its sessions in a different
588
+ shape, so chsum translates each one into Claude Code's shape once and reads the
589
+ copy; every view then works the same for both.
590
+
591
+ A digest is built by walking a transcript from start to end. The fields each
592
+ record carries separate your typed prompts from tool results and harness text,
593
+ and the files, commands and agents in between are counted from the tool calls
594
+ themselves. Nothing is generated along the way, so every line in the output
595
+ points back to a line in a transcript, and the locators printed beside each row
596
+ are those line numbers.
597
+
598
+ ### Branches
599
+
600
+ A rewind leaves the earlier path in place: the edited prompt is written as a
601
+ second record hanging off the same parent. Following the parent links from
602
+ each record that nothing points back to traces every path through the
603
+ conversation, and paths that share their typed prompts up to a point are
604
+ grouped where they part. That grouping is the branch list.
605
+
606
+ ### Checkpoints and undo
607
+
608
+ Checkpoints come from a hook that runs after each tool call. Where the working
609
+ tree differs from the last checkpoint, the hook records the tree as a git
610
+ commit under a ref of the session's own, beside your branches and never on
611
+ them. The difference between one commit and the next is what changed in the
612
+ files between those two calls, however the change was made.
613
+
614
+ Undo reads that difference back and applies it in reverse, and redo applies it
615
+ forward. Each undo and redo is recorded as a commit on the same chain, naming
616
+ the step it acted on, so the lists of steps in place and steps undone are
617
+ rebuilt from the chain alone. Git applies a change to every file or to none,
618
+ so a change whose lines were edited since is refused and the files stay as
619
+ they were.
620
+
621
+ ### Subagents
622
+
623
+ A subagent writes its own transcript beside its parent's as it works, one record
624
+ at a time, so its progress is on disk before its report exists. chsum reads that
625
+ file directly. Each message the agent writes prints whole, and each tool call it
626
+ makes prints as a single line naming the tool and the file or command, so the
627
+ output grows with what the agent said rather than with the size of its edits
628
+ and command output. The parent session reads that progress when it runs the
629
+ command, and nothing reaches its context between runs.
630
+
631
+ ### Marks
632
+
633
+ A mark is stored in chsum's own data directory, not in the transcript. When
634
+ `chsum mark` runs, it finds the newest message before the command in the
635
+ running session's transcript and records the reason beside that message's
636
+ location and its first line, filed under the turn it belongs to. A digest reads
637
+ these records for its session and prints each one under **Notable**, ahead of
638
+ everything else, with the message it points at quoted beneath it.
639
+
640
+ ### Names
641
+
642
+ Session names and recap bullets live in the same data directory. The one write
643
+ chsum makes to a transcript is the title record a rename appends.