@brandry/claude-jsonl-compressor 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -56
- package/LICENSE +674 -674
- package/NOTICE +8 -8
- package/README.md +666 -611
- package/SKILL.md +230 -345
- package/agents/openai.yaml +7 -7
- package/bin/claude-jsonl-compressor.cjs +4 -4
- package/bin/claude-jsonl-repair-read-pages.cjs +4 -4
- package/bin/run-python.cjs +77 -77
- package/package.json +60 -60
- package/references/claude-jsonl-compression-format.md +635 -578
- package/scripts/claude_session_tools.py +304 -245
- package/scripts/compress_claude_jsonl.py +8608 -8275
- package/scripts/repair_claude_jsonl.py +627 -627
- package/templates/summary_template_en.md +78 -78
package/README.md
CHANGED
|
@@ -1,611 +1,666 @@
|
|
|
1
|
-
# Claude JSONL Compressor
|
|
2
|
-
|
|
3
|
-
[English](https://github.com/brandrylabs/claude-jsonl-compressor/blob/v1.
|
|
4
|
-
|
|
5
|
-
Strict, model-assisted compression for one Claude Code session transcript, plus an independent byte-preserving compatibility repair for historical `Read.pages` records.
|
|
6
|
-
|
|
7
|
-
**Release:** [`1.
|
|
8
|
-
**Engine:** `v10`<br>
|
|
9
|
-
**Model-pack schema:** `v11`<br>
|
|
10
|
-
**License:** GPL-3.0-only<br>
|
|
11
|
-
**Repository:** [brandrylabs/claude-jsonl-compressor](https://github.com/brandrylabs/claude-jsonl-compressor)
|
|
12
|
-
|
|
13
|
-
This project is not affiliated with Anthropic. Claude Code's transcript JSONL is an observed internal format, not a published stable storage API. Always keep the original file or a verified backup.
|
|
14
|
-
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
Claude's
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
-
|
|
297
|
-
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
--
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
```text
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
--
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
-
|
|
499
|
-
-
|
|
500
|
-
-
|
|
501
|
-
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
-
|
|
509
|
-
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
`--
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
tests/
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
1
|
+
# Claude JSONL Compressor
|
|
2
|
+
|
|
3
|
+
[English](https://github.com/brandrylabs/claude-jsonl-compressor/blob/v1.1.0/README.md) | [简体中文](https://github.com/brandrylabs/claude-jsonl-compressor/blob/v1.1.0/docs/README.zh-CN.md) | [日本語](https://github.com/brandrylabs/claude-jsonl-compressor/blob/v1.1.0/docs/README.ja.md)
|
|
4
|
+
|
|
5
|
+
Strict, model-assisted compression for one Claude Code session transcript, plus an independent byte-preserving compatibility repair for historical `Read.pages` records.
|
|
6
|
+
|
|
7
|
+
**Release:** [`1.1.0`](CHANGELOG.md)<br>
|
|
8
|
+
**Engine:** `v10`<br>
|
|
9
|
+
**Model-pack schema:** `v11`<br>
|
|
10
|
+
**License:** GPL-3.0-only<br>
|
|
11
|
+
**Repository:** [brandrylabs/claude-jsonl-compressor](https://github.com/brandrylabs/claude-jsonl-compressor)
|
|
12
|
+
|
|
13
|
+
This project is not affiliated with Anthropic. Claude Code's transcript JSONL is an observed internal format, not a published stable storage API. Always keep the original file or a verified backup.
|
|
14
|
+
|
|
15
|
+
## Version 1.1.0: bounded research evidence
|
|
16
|
+
|
|
17
|
+
The goal is to reduce Claude context and cache costs without replacing them
|
|
18
|
+
with unbounded summarizer work. The CLI keeps `excerpt`, `legacy`, `fold`, and
|
|
19
|
+
zero protected human turns as compatible defaults. For new Codex workflows,
|
|
20
|
+
use scoped citations; select full tool evidence when research lives in tool
|
|
21
|
+
payloads. Run the same selection options in preflight and both passes:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
--preflight --tool-evidence full --citation-style scoped
|
|
25
|
+
--min-recent-turns 2
|
|
26
|
+
--preserve-prior-summaries-verbatim --prior-summary-overflow error
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`--preflight` is read-only and replaces an output operation; the other flags
|
|
30
|
+
are selection settings. It separates pointer topology from tool closure,
|
|
31
|
+
reports a physical-tail candidate without selecting it, and checks the chosen
|
|
32
|
+
pack against both existing ceilings. `nothing-to-summarize` needs no model work.
|
|
33
|
+
Full evidence retains complete old active tool inputs/results and auxiliary
|
|
34
|
+
results, including mixed prose/tool records and replacement characters. Exact
|
|
35
|
+
long strings repeated within one record are referenced once. It does not merge
|
|
36
|
+
near-duplicates, fetch external documents, or reconstruct unrecorded reasoning.
|
|
37
|
+
An over-budget full pack stops; it never silently samples required payloads,
|
|
38
|
+
raises the ceiling, launches more agents, or splits itself into volumes.
|
|
39
|
+
|
|
40
|
+
`--citation-style scoped` uses `[@L42]` / `[@H3]` in summary prose; ordinary
|
|
41
|
+
document labels such as L73/H1 remain literal. The mandatory coverage subsection
|
|
42
|
+
keeps its printed L-prefix syntax. `--prior-summary-overflow error` requires
|
|
43
|
+
verbatim preservation and refuses folding, including known impossible old-text
|
|
44
|
+
size before model work. Pass 2 checks the actual new layer too. The legacy
|
|
45
|
+
`fold` policy remains available. Exact old text includes trailing whitespace.
|
|
46
|
+
|
|
47
|
+
`--min-recent-turns N` protects human-started turns after the latest compact
|
|
48
|
+
and in the final session only. It may enlarge raw context and prevent meeting
|
|
49
|
+
a token target; protection is never silently reduced. It is unsupported with
|
|
50
|
+
physical-tail compatibility. Counts are structural, not a guarantee of rewind
|
|
51
|
+
menu entries. File rewind still requires native checkpoints and their files;
|
|
52
|
+
Bash changes cannot acquire checkpoints merely through JSONL compression.
|
|
53
|
+
|
|
54
|
+
The final attributable custom title (or automatic title if none) is preserved,
|
|
55
|
+
including a rename after the final pointer. Lookup shares that resolver and
|
|
56
|
+
prefers exact path/ID matches over title scanning. Old names are not aliases.
|
|
57
|
+
Unowned titles in mixed-session files are reported instead of guessed.
|
|
58
|
+
|
|
59
|
+
After successful read-only preflight, make and verify a numbered source backup
|
|
60
|
+
before semantic work; check its hash against preflight. Live replacement still
|
|
61
|
+
creates its independent transaction backup. Default model work is one authored
|
|
62
|
+
summary plus focused self-review. Explicit user requests for retrospective,
|
|
63
|
+
independent, or subagent review are supported with their requested configuration.
|
|
64
|
+
Review and cite relevant complete evidence; do not turn every run into repeated
|
|
65
|
+
full-history review. Structural checks cannot establish semantic truth or actual
|
|
66
|
+
Claude runtime compatibility. Engine v10 / model-pack v11 / report 1 remain;
|
|
67
|
+
regenerate a two-pass pack after upgrading.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## What It Does
|
|
71
|
+
|
|
72
|
+
- Compresses one Claude Code JSONL into one current compact-style summary pair plus a recent raw active suffix.
|
|
73
|
+
- Uses a model-authored semantic summary by default, with deterministic evidence selection and validation around it.
|
|
74
|
+
- Excludes rewound/inactive branch text from every Claude-readable output layer.
|
|
75
|
+
- Preserves recent conversation records for Claude rewind.
|
|
76
|
+
- Projects one final `last-prompt` while retaining unknown source fields.
|
|
77
|
+
- Validates UUIDs, parents, sessions, compact metadata and API-level tool pairing.
|
|
78
|
+
- Supports candidate output and transactional replacement of one live `.claude/projects` session.
|
|
79
|
+
- Handles repeated compression, including an explicit prior-summary verbatim mode.
|
|
80
|
+
- Offers an independent byte-level repair that removes unsupported historical `Read.pages` members without reserializing the JSONL.
|
|
81
|
+
- Runs with Python's standard library. No tokenizer or YAML dependency is required.
|
|
82
|
+
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
With this repository installed as a Codex skill, ask Codex:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
Use the claude-jsonl-compressor skill on exactly one Claude Code JSONL.
|
|
89
|
+
Input: C:\data\session.jsonl
|
|
90
|
+
Output: C:\data\session.compressed.jsonl
|
|
91
|
+
Target: about 150k estimated Messages tokens.
|
|
92
|
+
Keep recent raw records for rewind, use the default model-assisted summary, and run validation.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For a live `.claude/projects` file, explicitly request a numbered backup and in-place replacement, confirm that the session is closed, and provide a work directory outside `.claude`. The detailed two-pass CLI workflow appears below.
|
|
96
|
+
|
|
97
|
+
## Why Model-Assisted By Default
|
|
98
|
+
|
|
99
|
+
Deterministic code can select topology and validate bytes, but it cannot decide which historical arguments, legal distinctions, design rationale or research conclusions matter. Python therefore freezes the active branch and builds a bounded, source-anchored evidence pack; a host model writes the summary; Python then verifies request/evidence digests, anchors, required source excerpts and the final JSONL.
|
|
100
|
+
|
|
101
|
+
The script itself never calls a model or the network. The evidence pack bridges the practical 1M-session-versus-smaller-summarizer gap by including every non-empty older active human message and assistant `text`/`thinking` message in full while excluding inactive branches, recent raw records and low-value structural repetition. U+FFFD is reported without discarding the rest of a mandatory record. If mandatory evidence exceeds either pack ceiling, generation stops instead of sampling semantic history.
|
|
102
|
+
|
|
103
|
+
## Safety Properties
|
|
104
|
+
|
|
105
|
+
### Strict resume authority
|
|
106
|
+
|
|
107
|
+
The physically last `type: "last-prompt"` record is authoritative in automatic mode. A malformed latest pointer is an error; the program does not search backward for an older valid pointer and accidentally revive an obsolete branch.
|
|
108
|
+
|
|
109
|
+
Strict active mode rejects:
|
|
110
|
+
|
|
111
|
+
- missing or malformed authority
|
|
112
|
+
- missing leaf or parent
|
|
113
|
+
- parent loops or malformed non-string/empty `parentUuid` values
|
|
114
|
+
- ordinary-message/non-attachment physical parent inversion
|
|
115
|
+
- recurring, pointer-mismatched or otherwise unsafe session lineage
|
|
116
|
+
- duplicate UUIDs anywhere in the file
|
|
117
|
+
- unsafe post-pointer extension
|
|
118
|
+
|
|
119
|
+
Use `--resume-leaf UUID` only for an explicit recovery decision. It is reported as `active-chain-manual-override`, distinct from default strict `active-chain`. Use `--preserve-physical-tail` only as an explicit compatibility mode; it does not provide inactive-branch isolation.
|
|
120
|
+
|
|
121
|
+
An unusual or ambiguous topology is a stop, not an automatic fallback. The CLI exits before creating a pack, candidate, report, backup or other sidecar. A hosting agent may explain one applicable explicit recovery control and ask the user to confirm it in a new instruction; it must not infer that confirmation from the original compression request. Manually spliced transcripts generally require physical-tail compatibility and therefore lose branch/rewind isolation.
|
|
122
|
+
|
|
123
|
+
Current Claude Code reconstructs a conversation from a UUID map and parent links, so physical line order is not universally chronological. This project accepts only same-session `attachment -> attachment` physical inversions on an otherwise complete acyclic chain and writes them back in logical parent order. It also accepts one-way A->B (or A->B->C) session lineage only when a session never recurs and the final leaf and pointer match the final session. All earlier-session records become summary evidence; recent raw records remain entirely in the final session. A tool pair crossing that forced cut is a hard stop.
|
|
124
|
+
|
|
125
|
+
### Rewound branches stay out
|
|
126
|
+
|
|
127
|
+
The source indexes are partitioned into mutually exclusive sets:
|
|
128
|
+
|
|
129
|
+
| Set | Meaning | May enter summary? | May remain raw? |
|
|
130
|
+
| --- | --- | --- | --- |
|
|
131
|
+
| `summaryIndexes` | Older active-chain records | Yes | No |
|
|
132
|
+
| `rawKeepIndexes` | Recent active-chain records | No | Yes |
|
|
133
|
+
| `sideKeepIndexes` | Policy-approved checkpoint side records | No | Side records only |
|
|
134
|
+
| `controlProjectionIndexes` | Pointer and safe global control records | No | Projected only |
|
|
135
|
+
| `excludedBranchIndexes` | Inactive UUID branches | No | No |
|
|
136
|
+
| `excludedUnattributedIndexes` | Unattributed non-chain records | No | No |
|
|
137
|
+
|
|
138
|
+
Excluded records appear in reports only as counts and digests. Their text is not copied into the model pack, compact summary, deterministic appendix, verbatim prior-summary block or output message chain.
|
|
139
|
+
|
|
140
|
+
### Transactional writes
|
|
141
|
+
|
|
142
|
+
- Input and candidate bytes are bound by full SHA-256; candidates are staged, flushed, validated and atomically published.
|
|
143
|
+
- Numbered backups use exclusive creation and byte verification. Live replacement also captures and verifies the actual old target before installing the candidate.
|
|
144
|
+
- Failed post-replacement validation restores the captured original. A rollback failure is raised prominently while verified recovery assets remain available.
|
|
145
|
+
- Concurrent target recreation preserves the external target and recovery backups, then fails without publishing the candidate.
|
|
146
|
+
- Parent-directory fsync is best effort and reported; this is not a cross-platform power-loss guarantee.
|
|
147
|
+
- If the live JSONL commits but final report publication fails, the CLI does not undo valid committed data. It prints a `committed-report-failed` receipt with hashes and backup/candidate labels and exits with code 3.
|
|
148
|
+
|
|
149
|
+
## Requirements
|
|
150
|
+
|
|
151
|
+
- Python 3.10 or newer
|
|
152
|
+
- Node.js 22 or newer only when using the npm command wrappers
|
|
153
|
+
- Claude Code is optional; it is needed only for an explicitly requested runtime `/resume` or `/context` smoke test
|
|
154
|
+
- Hard-link support on the volume holding the target file, and on an explicitly configured backup directory, for `--replace-original` only
|
|
155
|
+
|
|
156
|
+
No Python package installation is required.
|
|
157
|
+
|
|
158
|
+
### Hard-link requirement for live replacement
|
|
159
|
+
|
|
160
|
+
`--replace-original` publishes the candidate with `os.link` so that it never overwrites a concurrent claimant, and the rollback path restores the captured original the same way. The target directory must therefore support file hard links. An explicitly supplied `--backup-dir` also publishes numbered backups with a hard link and must support the same operation.
|
|
161
|
+
|
|
162
|
+
Before live replacement staging, backup payload publication, or target movement, the compressor runs a unique, same-directory hard-link probe on the target volume. The probe briefly creates two dot-prefixed temporary files and removes them; a cleanup failure is reported with the retained probe name and stops the live operation. If the capability probe fails, the target remains at its original path and byte content, and no live replacement stage, backup payload, or target move has started. This probe is a capability check, not a guarantee against a later permission, quota, network, or concurrency failure; late publication, rollback, and cleanup failures are reported with their transaction state and verified recovery assets.
|
|
163
|
+
|
|
164
|
+
Each unique live-transaction temporary path is checked against its recorded filesystem identity and frozen bytes before cleanup. A detected mismatch is retained and reported as `committed-cleanup-failed` after a committed candidate, or alongside the primary failure before commit. Portable Python cannot bind the final pathname `unlink` atomically to that earlier identity check across Windows, Linux, and macOS. Run live replacement only with the session closed and no other writer; hostile same-account directory manipulation is outside this guarantee.
|
|
165
|
+
|
|
166
|
+
NTFS, APFS, ext4, XFS, and btrfs commonly support file hard links, while FAT/exFAT, some network shares, overlay or bind-mounted filesystems, and Windows ReFS may reject them. The probe is authoritative for the actual directory and account; the filesystem name alone is not treated as a guarantee. The repository CI runs the probe and transaction tests on Windows, Linux, and macOS runner volumes.
|
|
167
|
+
|
|
168
|
+
Candidate output is unaffected: it publishes through `os.replace` and has no hard-link dependency.
|
|
169
|
+
|
|
170
|
+
## Installation
|
|
171
|
+
|
|
172
|
+
### Install As A Codex Skill
|
|
173
|
+
|
|
174
|
+
Clone the repository into the Codex skill directory:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
skill="${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor"
|
|
178
|
+
mkdir -p "$(dirname "$skill")"
|
|
179
|
+
git clone https://github.com/brandrylabs/claude-jsonl-compressor.git "$skill"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Windows PowerShell:
|
|
183
|
+
|
|
184
|
+
```powershell
|
|
185
|
+
$codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $env:USERPROFILE '.codex' }
|
|
186
|
+
$skill = Join-Path $codexHome 'skills\claude-jsonl-compressor'
|
|
187
|
+
New-Item -ItemType Directory -Force (Split-Path -Parent $skill) | Out-Null
|
|
188
|
+
git clone https://github.com/brandrylabs/claude-jsonl-compressor.git $skill
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Update or uninstall the skill:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git -C "${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor" pull --ff-only
|
|
195
|
+
rm -rf "${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
git -C $skill pull --ff-only
|
|
200
|
+
Remove-Item -LiteralPath $skill -Recurse -Force
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The installed directory must contain `SKILL.md`, `scripts/`, `config/`, `templates/` and `references/`.
|
|
204
|
+
|
|
205
|
+
### Install The npm CLI
|
|
206
|
+
|
|
207
|
+
After version 1.1.0 is published:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm install --global @brandry/claude-jsonl-compressor
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
This installs two commands:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
claude-jsonl-compressor
|
|
217
|
+
claude-jsonl-repair-read-pages
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The npm package is a zero-dependency Node shim over the bundled Python implementation. It forwards arguments, stdio, exit codes and signals with `shell: false`. The tarball also contains `SKILL.md`, `agents/` and `references/`, but npm installation does not register the directory as a Codex skill; skill installation remains a separate copy/link step.
|
|
221
|
+
|
|
222
|
+
Upgrade or uninstall the global CLI:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npm install --global @brandry/claude-jsonl-compressor
|
|
226
|
+
npm update --global @brandry/claude-jsonl-compressor
|
|
227
|
+
npm uninstall --global @brandry/claude-jsonl-compressor
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Local development install and invocation:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
npm install --save-dev @brandry/claude-jsonl-compressor
|
|
234
|
+
npm update @brandry/claude-jsonl-compressor
|
|
235
|
+
npm exec -- claude-jsonl-compressor --version
|
|
236
|
+
npm exec -- claude-jsonl-repair-read-pages --version
|
|
237
|
+
npm uninstall @brandry/claude-jsonl-compressor
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Run without retaining an installation:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npx --yes --package @brandry/claude-jsonl-compressor claude-jsonl-compressor --version
|
|
244
|
+
npx --yes --package @brandry/claude-jsonl-compressor claude-jsonl-repair-read-pages --version
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Actual npm/npx operations use the same Python CLI options:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
npx --yes --package @brandry/claude-jsonl-compressor claude-jsonl-compressor --input session.jsonl --write-model-pack run/session.model-pack.md
|
|
251
|
+
npx --yes --package @brandry/claude-jsonl-compressor claude-jsonl-repair-read-pages --input session.jsonl --scan-only
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Use From Source Without Installing
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
python scripts/compress_claude_jsonl.py --version
|
|
258
|
+
python scripts/repair_claude_jsonl.py --version
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Can Claude Code Install This Skill?
|
|
262
|
+
|
|
263
|
+
`SKILL.md` is a Codex skill definition, not a native Claude Code skill/plugin format. Claude Code can still run the Python or npm commands when instructed, but installing this directory into Claude's configuration does not automatically create an equivalent Claude-native skill.
|
|
264
|
+
|
|
265
|
+
## Detailed Workflow
|
|
266
|
+
|
|
267
|
+
The examples below use PowerShell and a local skill installation:
|
|
268
|
+
|
|
269
|
+
```powershell
|
|
270
|
+
$skill = "$env:USERPROFILE\.codex\skills\claude-jsonl-compressor"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### 1. Analyze The Resume Path
|
|
274
|
+
|
|
275
|
+
```powershell
|
|
276
|
+
python "$skill\scripts\compress_claude_jsonl.py" `
|
|
277
|
+
--input "C:\data\session.jsonl" `
|
|
278
|
+
--analyze-resume-path
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
This is read-only. A nonzero result must be resolved before model-pack generation.
|
|
282
|
+
Use `reasonCode` for the exact machine-readable cause; `status` is only the
|
|
283
|
+
coarse category. The stable value table is in
|
|
284
|
+
[`references/claude-jsonl-compression-format.md`](references/claude-jsonl-compression-format.md#authoritative-last-prompt).
|
|
285
|
+
|
|
286
|
+
### 2. Generate A Model Evidence Pack
|
|
287
|
+
|
|
288
|
+
```powershell
|
|
289
|
+
python "$skill\scripts\compress_claude_jsonl.py" `
|
|
290
|
+
--input "C:\data\session.jsonl" `
|
|
291
|
+
--write-model-pack "C:\work\run\session.model-pack.md" `
|
|
292
|
+
--target-ratio 0.30 `
|
|
293
|
+
--min-recent-records 120 `
|
|
294
|
+
--summary-char-budget 60000 `
|
|
295
|
+
--target-estimated-tokens 150000 `
|
|
296
|
+
--model-pack-char-budget 500000 `
|
|
297
|
+
--model-pack-estimated-token-budget 150000
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The evidence pack has two independent default ceilings: 500,000 characters
|
|
301
|
+
and a conservative 150,000-token local estimate. The token ceiling leaves
|
|
302
|
+
working room in a typical 200k summarizer context. Mandatory human/assistant
|
|
303
|
+
semantic records, prior compact summaries, handoff lines, and required coverage
|
|
304
|
+
groups are never sampled or clipped; generation stops if they do not fit.
|
|
305
|
+
Optional source/tool/system/error evidence is added by importance and chronology
|
|
306
|
+
until either ceiling is reached, and the pack/report state whether that optional
|
|
307
|
+
evidence was truncated. Do not install a tokenizer to change this workflow.
|
|
308
|
+
|
|
309
|
+
`--target-ratio` is an approximate byte-ratio planning input, not a hard release gate. For a hard local Messages estimate ceiling, use:
|
|
310
|
+
|
|
311
|
+
```powershell
|
|
312
|
+
--target-estimated-tokens 150000
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
This candidate-output estimate is separate from the model-pack reading ceiling.
|
|
316
|
+
It covers complete retained structured message payloads, including full thinking,
|
|
317
|
+
`tool_use.input`, `tool_result`, and `toolUseResult` data. It does not include
|
|
318
|
+
Claude's system prompt, tool schemas, MCP servers, agents, skills, memory files
|
|
319
|
+
or runtime-loaded context. It is not a promise about total `/context` usage.
|
|
320
|
+
|
|
321
|
+
`--summary-char-budget` has a hard minimum of 4000 characters. A smaller value or a blank compact summary is rejected instead of publishing unusable memory.
|
|
322
|
+
|
|
323
|
+
### 3. Write The Model Summary
|
|
324
|
+
|
|
325
|
+
The model reads the pack and writes `session.model-summary.md`.
|
|
326
|
+
|
|
327
|
+
The first HTML comment must be copied exactly and contains:
|
|
328
|
+
|
|
329
|
+
```text
|
|
330
|
+
source_sha256
|
|
331
|
+
summary_source_sha256
|
|
332
|
+
evidence_anchor_lines_digest
|
|
333
|
+
required_anchor_groups_digest
|
|
334
|
+
handoff_summary_digest
|
|
335
|
+
pack_request_digest
|
|
336
|
+
required_claim_sources_digest
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Every substantive transcript claim needs a displayed `L<number>` anchor. Every external-handoff claim needs a displayed `H<number>` anchor. The validator rejects invented or hidden anchors. It also requires at least one cited anchor from every generated coverage group and an anchored body under each of the nine exact headings printed in the pack. Only the exact leading metadata comment and exact required headings are exempt from line grounding; extra HTML comments or headings are errors. The exact whole line `Unknown from provided anchors.` is the only unanchored uncertainty placeholder; adding other text to that line removes the exemption.
|
|
340
|
+
|
|
341
|
+
Schema v11 assigns a required full-text L-anchor group to every non-empty older active human message and every older active assistant `text`/`thinking` message. It binds every selection/resource option through `pack_request_digest`. Under the exact `### Mandatory Evidence Coverage` subsection, the model must provide exactly one line per mandatory semantic/prior-summary record:
|
|
342
|
+
|
|
343
|
+
```text
|
|
344
|
+
- L42 support_text_json="exact source substring" disposition=covered
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
The JSON string must decode to a meaningful exact substring of that L record. This mechanical gate blocks anchor-only boilerplate and leaves a checkable source excerpt; it does not prove that all natural-language interpretation is correct. Schema v11 also reserves early/middle/late/latest, source/tool and prior-summary coverage. Prior compact summaries and every physical line of an explicitly supplied handoff enter the pack in full; handoff early/middle/late/latest H groups must be cited. Pack generation stops instead of truncating or sampling mandatory evidence when either the character or estimated-token ceiling is insufficient. Raise `--model-pack-char-budget` or `--model-pack-estimated-token-budget` only when the summarizing model can read the resulting pack.
|
|
348
|
+
|
|
349
|
+
The summary should preserve:
|
|
350
|
+
|
|
351
|
+
- current state
|
|
352
|
+
- chronology and supersessions
|
|
353
|
+
- user constraints and wording
|
|
354
|
+
- assistant/model research decisions and reasons
|
|
355
|
+
- evidence provenance
|
|
356
|
+
- rejected alternatives
|
|
357
|
+
- risks, unknowns and follow-ups
|
|
358
|
+
- recent raw boundary
|
|
359
|
+
|
|
360
|
+
Later events control current state, but earlier decisions and their reasons remain as superseded history.
|
|
361
|
+
|
|
362
|
+
### 4. Build A Candidate
|
|
363
|
+
|
|
364
|
+
```powershell
|
|
365
|
+
python "$skill\scripts\compress_claude_jsonl.py" `
|
|
366
|
+
--input "C:\data\session.jsonl" `
|
|
367
|
+
--output "C:\data\session.compressed.jsonl" `
|
|
368
|
+
--target-ratio 0.30 `
|
|
369
|
+
--min-recent-records 120 `
|
|
370
|
+
--summary-char-budget 60000 `
|
|
371
|
+
--target-estimated-tokens 150000 `
|
|
372
|
+
--model-pack-char-budget 500000 `
|
|
373
|
+
--model-pack-estimated-token-budget 150000 `
|
|
374
|
+
--model-summary "C:\work\run\session.model-summary.md"
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Pass exactly the same selection options used for the model pack. In particular,
|
|
378
|
+
repeat both non-default model-pack ceilings so the second pass regenerates the
|
|
379
|
+
same evidence contract.
|
|
380
|
+
|
|
381
|
+
The command writes:
|
|
382
|
+
|
|
383
|
+
```text
|
|
384
|
+
session.compressed.jsonl
|
|
385
|
+
session.compressed.jsonl.validation.json
|
|
386
|
+
session.compressed.jsonl.report.md
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The input remains unchanged.
|
|
390
|
+
|
|
391
|
+
## Live Session Replacement
|
|
392
|
+
|
|
393
|
+
Close the Claude Code process using that session before replacement. The live target must be an existing regular `.jsonl` file under `.claude/projects`.
|
|
394
|
+
|
|
395
|
+
Generate the model pack and model summary outside `.claude`, then run:
|
|
396
|
+
|
|
397
|
+
```powershell
|
|
398
|
+
python "$skill\scripts\compress_claude_jsonl.py" `
|
|
399
|
+
--input "$env:USERPROFILE\.claude\projects\PROJECT\SESSION.jsonl" `
|
|
400
|
+
--replace-original `
|
|
401
|
+
--confirm-session-closed `
|
|
402
|
+
--work-dir "C:\work\claude-compression\SESSION-TIMESTAMP" `
|
|
403
|
+
--model-pack-estimated-token-budget 150000 `
|
|
404
|
+
--target-estimated-tokens 150000 `
|
|
405
|
+
--model-summary "C:\work\claude-compression\SESSION-TIMESTAMP\session.model-summary.md"
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
The default backup is placed beside the live file:
|
|
409
|
+
|
|
410
|
+
```text
|
|
411
|
+
SESSION.jsonl.backup
|
|
412
|
+
SESSION.jsonl.backup1
|
|
413
|
+
SESSION.jsonl.backup2
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
To keep backups outside `.claude`:
|
|
417
|
+
|
|
418
|
+
```powershell
|
|
419
|
+
--backup-dir "C:\work\claude-compression\SESSION-TIMESTAMP\backups"
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Candidate, report, validation, model pack and model summary files remain under the external work directory. Do not manually copy a refused candidate over a live session. Exit code 3 with `committed-report-failed` means the live JSONL was already replaced and validated but final report publication failed; inspect the printed hashes and numbered backup instead of rerunning blindly.
|
|
423
|
+
|
|
424
|
+
## Checkpoint And Rewind Behavior
|
|
425
|
+
|
|
426
|
+
Conversation rewind and file rewind are separate mechanisms.
|
|
427
|
+
|
|
428
|
+
Default:
|
|
429
|
+
|
|
430
|
+
```text
|
|
431
|
+
--checkpoint-policy active-correlated
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
It retains only UUID-less `file-history-snapshot` records with structural identifiers that correlate to recent retained active records.
|
|
435
|
+
|
|
436
|
+
Other controls:
|
|
437
|
+
|
|
438
|
+
```text
|
|
439
|
+
--checkpoint-policy none
|
|
440
|
+
--max-file-history-snapshots N
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
`--checkpoint-policy preserve-recent` is rejected in strict active-chain mode. It is available only together with explicit `--preserve-physical-tail`, which is labeled compatibility mode and does not isolate rewound branches. JSONL compression alone does not guarantee complete file-state rewind.
|
|
444
|
+
|
|
445
|
+
## Repeated Compression
|
|
446
|
+
|
|
447
|
+
The default behavior folds previous compact summaries into one new current summary. Old decisions must be checked against later supersessions; old summary text is not automatically current truth.
|
|
448
|
+
|
|
449
|
+
An older Codex compact boundary may retain a `preservedMessages` snapshot from the time it was created. If a later rewind diverges from that snapshot, source validation reports a historical-snapshot warning and follows only the current authoritative parent chain; the rewound tail stays excluded. Every newly generated candidate must rebuild this metadata to match its current chain exactly.
|
|
450
|
+
|
|
451
|
+
For an explicit exact-text request:
|
|
452
|
+
|
|
453
|
+
```text
|
|
454
|
+
--preserve-prior-summaries-verbatim --prior-summary-overflow error
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Use both flags in both passes. The compressor allows up to 1.5 times the configured summary character budget and stops if strict exact preservation cannot fit. Omitting the overflow flag retains the legacy `fold` behavior: an oversized block reports `fallback-folded` and uses normal semantic folding. It never leaves stacked old compact pairs on the current active chain.
|
|
458
|
+
|
|
459
|
+
## Deterministic Fallback
|
|
460
|
+
|
|
461
|
+
Model-assisted summary is the default. Use deterministic fallback only on explicit request:
|
|
462
|
+
|
|
463
|
+
```powershell
|
|
464
|
+
python "$skill\scripts\compress_claude_jsonl.py" `
|
|
465
|
+
--input "C:\data\session.jsonl" `
|
|
466
|
+
--output "C:\data\session.compressed.jsonl" `
|
|
467
|
+
--deterministic-summary
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
The CLI otherwise requires `--model-summary`.
|
|
471
|
+
|
|
472
|
+
## Read.pages Compatibility Repair
|
|
473
|
+
|
|
474
|
+
Claude's native Read tool can legitimately use `pages` for long PDFs. This repair exists for a separate compatibility failure where a historical bridge cannot accept that member. Compression never runs it automatically.
|
|
475
|
+
|
|
476
|
+
### Scan
|
|
477
|
+
|
|
478
|
+
```powershell
|
|
479
|
+
python "$skill\scripts\repair_claude_jsonl.py" `
|
|
480
|
+
--input "C:\data\session.jsonl" `
|
|
481
|
+
--scan-only
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Write A Candidate
|
|
485
|
+
|
|
486
|
+
```powershell
|
|
487
|
+
python "$skill\scripts\repair_claude_jsonl.py" `
|
|
488
|
+
--input "C:\data\session.jsonl" `
|
|
489
|
+
--output "C:\data\session.repaired.jsonl" `
|
|
490
|
+
--expect-matches 2
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Replace One Live File
|
|
494
|
+
|
|
495
|
+
```powershell
|
|
496
|
+
python "$skill\scripts\repair_claude_jsonl.py" `
|
|
497
|
+
--input "$env:USERPROFILE\.claude\projects\PROJECT\SESSION.jsonl" `
|
|
498
|
+
--replace-original `
|
|
499
|
+
--confirm-session-closed `
|
|
500
|
+
--work-dir "C:\work\claude-repair\SESSION-TIMESTAMP" `
|
|
501
|
+
--expect-matches 2
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Default scope is the strict active chain. `--scope all` must be explicit.
|
|
505
|
+
|
|
506
|
+
The repair requires:
|
|
507
|
+
|
|
508
|
+
- assistant API message
|
|
509
|
+
- structured `tool_use`
|
|
510
|
+
- exact tool name `Read`
|
|
511
|
+
- object `input`
|
|
512
|
+
- present `pages` member
|
|
513
|
+
- non-empty `file_path`
|
|
514
|
+
- exactly one later matching `tool_result` in scope
|
|
515
|
+
- the same non-empty `sessionId` on use and result
|
|
516
|
+
- result `sourceToolAssistantUUID` equal to the tool-use assistant UUID
|
|
517
|
+
|
|
518
|
+
Pending calls and near matches are reported but unchanged. Duplicate JSON keys or ambiguous spans stop the run before editing. Candidate publication re-reads the actual published bytes, binds them to the expected SHA-256, validates the repair plan, requires an idempotent second scan, and runs the shared full-transcript UUID/parent/compact/tool validator. Exit code 3 with `operationState: committed-report-failed` has the same already-committed meaning as live compression.
|
|
519
|
+
|
|
520
|
+
## CLI Reference
|
|
521
|
+
|
|
522
|
+
Important compression options:
|
|
523
|
+
|
|
524
|
+
| Option | Purpose |
|
|
525
|
+
| --- | --- |
|
|
526
|
+
| `--analyze-resume-path` | Read-only strict topology report |
|
|
527
|
+
| `--write-model-pack PATH` | Write bounded semantic evidence and stop |
|
|
528
|
+
| `--model-summary PATH` | Validate and embed model-authored summary |
|
|
529
|
+
| `--deterministic-summary` | Explicit model opt-out |
|
|
530
|
+
| `--target-ratio R` | Approximate output byte-ratio planning value; not a hard gate |
|
|
531
|
+
| `--target-estimated-tokens N` | Hard ceiling under the local complete-structure Messages estimate |
|
|
532
|
+
| `--min-recent-records N` | Raw active-suffix floor |
|
|
533
|
+
| `--summary-char-budget N` | Compact-summary character budget; minimum 4000 |
|
|
534
|
+
| `--model-pack-char-budget N` | Evidence-pack character budget |
|
|
535
|
+
| `--model-pack-estimated-token-budget N` | Evidence-pack local token estimate ceiling; default 150000 |
|
|
536
|
+
| `--resume-leaf UUID` | Explicit recovery leaf override |
|
|
537
|
+
| `--max-post-last-prompt-extension N` | Explicit complete tool-result-only closure limit; default 0 |
|
|
538
|
+
| `--checkpoint-policy POLICY` | Strict mode: `active-correlated` or `none`; `preserve-recent` only with physical-tail compatibility |
|
|
539
|
+
| `--preserve-prior-summaries-verbatim` | Explicit repeated-compression exact-text mode |
|
|
540
|
+
| `--preserve-physical-tail` | Compatibility mode without branch-isolation guarantee |
|
|
541
|
+
| `--replace-original` | Transactionally replace one live session |
|
|
542
|
+
| `--confirm-session-closed` | Required caller acknowledgement for live replacement; not process-lock detection |
|
|
543
|
+
| `--work-dir PATH` | External process directory for live replacement |
|
|
544
|
+
| `--backup-dir PATH` | Optional external backup directory |
|
|
545
|
+
| `--validate-only PATH` | Structural validation only |
|
|
546
|
+
|
|
547
|
+
Run `--help` for the complete list.
|
|
548
|
+
|
|
549
|
+
## Validation Scope
|
|
550
|
+
|
|
551
|
+
The validator checks:
|
|
552
|
+
|
|
553
|
+
- JSON object per non-empty line
|
|
554
|
+
- UUID uniqueness
|
|
555
|
+
- parent existence and session consistency
|
|
556
|
+
- final pointer target
|
|
557
|
+
- active chain closure
|
|
558
|
+
- narrow attachment-order and one-way session-lineage compatibility, with unsafe variants rejected
|
|
559
|
+
- one current compact boundary and compact summary
|
|
560
|
+
- compact metadata consistency
|
|
561
|
+
- merged assistant fragments and split user tool results
|
|
562
|
+
- API-level `tool_use` / `tool_result` order and pairing
|
|
563
|
+
- non-empty, unique active tool IDs; partial multi-tool ordered subsets remain a reported branch-compatibility warning
|
|
564
|
+
- absence of internal scratch fields
|
|
565
|
+
|
|
566
|
+
Validation checks internal consistency under the observed-format rules; Claude Code versions may still build runtime context differently.
|
|
567
|
+
|
|
568
|
+
When runtime testing is explicitly allowed, check these separately:
|
|
569
|
+
|
|
570
|
+
1. `/resume` lists and opens the session.
|
|
571
|
+
2. `/context` shows expected Messages usage.
|
|
572
|
+
3. Recent conversation rewind works.
|
|
573
|
+
4. Recent file rewind works for retained checkpoints.
|
|
574
|
+
|
|
575
|
+
High total `/context` with low Messages can come from system prompt, tools, MCP, agents, skills, memory files or newly read content. Recompressing JSONL does not reduce those categories.
|
|
576
|
+
|
|
577
|
+
## Session Locator
|
|
578
|
+
|
|
579
|
+
Locate exactly one file by filename or session ID without reading transcript bodies:
|
|
580
|
+
|
|
581
|
+
```powershell
|
|
582
|
+
python "$skill\scripts\claude_session_tools.py" `
|
|
583
|
+
--root "$env:USERPROFILE\.claude\projects" `
|
|
584
|
+
--query "SESSION.jsonl"
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
`--scan-titles` reads candidate files only when title matching is explicitly needed. Multiple matches are an error. The compressor never performs directory-wide multi-session compression.
|
|
588
|
+
|
|
589
|
+
## Development And Verification
|
|
590
|
+
|
|
591
|
+
Run the complete standard-library suite:
|
|
592
|
+
|
|
593
|
+
```bash
|
|
594
|
+
python -B -m unittest discover -s tests -v
|
|
595
|
+
python -B tests/test_compressor.py
|
|
596
|
+
python -B tests/test_repair.py
|
|
597
|
+
python -B tests/test_package.py
|
|
598
|
+
python -B tests/test_transaction_races.py
|
|
599
|
+
python -B tests/test_semantic_evidence_contracts.py
|
|
600
|
+
python -B tests/test_structural_safety_contracts.py
|
|
601
|
+
python -B tests/test_protocol_contracts.py
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Additional release checks:
|
|
605
|
+
|
|
606
|
+
```bash
|
|
607
|
+
pycache="$(mktemp -d)"
|
|
608
|
+
if ! PYTHONPYCACHEPREFIX="$pycache" python -m compileall -q scripts tests; then
|
|
609
|
+
rm -rf "$pycache"
|
|
610
|
+
exit 1
|
|
611
|
+
fi
|
|
612
|
+
rm -rf "$pycache"
|
|
613
|
+
python -B -I -S scripts/compress_claude_jsonl.py --version
|
|
614
|
+
python -B -I -S scripts/repair_claude_jsonl.py --version
|
|
615
|
+
npm test
|
|
616
|
+
npm pack --dry-run --json
|
|
617
|
+
npm publish --dry-run --access public --tag latest
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
The release suite covers active/dead branch partitioning, fixed-seed topology transformations, strict pointer failures, dual model-pack budgets, complete structured token accounting, multilingual semantic ledgers and thinking, handoffs, request/claim digests, mandatory support excerpts, tool pairs, repeated compression, checkpoint policies, transaction races and committed-report states, exact byte repair, BOM/CRLF, npm tarball allowlisting and offline tarball installation.
|
|
621
|
+
|
|
622
|
+
### Maintainer Stable Release Checklist
|
|
623
|
+
|
|
624
|
+
1. Confirm a clean public tree and matching `1.1.0` values in `package.json`, Python version output, docs, and tests.
|
|
625
|
+
2. Run the Python, npm, isolated-Python, tarball, privacy, and offline-install gates above.
|
|
626
|
+
3. Inspect `npm pack --dry-run --json`; publish only the allowlisted files.
|
|
627
|
+
4. Require a clean worktree, create annotated tag `v1.1.0`, and push the commit and tag.
|
|
628
|
+
5. Publish from an authenticated maintainer environment with permission to publish this package:
|
|
629
|
+
|
|
630
|
+
```bash
|
|
631
|
+
npm publish --access public --tag latest
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
6. Verify npm version `1.1.0` and the `latest` dist-tag, then create a GitHub release (not a prerelease) from the already-pushed tag.
|
|
635
|
+
|
|
636
|
+
Do not append `--provenance` to a local publish. npm provenance requires a supported cloud CI runner. For later releases, prefer npm trusted publishing from a public GitHub repository on a GitHub-hosted runner with `id-token: write`, a protected release tag, and a matching protected environment; trusted publishing generates provenance automatically.
|
|
637
|
+
|
|
638
|
+
Registry ownership, npm trusted-publisher configuration, credentials, tag push, GitHub prerelease creation, and npm publication are external maintainer actions and are not claimed by the local test suite.
|
|
639
|
+
|
|
640
|
+
## Repository Layout
|
|
641
|
+
|
|
642
|
+
```text
|
|
643
|
+
SKILL.md
|
|
644
|
+
CHANGELOG.md
|
|
645
|
+
README.md
|
|
646
|
+
LICENSE
|
|
647
|
+
package.json
|
|
648
|
+
bin/
|
|
649
|
+
config/
|
|
650
|
+
scripts/
|
|
651
|
+
templates/
|
|
652
|
+
references/
|
|
653
|
+
tests/
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## Privacy
|
|
657
|
+
|
|
658
|
+
- The public project contains only anonymous synthetic fixtures.
|
|
659
|
+
- Model packs and candidate metadata use generic labels such as `SOURCE_JSONL`; generated reports expose basenames, never full local paths.
|
|
660
|
+
- npm publication uses an extension-level file allowlist.
|
|
661
|
+
- JSONL, backups, reports, model packs, model summaries, caches and compiled Python files are excluded from the package.
|
|
662
|
+
- Review generated evidence packs before sharing them; they intentionally contain selected transcript evidence.
|
|
663
|
+
|
|
664
|
+
## License
|
|
665
|
+
|
|
666
|
+
GPL-3.0-only. You may use, study, modify and redistribute the project under the GPL terms. Distribution of modified or incorporated versions may require corresponding source and the same license; review the license when integrating it into a distributed commercial product.
|