chsum 1.0.0__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-1.0.0/.gitignore +4 -0
- chsum-1.0.0/CLAUDE.md +91 -0
- chsum-1.0.0/PKG-INFO +199 -0
- chsum-1.0.0/README.md +189 -0
- chsum-1.0.0/chsum.py +1103 -0
- chsum-1.0.0/pyproject.toml +28 -0
chsum-1.0.0/.gitignore
ADDED
chsum-1.0.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# chsum
|
|
2
|
+
|
|
3
|
+
Single-file, stdlib-only Python tool (`chsum.py`) turning Claude Code transcripts
|
|
4
|
+
into work logs and reload-ready context. `README.md` is the user-facing doc; this
|
|
5
|
+
is what you need before changing the code.
|
|
6
|
+
|
|
7
|
+
Installed with pipx (`pipx install --editable .` here), so `chsum.py` in this
|
|
8
|
+
checkout *is* what runs. No shell alias — an alias only exists in an interactive
|
|
9
|
+
shell, and this has to work from scripts, hooks, and agents. `dependencies` stays
|
|
10
|
+
empty; `claude-history` is a runtime requirement but a separate binary.
|
|
11
|
+
|
|
12
|
+
## Nothing here may invent anything
|
|
13
|
+
|
|
14
|
+
Every line of output is copied verbatim or computed. **Why:** output gets pasted
|
|
15
|
+
into future sessions, where a plausible-but-wrong sentence becomes ground truth.
|
|
16
|
+
A digest that's merely *usually* right is worse than none, because nothing
|
|
17
|
+
downstream can tell.
|
|
18
|
+
|
|
19
|
+
**Applying it:** for any new section, ask where each value came from. If the
|
|
20
|
+
answer involves inference or summarising, it belongs behind the `Summariser`
|
|
21
|
+
seam, whose output is additive and sits *beneath* the quotes that would
|
|
22
|
+
contradict it. Transcript text is blockquoted so a quoted `## Summary` can't
|
|
23
|
+
forge a section.
|
|
24
|
+
|
|
25
|
+
## Two ref schemes, one of them ours
|
|
26
|
+
|
|
27
|
+
- `ch_<32 hex>` — claude-history's, reimplemented in `ch_ref_for_path` from a
|
|
28
|
+
versioned internal. Derived values are verified against the uuid they report
|
|
29
|
+
(`resolve_ref`). If that check fires, their scheme changed.
|
|
30
|
+
- `ch_…/<agent-id>` — chsum's own, for subagents. claude-history has no per-agent
|
|
31
|
+
ref: `--subagents` inlines agent messages into the parent read untagged.
|
|
32
|
+
|
|
33
|
+
Never print a chsum agent ref inside a suggested `claude-history agent read`
|
|
34
|
+
command; it won't resolve. Agent digests point at the sidecar path.
|
|
35
|
+
|
|
36
|
+
## Text sources
|
|
37
|
+
|
|
38
|
+
`read_messages` shells out to `claude-history agent read` — it strips tool sludge
|
|
39
|
+
and returns `mN` ordinals and durable `ma_` anchors.
|
|
40
|
+
|
|
41
|
+
`messages_from_jsonl` parses raw JSONL and exists **only** for sidecars. It can't
|
|
42
|
+
mint anchors, so agent digests have none. Don't fix this by generating
|
|
43
|
+
anchor-shaped strings.
|
|
44
|
+
|
|
45
|
+
`extract_meta` is pure JSONL, no subprocesses — that's what keeps the listing and
|
|
46
|
+
`journal` fast (195 sessions in ~3s). Anything that shells out per session belongs
|
|
47
|
+
in the digest path, not the listing path.
|
|
48
|
+
|
|
49
|
+
## Layout
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
~/.claude/projects/<project-dir-name>/
|
|
53
|
+
<session-uuid>.jsonl the conversation
|
|
54
|
+
<session-uuid>/subagents/agent-<id>.jsonl one per subagent
|
|
55
|
+
<session-uuid>/subagents/agent-<id>.meta.json agentType, model, description, spawnDepth
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Sidecars can be absent (older/pruned) or outnumber the visible `Agent` calls (an
|
|
59
|
+
agent spawning its own), so `Meta.agent_count` takes the larger count.
|
|
60
|
+
|
|
61
|
+
## Delegated work is the session's work
|
|
62
|
+
|
|
63
|
+
Subagent edits and commands fold into the parent's totals. **Why:** otherwise a
|
|
64
|
+
session that delegated everything reads as no activity — usually it was the
|
|
65
|
+
busiest. Prompts stay parent-only. Files no parent turn touched are marked
|
|
66
|
+
`(agent)`.
|
|
67
|
+
|
|
68
|
+
## Releasing
|
|
69
|
+
|
|
70
|
+
Version lives in `pyproject.toml` and `skills/chsum/SKILL.md` frontmatter. Both
|
|
71
|
+
ship, so `publish.yml` refuses a tag that disagrees with either.
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
# bump both, then
|
|
75
|
+
git tag v1.0.1 && git push origin v1.0.1
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The tag publishes to PyPI via trusted publishing (no stored token) and asks
|
|
79
|
+
[InDate/indate-tools](https://github.com/InDate/indate-tools) to repin. The
|
|
80
|
+
marketplace opens a PR: publishing and pushing an update to installed users are
|
|
81
|
+
separate decisions.
|
|
82
|
+
|
|
83
|
+
## Conventions
|
|
84
|
+
|
|
85
|
+
- Comments explain *why*, briefly. Several behaviours look wrong until you know
|
|
86
|
+
the reason (idle-gap duration, ambiguous anchors, two `outline` shapes).
|
|
87
|
+
- Output is token-budgeted: it lands in future context windows. New sections go
|
|
88
|
+
through `_plural`/`_bullets`/`_clip`/`_quote` so clipping stays consistent and
|
|
89
|
+
truncation is always marked, never silent.
|
|
90
|
+
- Widen an existing command before adding one. The surface is deliberately small:
|
|
91
|
+
`sessions` (default), `last`, `find`, `digest`, `context`, `journal`.
|
chsum-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chsum
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Work logs and reload-ready context from Claude Code conversations. Deterministic: no model, nothing invented.
|
|
5
|
+
Author: Joshua
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: claude,claude-code,context,transcripts,work-log
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# chsum
|
|
12
|
+
|
|
13
|
+
Work logs and reload-ready context from your Claude Code conversations.
|
|
14
|
+
|
|
15
|
+
**Nothing here is generated by a model.** Every line of output is either copied
|
|
16
|
+
verbatim from a transcript or computed from it, so nothing can be invented. That
|
|
17
|
+
matters because the output is designed to be pasted back into a future Claude
|
|
18
|
+
session, where a plausible-but-wrong sentence would become ground truth.
|
|
19
|
+
|
|
20
|
+
## The idea
|
|
21
|
+
|
|
22
|
+
Your own prompts already are a faithful record of what you were trying to do.
|
|
23
|
+
Extracted in order they read as the story of the session — most of what a summary
|
|
24
|
+
would have said, without the risk:
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
**m1**
|
|
28
|
+
> can you open a chrome page to the site, it is running on 3000
|
|
29
|
+
|
|
30
|
+
**m7**
|
|
31
|
+
> sherpa-onnx-tts.worker.js:267 [Sherpa Worker] Initialization failed…
|
|
32
|
+
|
|
33
|
+
**m137**
|
|
34
|
+
> when I speed up the text to speech, it ends up sounding like a chipmunk
|
|
35
|
+
|
|
36
|
+
**m153**
|
|
37
|
+
> The toolbar is no longer working to slow it down or speed it up live
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Blockquoting is functional, not cosmetic: a quoted reply containing `## Summary`
|
|
41
|
+
would otherwise forge a section of the digest. Everything else — dates, duration,
|
|
42
|
+
branch, files, commands — is parsed straight out of the transcript.
|
|
43
|
+
|
|
44
|
+
## Requirements
|
|
45
|
+
|
|
46
|
+
- [`claude-history`](https://github.com/) on your `PATH`
|
|
47
|
+
- Python 3.10+. No third-party packages, no model, no network.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pipx install chsum # from a checkout: pipx install .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or as a Claude Code plugin, which brings the skill with it:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
/plugin marketplace add InDate/indate-tools
|
|
59
|
+
/plugin install chsum@indate-tools
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The plugin carries the skill; the `chsum` command still comes from pipx.
|
|
63
|
+
|
|
64
|
+
pipx, not `pip install --user`: chsum is an application, so it gets its own venv
|
|
65
|
+
and one symlink on `PATH`. `pipx install --editable .` while working on it.
|
|
66
|
+
|
|
67
|
+
A real command rather than a shell alias, because an alias doesn't exist for
|
|
68
|
+
scripts, hooks, or agents.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
chsum # every session in this project, one line each
|
|
74
|
+
chsum -n 5 # just the five most recent
|
|
75
|
+
chsum --since 7d # only the last week
|
|
76
|
+
chsum --all # across every project
|
|
77
|
+
chsum last # most recent real session, as context
|
|
78
|
+
chsum last -n 2 # the one before that
|
|
79
|
+
chsum find "text to speech playback speed" # locate a conversation
|
|
80
|
+
chsum digest <ch_ref> # write a digest file
|
|
81
|
+
chsum digest <ch_ref> --stdout # print it instead
|
|
82
|
+
chsum digest --file path/to/session.jsonl # address by file
|
|
83
|
+
chsum context <ch_ref> # reload artifact, for pasting into Claude
|
|
84
|
+
chsum context <ch_ref>/<agent-id> # one subagent's own digest
|
|
85
|
+
chsum journal --since 7d # work log for this project
|
|
86
|
+
chsum journal --since 2w --all # across every project
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Bare `chsum` lists the project's sessions, newest activity first:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
ref date dur prompts files agents title
|
|
93
|
+
ch_c120431a267b202aebf0b38f6c3c1b69 2026-08-06 5h38m 78 14 - Plan 3D house model…
|
|
94
|
+
ch_da4e99d42e5efab11ebdedc22fb65145 2026-08-05 3h03m 30 12 5 Set up cdp-tools server
|
|
95
|
+
ch_b99f11b7c257dafc8b93f53480ba3804 2026-08-05 6s 1 0 - empty (untitled)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Listing is the default because picking is the common case, and "most recent" is
|
|
99
|
+
often a session you abandoned after one prompt. Those are flagged `empty` rather
|
|
100
|
+
than hidden — knowing a session was a dead end is the answer to "where did that
|
|
101
|
+
work go". Activity means a file edited, a notable command, an agent spawned, or a
|
|
102
|
+
second prompt.
|
|
103
|
+
|
|
104
|
+
`chsum last` is `chsum context` on the most recent session with activity, ordered
|
|
105
|
+
by last activity so one you resumed yesterday beats one you started last week.
|
|
106
|
+
Run from inside Claude Code, the session doing the running is excluded.
|
|
107
|
+
|
|
108
|
+
Everything scopes to the current project; `--all` widens. Digests land in
|
|
109
|
+
`~/.claude/chsum/digests/<uuid>.md` (`--out` to change).
|
|
110
|
+
|
|
111
|
+
### Subagents
|
|
112
|
+
|
|
113
|
+
A subagent's edits and commands fold into its parent's totals — otherwise a
|
|
114
|
+
session that delegated everything reads as no activity. Files no parent turn
|
|
115
|
+
touched are marked `(agent)`. Each agent gets a line in **Delegated**, and an
|
|
116
|
+
address:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
chsum context ch_da4e99d42e5efab11ebdedc22fb65145/a728cd49179f1a356
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Its task, files, commands, and last message. Everything past the one-line summary
|
|
123
|
+
is fetched on demand, so a heavily-delegated session doesn't produce a digest
|
|
124
|
+
nobody wants to read.
|
|
125
|
+
|
|
126
|
+
`<parent-ref>/<agent-id>` resolves to `<uuid>/subagents/agent-<id>.jsonl`. chsum's
|
|
127
|
+
own scheme, not claude-history's — see *Notes on correctness*.
|
|
128
|
+
|
|
129
|
+
### Search modes
|
|
130
|
+
|
|
131
|
+
`--hybrid` (default) and `--semantic` are best for conceptual recall but are slow:
|
|
132
|
+
tens of seconds warm, and **several minutes on the very first run** while the
|
|
133
|
+
embedding index builds. Use `--lexical` (sub-second) for identifiers, filenames,
|
|
134
|
+
and error strings, or `--exact` for exact tokens.
|
|
135
|
+
|
|
136
|
+
## What a digest contains
|
|
137
|
+
|
|
138
|
+
| Section | Source |
|
|
139
|
+
|---|---|
|
|
140
|
+
| Frontmatter — ref, title, project, branch, start, duration, counts | computed |
|
|
141
|
+
| **What I asked for** — your prompts, verbatim, in order | copied |
|
|
142
|
+
| **Files changed** / **Commands run** | parsed from tool calls |
|
|
143
|
+
| **Delegated** — one line per subagent, with its address | parsed from sidecars |
|
|
144
|
+
| **Where I left off** — last prompt and last reply, verbatim | copied |
|
|
145
|
+
| — *found by two separate backward scans, so they may be far apart and are not a Q&A pair* | |
|
|
146
|
+
| **Drill down** — `mN → ma_…` anchor map | computed |
|
|
147
|
+
|
|
148
|
+
An agent digest has the same shape minus the intent trail — an agent gets one
|
|
149
|
+
instruction, so **Task** is a single block — and no anchor map (see below).
|
|
150
|
+
|
|
151
|
+
Output is budgeted, because it lands in a future context window: quotes clip,
|
|
152
|
+
lists cap. Every truncation is marked (`[+N chars, read the anchor]`, `…and N
|
|
153
|
+
more`) so you always know when you're seeing a fragment.
|
|
154
|
+
|
|
155
|
+
## Notes on correctness
|
|
156
|
+
|
|
157
|
+
Several things here are non-obvious and were established by measuring, not assuming:
|
|
158
|
+
|
|
159
|
+
- **Duration excludes idle time.** Sessions get resumed hours or days later, so
|
|
160
|
+
first-record-to-last-record wildly overstates effort — one session in the corpus
|
|
161
|
+
reads as 92 hours. Gaps over 30 minutes are treated as "walked away".
|
|
162
|
+
- **Anchors are content-addressed, so they can collide.** Two messages with
|
|
163
|
+
byte-identical text (`[Request interrupted by user]`, say) share one anchor, and
|
|
164
|
+
`read --anchor` then fails with `ambiguous-ref`. Ambiguous anchors are detected
|
|
165
|
+
and never published — every anchor a digest prints resolves to exactly one message.
|
|
166
|
+
- **Most "user" records aren't from you.** They're tool results, interrupts, and
|
|
167
|
+
harness scaffolding. Those are filtered out; `prompts:` counts what you typed.
|
|
168
|
+
- **`outline` has two output shapes** — segment ranges for long conversations,
|
|
169
|
+
per-message lines for short ones. Both are handled.
|
|
170
|
+
- **Subagent transcripts** aren't conversations in their own right and never appear
|
|
171
|
+
in the listing, matching `claude-history`'s discovery rules.
|
|
172
|
+
- **`claude-history` has no per-agent ref.** `--subagents` inlines agent messages
|
|
173
|
+
into the parent read untagged, so they can't be sliced apart. Sidecars are
|
|
174
|
+
parsed directly, which is why agent digests carry no `ma_` anchors — those are
|
|
175
|
+
claude-history's to mint, and a fabricated one is worse than none.
|
|
176
|
+
- **An agent's last message isn't necessarily its conclusion**, so the section is
|
|
177
|
+
*Last thing it said*. An interrupted agent ends mid-thought.
|
|
178
|
+
- **Agent counts take the larger of two sources** — `Agent`/`Task` calls in the
|
|
179
|
+
parent, and sidecars on disk. Sidecars go missing; an agent that spawns its own
|
|
180
|
+
outnumbers the visible calls.
|
|
181
|
+
- **Scratch paths** (`/tmp`, scratchpads, plan files) are excluded from "files
|
|
182
|
+
changed" so the work log shows real project changes.
|
|
183
|
+
|
|
184
|
+
## Adding prose later
|
|
185
|
+
|
|
186
|
+
There is a deliberately unimplemented `Summariser` seam at the bottom of
|
|
187
|
+
`chsum.py`. A TL;DR is the one thing extraction can't produce; the intended order
|
|
188
|
+
is Haiku first to set a quality bar and a price, then a local MLX backend measured
|
|
189
|
+
against it.
|
|
190
|
+
|
|
191
|
+
The rule for any backend: it gets the already-extracted material, and its output is
|
|
192
|
+
**additive** — layered on top of the verbatim record so a wrong sentence can always
|
|
193
|
+
be checked against the quotes beneath it.
|
|
194
|
+
|
|
195
|
+
If you do go local, note that the model in `mlx-community/DeepSeek-R1-Distill-Qwen-14B-MLX`
|
|
196
|
+
is **139 GB** of unquantised weights. The 4-bit build is `…-14B-4bit` at 8.32 GB. On a
|
|
197
|
+
16 GB machine the binding constraint is KV cache, not context length: this architecture
|
|
198
|
+
costs 192 KB/token at fp16 (96 KB with `kv_bits=8`), so after 8.32 GB of weights you get
|
|
199
|
+
roughly 18k–36k tokens of usable input, not the 131k the config advertises.
|
chsum-1.0.0/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# chsum
|
|
2
|
+
|
|
3
|
+
Work logs and reload-ready context from your Claude Code conversations.
|
|
4
|
+
|
|
5
|
+
**Nothing here is generated by a model.** Every line of output is either copied
|
|
6
|
+
verbatim from a transcript or computed from it, so nothing can be invented. That
|
|
7
|
+
matters because the output is designed to be pasted back into a future Claude
|
|
8
|
+
session, where a plausible-but-wrong sentence would become ground truth.
|
|
9
|
+
|
|
10
|
+
## The idea
|
|
11
|
+
|
|
12
|
+
Your own prompts already are a faithful record of what you were trying to do.
|
|
13
|
+
Extracted in order they read as the story of the session — most of what a summary
|
|
14
|
+
would have said, without the risk:
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
**m1**
|
|
18
|
+
> can you open a chrome page to the site, it is running on 3000
|
|
19
|
+
|
|
20
|
+
**m7**
|
|
21
|
+
> sherpa-onnx-tts.worker.js:267 [Sherpa Worker] Initialization failed…
|
|
22
|
+
|
|
23
|
+
**m137**
|
|
24
|
+
> when I speed up the text to speech, it ends up sounding like a chipmunk
|
|
25
|
+
|
|
26
|
+
**m153**
|
|
27
|
+
> The toolbar is no longer working to slow it down or speed it up live
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Blockquoting is functional, not cosmetic: a quoted reply containing `## Summary`
|
|
31
|
+
would otherwise forge a section of the digest. Everything else — dates, duration,
|
|
32
|
+
branch, files, commands — is parsed straight out of the transcript.
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- [`claude-history`](https://github.com/) on your `PATH`
|
|
37
|
+
- Python 3.10+. No third-party packages, no model, no network.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
pipx install chsum # from a checkout: pipx install .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or as a Claude Code plugin, which brings the skill with it:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
/plugin marketplace add InDate/indate-tools
|
|
49
|
+
/plugin install chsum@indate-tools
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The plugin carries the skill; the `chsum` command still comes from pipx.
|
|
53
|
+
|
|
54
|
+
pipx, not `pip install --user`: chsum is an application, so it gets its own venv
|
|
55
|
+
and one symlink on `PATH`. `pipx install --editable .` while working on it.
|
|
56
|
+
|
|
57
|
+
A real command rather than a shell alias, because an alias doesn't exist for
|
|
58
|
+
scripts, hooks, or agents.
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
chsum # every session in this project, one line each
|
|
64
|
+
chsum -n 5 # just the five most recent
|
|
65
|
+
chsum --since 7d # only the last week
|
|
66
|
+
chsum --all # across every project
|
|
67
|
+
chsum last # most recent real session, as context
|
|
68
|
+
chsum last -n 2 # the one before that
|
|
69
|
+
chsum find "text to speech playback speed" # locate a conversation
|
|
70
|
+
chsum digest <ch_ref> # write a digest file
|
|
71
|
+
chsum digest <ch_ref> --stdout # print it instead
|
|
72
|
+
chsum digest --file path/to/session.jsonl # address by file
|
|
73
|
+
chsum context <ch_ref> # reload artifact, for pasting into Claude
|
|
74
|
+
chsum context <ch_ref>/<agent-id> # one subagent's own digest
|
|
75
|
+
chsum journal --since 7d # work log for this project
|
|
76
|
+
chsum journal --since 2w --all # across every project
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Bare `chsum` lists the project's sessions, newest activity first:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
ref date dur prompts files agents title
|
|
83
|
+
ch_c120431a267b202aebf0b38f6c3c1b69 2026-08-06 5h38m 78 14 - Plan 3D house model…
|
|
84
|
+
ch_da4e99d42e5efab11ebdedc22fb65145 2026-08-05 3h03m 30 12 5 Set up cdp-tools server
|
|
85
|
+
ch_b99f11b7c257dafc8b93f53480ba3804 2026-08-05 6s 1 0 - empty (untitled)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Listing is the default because picking is the common case, and "most recent" is
|
|
89
|
+
often a session you abandoned after one prompt. Those are flagged `empty` rather
|
|
90
|
+
than hidden — knowing a session was a dead end is the answer to "where did that
|
|
91
|
+
work go". Activity means a file edited, a notable command, an agent spawned, or a
|
|
92
|
+
second prompt.
|
|
93
|
+
|
|
94
|
+
`chsum last` is `chsum context` on the most recent session with activity, ordered
|
|
95
|
+
by last activity so one you resumed yesterday beats one you started last week.
|
|
96
|
+
Run from inside Claude Code, the session doing the running is excluded.
|
|
97
|
+
|
|
98
|
+
Everything scopes to the current project; `--all` widens. Digests land in
|
|
99
|
+
`~/.claude/chsum/digests/<uuid>.md` (`--out` to change).
|
|
100
|
+
|
|
101
|
+
### Subagents
|
|
102
|
+
|
|
103
|
+
A subagent's edits and commands fold into its parent's totals — otherwise a
|
|
104
|
+
session that delegated everything reads as no activity. Files no parent turn
|
|
105
|
+
touched are marked `(agent)`. Each agent gets a line in **Delegated**, and an
|
|
106
|
+
address:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
chsum context ch_da4e99d42e5efab11ebdedc22fb65145/a728cd49179f1a356
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Its task, files, commands, and last message. Everything past the one-line summary
|
|
113
|
+
is fetched on demand, so a heavily-delegated session doesn't produce a digest
|
|
114
|
+
nobody wants to read.
|
|
115
|
+
|
|
116
|
+
`<parent-ref>/<agent-id>` resolves to `<uuid>/subagents/agent-<id>.jsonl`. chsum's
|
|
117
|
+
own scheme, not claude-history's — see *Notes on correctness*.
|
|
118
|
+
|
|
119
|
+
### Search modes
|
|
120
|
+
|
|
121
|
+
`--hybrid` (default) and `--semantic` are best for conceptual recall but are slow:
|
|
122
|
+
tens of seconds warm, and **several minutes on the very first run** while the
|
|
123
|
+
embedding index builds. Use `--lexical` (sub-second) for identifiers, filenames,
|
|
124
|
+
and error strings, or `--exact` for exact tokens.
|
|
125
|
+
|
|
126
|
+
## What a digest contains
|
|
127
|
+
|
|
128
|
+
| Section | Source |
|
|
129
|
+
|---|---|
|
|
130
|
+
| Frontmatter — ref, title, project, branch, start, duration, counts | computed |
|
|
131
|
+
| **What I asked for** — your prompts, verbatim, in order | copied |
|
|
132
|
+
| **Files changed** / **Commands run** | parsed from tool calls |
|
|
133
|
+
| **Delegated** — one line per subagent, with its address | parsed from sidecars |
|
|
134
|
+
| **Where I left off** — last prompt and last reply, verbatim | copied |
|
|
135
|
+
| — *found by two separate backward scans, so they may be far apart and are not a Q&A pair* | |
|
|
136
|
+
| **Drill down** — `mN → ma_…` anchor map | computed |
|
|
137
|
+
|
|
138
|
+
An agent digest has the same shape minus the intent trail — an agent gets one
|
|
139
|
+
instruction, so **Task** is a single block — and no anchor map (see below).
|
|
140
|
+
|
|
141
|
+
Output is budgeted, because it lands in a future context window: quotes clip,
|
|
142
|
+
lists cap. Every truncation is marked (`[+N chars, read the anchor]`, `…and N
|
|
143
|
+
more`) so you always know when you're seeing a fragment.
|
|
144
|
+
|
|
145
|
+
## Notes on correctness
|
|
146
|
+
|
|
147
|
+
Several things here are non-obvious and were established by measuring, not assuming:
|
|
148
|
+
|
|
149
|
+
- **Duration excludes idle time.** Sessions get resumed hours or days later, so
|
|
150
|
+
first-record-to-last-record wildly overstates effort — one session in the corpus
|
|
151
|
+
reads as 92 hours. Gaps over 30 minutes are treated as "walked away".
|
|
152
|
+
- **Anchors are content-addressed, so they can collide.** Two messages with
|
|
153
|
+
byte-identical text (`[Request interrupted by user]`, say) share one anchor, and
|
|
154
|
+
`read --anchor` then fails with `ambiguous-ref`. Ambiguous anchors are detected
|
|
155
|
+
and never published — every anchor a digest prints resolves to exactly one message.
|
|
156
|
+
- **Most "user" records aren't from you.** They're tool results, interrupts, and
|
|
157
|
+
harness scaffolding. Those are filtered out; `prompts:` counts what you typed.
|
|
158
|
+
- **`outline` has two output shapes** — segment ranges for long conversations,
|
|
159
|
+
per-message lines for short ones. Both are handled.
|
|
160
|
+
- **Subagent transcripts** aren't conversations in their own right and never appear
|
|
161
|
+
in the listing, matching `claude-history`'s discovery rules.
|
|
162
|
+
- **`claude-history` has no per-agent ref.** `--subagents` inlines agent messages
|
|
163
|
+
into the parent read untagged, so they can't be sliced apart. Sidecars are
|
|
164
|
+
parsed directly, which is why agent digests carry no `ma_` anchors — those are
|
|
165
|
+
claude-history's to mint, and a fabricated one is worse than none.
|
|
166
|
+
- **An agent's last message isn't necessarily its conclusion**, so the section is
|
|
167
|
+
*Last thing it said*. An interrupted agent ends mid-thought.
|
|
168
|
+
- **Agent counts take the larger of two sources** — `Agent`/`Task` calls in the
|
|
169
|
+
parent, and sidecars on disk. Sidecars go missing; an agent that spawns its own
|
|
170
|
+
outnumbers the visible calls.
|
|
171
|
+
- **Scratch paths** (`/tmp`, scratchpads, plan files) are excluded from "files
|
|
172
|
+
changed" so the work log shows real project changes.
|
|
173
|
+
|
|
174
|
+
## Adding prose later
|
|
175
|
+
|
|
176
|
+
There is a deliberately unimplemented `Summariser` seam at the bottom of
|
|
177
|
+
`chsum.py`. A TL;DR is the one thing extraction can't produce; the intended order
|
|
178
|
+
is Haiku first to set a quality bar and a price, then a local MLX backend measured
|
|
179
|
+
against it.
|
|
180
|
+
|
|
181
|
+
The rule for any backend: it gets the already-extracted material, and its output is
|
|
182
|
+
**additive** — layered on top of the verbatim record so a wrong sentence can always
|
|
183
|
+
be checked against the quotes beneath it.
|
|
184
|
+
|
|
185
|
+
If you do go local, note that the model in `mlx-community/DeepSeek-R1-Distill-Qwen-14B-MLX`
|
|
186
|
+
is **139 GB** of unquantised weights. The 4-bit build is `…-14B-4bit` at 8.32 GB. On a
|
|
187
|
+
16 GB machine the binding constraint is KV cache, not context length: this architecture
|
|
188
|
+
costs 192 KB/token at fp16 (96 KB with `kv_bits=8`), so after 8.32 GB of weights you get
|
|
189
|
+
roughly 18k–36k tokens of usable input, not the 131k the config advertises.
|