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.
- chsum-3.0.4/PKG-INFO +643 -0
- chsum-3.0.4/README.md +632 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/checkpoints.py +139 -75
- {chsum-3.0.2 → chsum-3.0.4}/chsum/core.py +1119 -38
- {chsum-3.0.2 → chsum-3.0.4}/pyproject.toml +1 -1
- chsum-3.0.4/skills/chsum/SKILL.md +120 -0
- chsum-3.0.4/skills/chsum/references/checkpoints.md +45 -0
- chsum-3.0.4/skills/chsum/references/debugging.md +9 -0
- chsum-3.0.4/skills/chsum/references/naming.md +12 -0
- chsum-3.0.4/skills/chsum/references/noting.md +29 -0
- chsum-3.0.4/skills/chsum/references/recap.md +15 -0
- chsum-3.0.4/tests/test_branches.py +192 -0
- chsum-3.0.4/tests/test_handbacks.py +190 -0
- chsum-3.0.4/tests/test_undo.py +366 -0
- {chsum-3.0.2 → chsum-3.0.4}/tests/test_views.py +1 -1
- chsum-3.0.2/PKG-INFO +0 -1068
- chsum-3.0.2/README.md +0 -1057
- chsum-3.0.2/skills/chsum/SKILL.md +0 -185
- chsum-3.0.2/skills/chsum/references/checkpoints.md +0 -54
- chsum-3.0.2/skills/chsum/references/debugging.md +0 -13
- chsum-3.0.2/skills/chsum/references/naming.md +0 -14
- chsum-3.0.2/skills/chsum/references/noting.md +0 -54
- chsum-3.0.2/skills/chsum/references/recap.md +0 -30
- {chsum-3.0.2 → chsum-3.0.4}/.gitignore +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/CONTRIBUTING.md +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/LICENSE +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/__init__.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/__main__.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/__init__.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/claude.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum/sources/codex.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/chsum.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/tests/harness.py +0 -0
- {chsum-3.0.2 → chsum-3.0.4}/tests/test_checkpoints.py +0 -0
- {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.
|