sessionwiki 0.34.9

Find, search, and read every AI coding session you've ever had - across Claude Code, Codex, Gemini CLI, OpenCode, Cline, and more.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
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
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
# Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/), and the project aims to follow
semantic versioning once it reaches 1.0.

## [Unreleased]

## [0.34.9] - 2026-10-21

### Fixed

- A large Codex session keeps its whole conversation again. From the middle
  of a session over the size cap only conversation records are kept, within a
  64 MB budget, but `compacted` records (which carry the whole replacement
  history) were matched as conversation and filled the budget first. In one
  real 1.1 GB rollout 5025 of 6960 conversation lines were dropped; it now
  indexes 2883 messages instead of 926. Large sessions are re-parsed once on
  the next sync.
- A Codex session that changes path keeps its summary. Moving a rollout to or
  from `archived_sessions`, or between a rollout and the history database,
  carried its tags and note over and deleted its summary.
- A rollout taken back out of `archived_sessions` is listed once. The old row
  was still live when the new one was indexed, so both stayed, and its tags
  stayed on the archived one.
- A Codex call declined at approval is recorded as not having run, instead of
  as a success.
- A Gemini chat's `/rewind` is applied: the rewound turns are no longer
  indexed and searchable as part of the chat.
- Gemini subagent transcripts, written under their parent chat at
  `chats/<parent session id>/`, are indexed, as subagents.

## [0.34.8] - 2026-10-20

### Fixed

- `blame` no longer credits a session that edited a different file whose name
  differs only where the asked-for name has `_` or `%`. The path query used
  them as SQL wildcards, so `blame KBS/newdata_copy.py` also took the session
  that edited `KBS/newdata copy.py`. `trace` already treated them literally.

## [0.34.7] - 2026-10-20

### Fixed

- **Gemini CLI chats written as JSONL are indexed.** Gemini CLI now saves
  each chat as `chats/session-*.jsonl` - a header line, `$set` lines and one
  line per message, repeated as the message grows - and only `.json` chats
  were read, so every Gemini session since mid-June was missing (14 on one
  machine). These chats are now folded back into their messages, each
  message once.
- **Search finds what was said in the middle of a large session.** A session
  over the 256 MB cap was indexed from its first 256 KB and last 512 KB only,
  so its conversation in between could not be searched: one 352 MB session
  had 1,733 prompts and 7 of them were indexed. The user and assistant text
  of a windowed Claude or Codex session is now kept from the whole file (up to
  64 MB of it); tool output in the middle stays windowed. The live windowed
  sessions are re-parsed once on the next sync.

## [0.34.6] - 2026-10-20

### Fixed

- **`trace` finds the files a large session edited.** A session over the
  256 MB cap is indexed from its first 256 KB and last 512 KB, and the files
  it edited in between were dropped with the rest of the middle. On one
  machine 82 sessions (29 GB) were windowed, the longest-running work there
  was, and three of them that edited 574 to 585 files each traced to none.
  The edited files are now read from the whole file, parsing only the lines
  that carry a tool call or patch, so `trace`, `files` and `blame` see every
  edit; the text stays windowed. The live windowed sessions are re-parsed
  once on the next sync (about 4 s per 3 GB).
- **`doctor` no longer calls Codex's thread history unreadable.** Since
  0.34.4 Codex's thread history is indexed from `thread_history_1.sqlite`,
  one database file, and `doctor` read every store as a directory, so it
  reported `store: codex - present but unreadable: Not a directory` on any
  machine that has one. A store that is a file is now opened as a file.

## [0.34.5] - 2026-10-19

### Fixed

- **Compressed Codex rollouts are indexed.** Codex compresses older rollouts
  in place, `rollout-*.jsonl` becoming `rollout-*.jsonl.zst`, and only
  `.jsonl` files were read. On one Mac, 678 of 684 rollouts were compressed:
  none were indexed, and the 667 indexed earlier were listed as deleted
  sessions once their `.jsonl` disappeared. Compressed rollouts are now read
  (with the pure-Rust `ruzstd` decoder), and each one absorbs its row from
  before compression, tags and note included.

## [0.34.4] - 2026-10-19

### Fixed

- **Codex threads kept only in Codex's history database are indexed.**
  Codex now stores thread history in `thread_history_1.sqlite` and may
  remove a thread's rollout file after migrating it. Only rollouts in
  `~/.codex/sessions` were read, so one machine with 2,987 threads of history
  showed 128 Codex sessions. Threads without a rollout are now read from the
  history database, with cwd and sub-agent status taken from `state_5.sqlite`.
  Rollouts in `~/.codex/archived_sessions` are indexed too (#65).
- **A Codex session that changes location is listed once.** Codex moves a
  rollout into `archived_sessions` when a thread is archived, and the rollout
  may be removed while the thread continues in the history database. The old
  location's row was kept as a deleted session beside the new one. It is now
  merged into the new row, with its tags and note, unless it held more
  messages than the new copy.
- **`sync --tool codex` covers every Codex store.** It ran only the first
  adapter of that name.

- **Codex MCP calls recorded only as events are indexed.** Some Codex
  rollouts record an MCP call only as its `mcp_tool_call_end` event, with no
  tool call or output beside it, and those calls were not indexed at all -
  5698 on one machine, 1608 of them failures. Each is now indexed from its
  event, marked as an error when it failed; a call that also has a tool call
  record is not repeated. Codex sessions already indexed are re-parsed once
  on the next sync.

## [0.34.3] - 2026-10-13

### Fixed

- **A failed Codex MCP tool call shows as an error.** Codex states an MCP
  call's failure only in its `mcp_tool_call_end` event (`isError`, or an
  `Err` result); the tool output beside it is plain text, so every failed
  MCP call read `⇒ ok` - 257 calls on one machine (an earlier version of this
  entry said 1782, counting calls that were not indexed at all; see 0.34.4).
  The event is now read and the call is marked as an error. The first open after
  upgrading marks Codex sessions already indexed for one re-parse, so the
  next sync corrects them too; sessions whose rollout is gone keep what they
  had.

## [0.34.2] - 2026-10-10

### Fixed

- **Workflow journals are no longer indexed as sessions.** Claude Code keeps
  a workflow's bookkeeping beside its agents' transcripts
  (`subagents/workflows/wf_*/journal.jsonl`). Every `.jsonl` was indexed, so
  each journal became an empty subagent session whose project was the
  `wf_*` folder name - 257 on one machine. Only `agent-*.jsonl` under
  `subagents/` is read now, and the next sync removes the journal rows.
- **A session with nothing indexed is removed, not archived, when its file
  goes.** Archiving was documented to skip such sessions, but kept every one
  as an archived row with no transcript.
- **"Kept after the tool deleted them" counts sessions.** `stats`, `doctor`
  and the sync summary counted every archived transcript, subagent
  transcripts included, beside a session total that counts only main
  sessions - one store read "3959 sessions, 2050 kept" where 611 sessions
  were kept. The kept count now covers main sessions, like the total.

## [0.34.1] - 2026-10-10

### Fixed

- **An older sessionwiki no longer rebuilds an index a newer one wrote.** The
  cache is rebuilt whenever its schema version differs from the binary's, and
  that included a NEWER version. A `sessionwiki mcp` server started before an
  upgrade keeps running the old binary, so after 0.34.0 rebuilt the index each
  such server rebuilt it back in the old format on its next call - keeping
  only the last 15 minutes of sessions - and the next CLI run rebuilt it again.
  An older binary now refuses a newer index with an error that says to
  restart it. Servers already running 0.33.x or earlier do not have this
  check: restart agent sessions that run `sessionwiki mcp` after upgrading.

## [0.34.0] - 2026-10-10

### Changed

- **Tool calls are stored as one compact line each**, for example
  `→ Bash(cargo test) ⇒ error · 12 lines — error[E0425]: ...`: tool name,
  primary argument, status, output line count, and the first output line on
  error. Every adapter (Claude Code, Codex, Gemini, gptme, Cline/Roo/Kilo,
  Continue, Gajae, OpenCode) emits structured calls and results, and one shared
  renderer formats them. The line is what `show`, `brief`, the web UI, MCP and
  search see; `brief` now includes tool lines by default, and `--tools`
  (`brief`) or `--full` (`show`) append bounded output. The default `summary`
  mode keeps only the compact line in new archives, plus the first output line
  for failed calls. This is less than the previous behavior, which kept up to
  500 characters of tool output. Run `sessionwiki tool-output full` to retain up
  to 8 KB of redacted output per result in archive mode. The per-index setting
  lets embedders choose; switching to `summary` clears full output from live
  sessions, while already archived sessions keep what they have. Switching
  back to `full` marks live sessions for re-parsing.
  Tool output is no longer indexed, so a string that appeared only mid-output
  no longer matches a search. Schema v9 rebuilds each existing index once on
  first use; the first run after upgrading re-parses every session, which can
  take a while on a large store.

## [0.33.2] - 2026-10-08

### Fixed

- **A prodex consult is listed once, and `show <id>` opens it.** The bridge
  registry can name one repo under two spellings - a case-variant working
  directory on a case-insensitive drive, or a symlink. Each spelling was
  walked, so every consult in that repo was indexed twice under one id: it
  appeared twice in `list` and `projects`, and `show`, `brief` and `resume`
  stopped with "ambiguous id" even given the full id. On the machine this was
  found, 524 consults were doubled. Discovery now walks each repo once, and
  the next sync drops the second copy instead of archiving it.
- **Gemini CLI sessions carry their project's path.** Gemini CLI names each
  project's chat folder with a short slug and records the real directory in
  a `.project_root` file beside it. The adapter used the slug, so a Gemini
  session's project read `myrepo` while every other tool's read
  `/home/me/myrepo`: `list --project /home/me/myrepo` and the session-start
  recall hook left Gemini sessions out, and `projects` showed the repo twice.
  On the machine this was found, all 46 Gemini sessions were affected. The
  project is now the recorded path, and the first open after upgrading
  corrects rows already indexed.
## [0.33.1] - 2026-10-07

### Fixed

- **Stopping the npm-installed command stops sessionwiki.** The npm launcher
  ran the binary with a blocking call that cannot pass a signal on, so a
  SIGTERM or SIGHUP to the `sessionwiki` command - from a process manager, an
  MCP host or `kill` - ended only the launcher. The binary kept running with
  no parent; `sessionwiki web` kept its port, so the next start failed. The
  launcher now forwards SIGINT, SIGTERM and SIGHUP to the binary and exits
  with its status once it has stopped.

## [0.33.0] - 2026-10-07

### Added

- **npm package.** `npm i -g @youdie006/sessionwiki` installs the prebuilt
  binary for macOS (arm64, x64), Linux x64 or Windows x64 through a platform
  package, with no install script. On macOS it upgrades the binary in place,
  which keeps folder-access grants across releases.

### Fixed

- **macOS keeps a folder-access answer across upgrades, and stops asking
  about media folders.** macOS ties a grant to read Documents or Desktop to
  the binary's path and code signature. Releases were ad-hoc signed, so every
  version looked like a new program and asked again - on one Mac, Desktop,
  Documents and Downloads prompts plus 23 Photos prompts in three days. The
  macOS binaries are now signed with one stable identity, so at a stable
  install path (npm, the install script) an answer given once still applies
  after an upgrade; Homebrew installs each version under a new path and still
  asks once per upgrade. The aider walk also no longer enters Pictures,
  Movies, Music or the Trash, which cannot hold a project and raised the
  Photos and Media Library prompts.
- **Index fix-ups also catch rows written later by an older binary.** The
  one-off passes that respell project paths (0.30.2) and mark Codex sub-agent
  threads (0.32.0) ran once and recorded that they had. A `sessionwiki mcp`
  started before an upgrade keeps running the old code, often for weeks, and
  kept writing case-variant paths and sub-agent threads as main sessions
  afterwards; nothing looked at those rows again. On the machine this was
  found, four sub-agent threads reappeared in `list` within an hour of
  upgrading. Each pass now records how far it has checked and, on every
  open, looks only at rows written since, so a late write is fixed the next
  time the current version opens the index.

## [0.32.0] - 2026-10-07

### Added

- **Search can filter by message role.** `--role user,assistant` limits matches
  to conversation messages before ranking and grouping, so tool output cannot
  crowd conversational matches out of search results. The web search and MCP
  search accept the same role filter.

### Fixed

- **Codex sub-agent threads are sub-agent sessions, not main ones.** Codex
  marks a sub-agent's rollout in its `session_meta` (`thread_source:
  "subagent"`), and its task arrives encrypted, so these threads have no
  readable prompt. The adapter ignored the marker and listed every one as a
  main session: on the machine this was found, 2,924 of 4,843 Codex "main"
  sessions were sub-agent threads, crowding `list`, the `projects` counts,
  `recent_sessions` and the recall hook with "(no user prompt)" rows. They
  are now sub-agent sessions like Claude Code's, and the first open after
  upgrading reclassifies rows already indexed by reading each file's first
  line (a one-off update, not a rebuild).
## [0.31.0] - 2026-10-06

### Added

- **Configurable FTS5 tokenizer.** `sessionwiki tokenizer` shows the current
  setting; `sessionwiki tokenizer <SPEC>` changes it and rebuilds only the FTS
  table from indexed messages. The choice is stored in the index and shared by
  CLI, web, and MCP.

### Fixed

- **Search now ANDs terms within one message.** Previously a multi-word query
  matched only the exact substring, including its whitespace. Quote words to
  require a phrase; phrase whitespace follows the configured tokenizer, and
  short terms still work alongside longer indexed terms.

## [0.30.2] - 2026-10-06

### Fixed

- **`projects` LAST and its order follow last activity, as `list` does.**
  0.30.1 moved `list` to each session's last message, but `projects` still
  took LAST from when its newest session began, so a project worked in
  yesterday through a session started in May showed May and ranked below
  projects untouched since. LAST is now the latest activity of any session in
  the project (its start when it has none), and equally busy projects are
  ordered by it. The web UI's project list reads the same value.
- **One directory is one project, however its case was typed.** On a
  case-insensitive filesystem (WSL's `/mnt/<drive>`, macOS by default) a
  shell can enter the same directory as `apo` or `APO`, and each tool records
  what it was given, so one project split into case-variant rows - on the
  machine this was found, 14 projects, one of them 23 + 514 sessions. Project
  paths are now stored as spelled on disk, and the first open after upgrading
  respells the rows already indexed (a one-off update, not a rebuild). The
  recall hook's exact project match uses the same spelling. A case-sensitive
  filesystem is unaffected: two directories that differ only in case stay
  two projects.

## [0.30.1] - 2026-09-30

### Fixed

- **`list` and the `recent_sessions` MCP tool order sessions by last
  activity.** They sorted by when a session started, so one resumed day after
  day sank below everything begun since: on the machine this was found, eleven
  sessions active within the last day ranked as weeks or months old, including
  the one asking. They now order by the session's last message (its start when
  it has none), and `list`'s WHEN column shows that time.

### Changed

- Session rows from `recent` carry `last_active` (RFC 3339, the last message's
  time) alongside `started` in `--json` and MCP output. `started` keeps its
  meaning.

## [0.30.0] - 2026-09-27

### Added

- **`Codex::in_home` and `ClaudeCode::in_home` for embedders with several
  installs of one tool.** A program that drives more than one Codex or Claude
  Code install (`~/.codex2`, `~/.claude4`, and so on) can now build one adapter
  per install root; the adapter knows its own session sub-directory layout, so
  the caller passes only the home. Every install keeps the shared tool name, so
  parsing by tool name still works for rows from any of them. An adapter built
  this way scopes deletion reconciliation to its own root, so syncing one
  install never archives another install's rows. `Codex::default()` and
  `ClaudeCode::default()` keep reading the stock locations and scope
  reconciliation to those locations.

### Fixed

- Syncing a stock Codex or Claude Code install no longer archives rows from
  another install. A later sync restores archived rows when their source still
  exists, without reparsing an unchanged transcript.

### Maintenance

- `clap` is updated from 4.6.6 to 4.6.7.

## [0.29.0] - 2026-09-17

### Added

- Embedders can index custom adapters with `index::sync_with`, restrict deletion
  reconciliation to their own keys with `Adapter::reconcile_scope`, and render
  a redacted briefing without its source path with `commands::brief_markdown`.
  Custom tool names are preserved when reading sessions from the index.

### Fixed

- Sessions indexed by an external adapter stay readable in `show`, `brief`, MCP
  and the web viewer while their source files still exist. Readers without the
  adapter use the indexed transcript instead of failing with `unknown tool`;
  the embedder must sync again to publish later changes. Built-in adapters still
  reparse live files and report parse errors. The web viewer now shares the same
  reader as the CLI and MCP.
- Redirected synchronization logs omit terminal-only progress redraws while
  retaining warnings and per-tool summaries.

### Maintenance

- CI and the dependency auto-merge gate use `actions/setup-python` v7 with
  the existing Python 3.12 configuration.

Implementation and validation: [PR #26](https://github.com/youdie006/sessionwiki/pull/26)
and [PR #27](https://github.com/youdie006/sessionwiki/pull/27). Publication and
installation verification are recorded in the
[0.29.0 release](https://github.com/youdie006/sessionwiki/releases/tag/v0.29.0).

## [0.28.0] - 2026-09-15

### Fixed

- **Large MCP turn responses remain valid JSON.** Quote-heavy and backslash-heavy
  text can expand when JSON-encoded, exceeding the transport cap even when its
  raw character count fits. Single-turn responses now retain the longest text
  prefix that fits after serialization and set `clipped: true`, preserving the
  schema, turn identity and original retained byte count. If metadata alone
  exceeds the limit, window and turn responses return a small, parseable JSON
  error instead of a success payload cut in the middle of a string.

## [0.27.0] - 2026-09-15

### Fixed

- **Exported session fields are redacted before they are shortened.** Briefs,
  summarizer input and MCP session windows now redact the complete parsed
  session, including titles, project names, paths, messages and edit snippets,
  before rendering or applying length limits. This covers reparsed originals
  and archived sessions, including single-turn MCP output. A token cut by a
  preview or output budget can no longer survive as an unrecognized prefix.
- **Prompt-derived titles and previews no longer preserve credential fragments.**
  Redaction runs before adapters select a title line or shorten tool previews,
  edit snippets and Prodex answers, including structured tool input and
  multiline private keys.
- **Turning off swapdex serving clears subsequent account badges.**
  `serve-off` is an explicit attribution boundary until a later `use`,
  `restore` or `serve` event activates an account. It no longer leaves the
  previous account attached to later sessions.
- **Incomplete discovery no longer looks like deleted sessions.** Aider walk
  errors and unreadable, malformed or partial Prodex registry/task listings
  retain the incomplete-discovery signal, so synchronization preserves live
  sessions until a complete listing can reconcile deletions.

### Maintenance

- Update `dirs` from 6 to 7. Its upstream behavior change affects Windows
  `preference_dir()`, which sessionwiki does not call; the home, configuration
  and data directory functions used for session discovery remain unchanged.
  The update was checked against the current implementation with 205 Rust
  tests and clippy passing.
- Dependency auto-merge now verifies the workflow, repository, PR and tested
  commit, checks permitted manifest and lockfile changes structurally, and
  rechecks current state before merging. Incomplete or inconsistent evidence
  refuses the merge. The gate's regression tests run in CI.

Implementation and review: [a1ef3a8](https://github.com/youdie006/sessionwiki/commit/a1ef3a884cacecb1b495fff5710709318de8ffc0)
and [PR #21](https://github.com/youdie006/sessionwiki/pull/21). Publication and
installation verification are recorded in the
[0.27.0 release](https://github.com/youdie006/sessionwiki/releases/tag/v0.27.0).

## [0.26.0] - 2026-09-07

### Fixed

- **A brief no longer carries credentials off the machine.** `redact` has
  stripped them since the beginning, at INDEX time, because the index outlives
  the original session. `brief_text` does not read the index: `load_session`
  parses the ORIGINAL file whenever it still exists and falls back to the index
  only when it is gone, so the same session was redacted only in the case where
  the original had been deleted. Every consumer sends the text somewhere -
  `brief` is written to be pasted into another session and says so, `recall`
  prints it for the same, `summarize` pipes it to an external LLM CLI, and the
  MCP server hands it to a connected agent. That MCP handler already neutralized
  the title, redacted the username out of the project path, stripped control
  characters and framed the whole thing as untrusted data; credentials were not
  on the list. Stripped now in `brief_text`, where all four meet, and before the
  length budget - a truncated secret is still a leaked prefix.
- **The timeline read is bounded for real.** `load_events` said it capped the
  read as defence against a hand-edited file, then read the whole thing into
  memory and capped only the PARSE. It takes the last megabyte as whole lines
  now, dropping the one the seek cut in half so no fragment can parse as a
  different record.
- **A partial store walk says it skipped deletion reconciliation.** Two paths
  carry that rule - do not archive off an incomplete listing - and only one said
  so. The silent one is the path aider takes, and aider is rootless: its walk
  covers the whole home under a two-second budget, and the flag is set on any
  cap-hit. On a large home reconciliation could be skipped every run with
  nothing saying why a session the tool deleted was still listed.

## [0.25.0] - 2026-09-07

### Fixed

- **The account badge names the account that actually served the session.** It
  counted swapdex's `use` and `restore` events, which was right while every
  switch went through them. Switching now goes through swapdex's proxy, which
  writes `serve` - and `serve` was being dropped as "not a switch". True of the
  event, false of the question: on a machine driven by the proxy it is the only
  record of which account was live. Every claude-code session on this one was
  badged with nothing while 190 serve events named three accounts, and codex
  sessions carried a `use` from six weeks before the account last changed. The
  newest event now wins whatever kind it is; a session that predates every event
  still gets no badge rather than a guess. The parsing half is separated from
  the file read so which lines survive it is testable.
- **The prodex adapter's four reads are bounded.** The memory cap on session
  files exists so a corrupt or hostile one cannot exhaust the process. Eleven
  adapters went through it; prodex read its task JSON, its result JSON, its
  registry and its artifact with a plain `fs::read` - one of them under a comment
  saying "Bounded read; an artifact is normally a few KB", where the largest file
  in the real store on this machine is 35 MB.
- **`doctor` no longer reports a failed count as zero.** The count of sessions
  kept after their tool deleted them turned any error - a schema without
  `archived_at`, a locked database - into "0 kept", which reads as the good news
  that nothing was lost.
- **A redirected run leaves the real index alone.** The one-time migration from
  the old directory names looked under `dirs::data_dir()` whatever `SESSIONWIKI_DATA`
  said, then renamed what it found into the destination - so a redirected run
  could move the user's real index out of their home.
- `ResumeInfo`'s doc claimed every supported tool encodes its native session id
  in the filename. Two of twelve do, and the code already answers None for the
  rest; only the comment was wrong.

### Added

- `doctor` says when a store's location could not be worked out, instead of
  giving that the same silence as a tool that is not installed. Defence, not a
  reproduced failure - on Unix `dirs` falls back to the passwd database, so
  unsetting HOME does not make it fire.

## [0.24.0] - 2026-08-20

### Fixed

- **A renamed folder no longer hides a file's history.** `trace` matched paths by
  suffix, so a file traced by the path it has TODAY found nothing once its folder
  had been renamed - and said "no session touched a file matching ...", about a
  file whose entire history was in the index under the old directory. Found on a
  real machine where `~/Project/lunch` had become `~/Project/slack`: the sessions
  that built it were all there and unreachable by the path the owner had. A full
  path that matches nothing now retries with the file NAME, which is the part
  that survives a move, and says so - otherwise the older paths listed underneath
  read as the index pointing somewhere wrong.

## [0.23.0] - 2026-08-19

### Added

- **`migrate --config-dir`** - write a transcript into a specific account's
  store instead of always the default one. This is what lets a conversation be
  handed to another ACCOUNT: under swapdex's slot model each account has its own
  `CLAUDE_CONFIG_DIR` with its own `projects/` inside, and migrate wrote into
  `~/.claude` unconditionally, so on a slotted machine the copy succeeded and
  landed where the resuming account never looks. Without the flag
  `CLAUDE_CONFIG_DIR` is honoured, so running inside a slot's own shell already
  does the right thing; failing both, the single default store.

- **`doctor`** - a read-only, one-command health check of this machine's setup:
  which session stores exist (and how many sessions each holds), the index's
  schema currency and core-table presence, how many sessions are indexed (and
  kept after a tool deleted them), and the version. `--json` for scripts. When
  something looks empty or stale the cause is usually mundane; this surfaces it
  so a bug report starts from facts.
- **Secrets are redacted from message text, titles, edit snippets, and synopses
  at index time** (`[redacted:<kind>]`) - PEM private keys, JWTs, and prefixed
  tokens (OpenAI, AWS, GitHub, Stripe, Google, Slack). The index outlives the
  original session via archive mode, so credentials must not land in it. A
  schema bump scrubs sessions already indexed before this change. Dependency-free
  and tuned to high-confidence shapes to avoid redacting ordinary code.
- **File history - "how this file was written".** Clicking a file in the web UI
  now shows its evidence chain: the sessions that edited it, newest first, each
  with what it actually changed - the edit kind (edit/write/multiedit) and a
  bounded snippet of the new code, not just a bare list of sessions that touched
  the path. This answers *why does this file look like this*. Backed by a new
  `edits(session_id, path, kind, ts, snippet)` cache table (extracted at parse
  time from each tool call, rebuilt on a schema bump like the other cache
  tables), an `evidence_for(path)` assembly, and a `GET /api/file?path=`
  endpoint. `trace`/`blame` still give the path-level provenance.

## [0.22.0] - 2026-07-20

Open any live session by its native id (codex-rollout or claude-transcript
UUID), closing the harness tower to sessionwiki join gap.

### Added

- `session_window`/`show` now resolve a session by its native codex-rollout or
  claude-transcript UUID (full or prefix), in addition to the sessionwiki short
  id. Live sessions not yet indexed are found via a disk-scan fallback (no
  sync), so a session started today opens by native id in one call.
- `list`, `recent_sessions`, and `search` JSON now expose a `native_id` field
  (the UUID only, never the absolute path). Closes the harness tower to
  sessionwiki join gap.

## [0.21.0] - 2026-07-16

Harden the MCP read path for in-loop agent-to-agent reads: a stable window
contract and freshness on every read tool.

### Added
- **`session_window` (MCP) now returns versioned JSON** (schema `sessionwiki.window/1`) instead of an unversioned text render, so a reading agent can parse a sibling's window rather than scrape it. Fields: `id`, `tool`, `project`, `title`, `started`/`ended`, `messages` (total turns), `large` (indexed head+tail), `budget_tokens`, `omitted_leading`, `turns[]` (each with `i` = stable turn index, `role` = user/assistant/tool, `text`, and `truncated` or `folded`+`bytes`), and a `drilldown` hint. Deterministic for a fixed (id, budget); the recent tail is kept within budget and the whole object is size-guarded so it is always valid JSON. Tool output is folded head+tail and byte-bounded.
- **Per-turn drill-down:** `session_window(id, turn=<i>)` returns that one turn's full retained text (schema `sessionwiki.turn/1`), untruncated by the window's folding/cap - fetch-full-content-on-demand for a turn seen in a window. (Tool outputs are already capped at parse time, so this recovers folded-out lines, not adapter-dropped bulk.)

### Changed
- **`search_sessions` (MCP) freshens in the background**, matching `recent_sessions` (0.20.2): it serves the current index immediately and kicks a bounded incremental sync, so a just-created sibling shows on a subsequent search without the request ever waiting on the store walk. `session_window` already reads the target file directly (live). This closes the last MCP read tool that did no freshen; incremental parsing (only files whose mtime/size changed) was already in place.

## [0.20.2] - 2026-07-16

### Changed
- **`recent_sessions` (MCP) freshens in the background.** It returns the current index immediately (~200ms) and kicks a bounded incremental sync, so a just-started sibling session shows on the next call - without the multi-second blocking sync a full 46GB-corpus walk would cost. New `index::sync_bounded` re-parses only files modified since a floor and never archives a live session on a bounded run.

## [0.20.1] - 2026-07-16

### Fixed
- **Over-cap sessions are windowed (head+tail) instead of dropped.** A session past the 256MB read cap was skipped entirely - so the biggest sessions, the ones most worth referencing across sessions, vanished from search and `session_window`. They are now indexed from the first 256KB + last 512KB of lines (byte-bounded, no full scan), partially readable, and flagged `[large]` in the title.

## [0.20.0] - 2026-07-15

Cross-session context for agents: one agent can now see what a sibling session
(or its other self) is doing, as the ACTUAL recent conversation - not a lossy
summary - bounded so it can't flood the reader's context.

### Added
- **`sessionwiki show <id> --window [--budget N]`** renders a session's real
  recent turns with tool outputs folded to head+tail, capped to the recent tail
  by a token budget, an orientation header + role labels, and a
  `show <id> --full` drill-down hint. `--live` reads the session file directly
  (0-delay), bypassing the index sync.
- **MCP discovery + read tools** so an agent can find and read sibling sessions:
  - `session_window(id, budget_tokens)` - the bounded window above, over stdio.
  - `recent_sessions(limit, tool, exclude_id)` - the most recent sessions across
    every tool ("who's around"), bounded to a recent window.
  - `related_sessions(id, limit, exclude_id)` - a session's siblings by shared
    project, edited files, or tags.
  Both discovery tools take `exclude_id` to drop your own session. This closes
  the chain: `recent`/`search`/`related` -> id -> `session_window`. Verified
  cross-tool (Claude Code and Codex sessions see each other).

### Fixed
- (from 0.19.4) `sessionwiki web` no longer auto-opens a browser on WSL, where
  `xdg-open` pops a stray WSLg/Windows window on every start and often can't
  reach the loopback server; it prints the URL instead. Native Linux/macOS keep
  auto-open.

## [0.19.4] - 2026-07-14

### Fixed
- **`sessionwiki web` no longer pops a stray browser window on WSL.** On WSL,
  `xdg-open` launches a WSLg/Windows browser on every `web` start - a blank
  window each time you restart the server during development, and it often
  cannot even reach the loopback address. `web` now detects WSL and prints the
  URL instead of auto-opening; native Linux/macOS keep the existing auto-open
  (still overridable with `--no-open`).

## [0.19.3] - 2026-07-14

Codex/Claude transcript formats drifted; a comprehensive audit against the
real corpus caught five parsing gaps, all fixed here.

### Fixed
- **Codex user messages no longer index twice.** Current rollouts carry each
  prompt BOTH as an `event_msg` and as a `response_item`; the adapter now
  cancels each pair exactly once (counted, so a genuinely repeated prompt -
  "continue" twice - still keeps every occurrence).
- **AGENTS.md instructions no longer become session titles.** The new
  `# AGENTS.md instructions for <path>` / `<INSTRUCTIONS>` user-message shape
  is treated as boilerplate, like the older environment-context wrappers.
- **2025-era Codex rollouts parse again.** Files that predate the `payload`
  envelope (bare `{"type":"message"}` lines) indexed as empty "(no user
  prompt)" sessions; they are now parsed like their modern counterparts.
- **`custom_tool_call` items are indexed** and their inputs feed `trace` /
  `blame` path extraction, so edits made through custom tools are no longer
  invisible.
- **Claude titles use the `ai-title` event.** Current Claude Code transcripts
  stopped emitting `summary` events; titles now fall back summary ->
  ai-title -> first user message instead of always the first prompt.

## [0.19.2] - 2026-07-07

### Fixed
- A crafted/corrupt prodex task id with a multibyte character at a slice
  boundary could panic the parser - and a parse panic aborts the WHOLE
  indexer, so one bad `.bridge` file bricked every `list`/`search`/`scan`.
  The id timestamp parse now gates on ASCII digits before slicing (found by
  an adversarial audit; same bug class swapdex fixed a release earlier).
- `list --account` no longer silently returns fewer rows than `-n`: the
  badge filter is computed post-query, so the query now over-fetches and
  truncates after filtering.

## [0.19.1] - 2026-07-07

Ecosystem-walkthrough fixes, from a fresh user's chair.

### Added
- `--account <name>` on `list` and `search`: filter by the swapdex @badge,
  which the help text now explains.
- prodex consult titles are the QUESTION (prompt first line) instead of
  prodex's identical auto-title, so a list of consults is tellable apart.
  The derived-cache version was bumped, so existing rows re-index once.

### Fixed
- A consult whose answer artifact was written but whose result JSON was not
  (the crash path the durable ledger exists for) is indexed again: the
  artifact is read independently of the result.
- `trace` with an ABSOLUTE editor path now finds sessions whose stored paths
  are repo-relative (prodex bundles relative paths; matching honors the `/`
  boundary, so suffix lookalikes cannot match).
- `--tool` help enumerates prodex and points at `scan` for the full list;
  the scan footer pluralizes correctly; scan's prodex PATH shows the store
  directory (not the registry file); the prodex resume error message no
  longer has a hanging indent.

## [0.19.0] - 2026-07-07

### Added
- prodex adapter: every ChatGPT Pro consult made through
  [prodex](https://github.com/youdie006/prodex) becomes a searchable session -
  the bridge task is the question, the result/answer artifact is the answer,
  and files bundled with a task become `trace` provenance links. Discovery
  reads the machine-wide bridge registry prodex >=0.11.0 maintains
  (`~/.local/share/prodex/bridges.json`); registered repos that no longer
  exist are skipped silently. `resume` on a prodex session prints the ChatGPT
  thread URL it ran in (only an `https://chatgpt.com/` URL is ever surfaced).
- Session ids for prodex are the same short stable 12-hex shape as every
  other tool (task ids share a long date prefix that would defeat prefix
  addressing).

### Changed
- `list`/`search` truncate the ID column display at 13 chars so an unusually
  long id cannot shear the table (ids are prefix-addressable).

## [0.18.1] - 2026-07-07

### Fixed
- `trace` and `related` rows now carry the swapdex `account` field like
  `list`/`search` do (the annotate call was missing on those two query paths,
  so the same session showed a badge in search but never in a file trace -
  across CLI, web, and MCP).

### Changed
- Timeline reads are capped to the newest 4000 lines (defense in depth;
  swapdex itself bounds the file to ~1000 events), and account names are
  control-char-stripped at the source so every consumer gets a terminal-safe
  badge. `search` no longer prints a trailing space on badge-less lines.
- The web UI shows the account badge in each session's meta line.

## [0.18.0] - 2026-07-07

### Added
- swapdex integration: `list` and `search` badge each session with the
  account profile active when it ran (`@work`), and `--json` rows carry an
  `account` field (null when unknown). Attribution reads swapdex's switch
  timeline read-only and never guesses - sessions that predate the first
  recorded switch stay unbadged. No swapdex on the machine, no change.
  The MCP server neutralizes the new field like every other free-text one.

## [0.17.0] - 2026-07-03

### Added
- `sessionwiki mcp`: a stdio MCP server exposing three read-only tools
  (`search_sessions`, `trace_file`, `get_session_brief`) to any MCP client
  (Claude Code, Cursor, and others). Cross-tool session search as agent tools;
  100% local, read-only, no sync. Register with
  `claude mcp add sessionwiki -- sessionwiki mcp`.
- Homebrew: `brew install youdie006/tap/sessionwiki` (macOS and Linux).

### Changed
- aider re-indexing is now linear instead of O(runs^2): a long
  `.aider.chat.history.md` is split once per sync and cached, so a file with
  thousands of runs re-indexes in a fraction of the time (measured 1600 runs:
  ~11s to ~0.2s).

### Fixed
- A partial directory walk (an unreadable project directory) can no longer
  archive live sessions: file-per-session adapters now report a partial listing
  and sync skips deletion reconciliation for that run, the same guard shared
  stores already had.
- `sync` warns when a session fails to parse and reports honest counts
  ("indexed 12/14 (2 failed to parse)") instead of silently dropping it.
- Tags are NFC-normalized on add, filter, and remove, so a tag typed in
  decomposed form (macOS IME) matches everywhere, like every other indexed
  string.
- `resume` checks tool support before file existence, so tools without headless
  resume (aider, OpenCode) get the right message instead of a false "the
  session file is gone".
- `digest --since` with an out-of-range duration returns an error instead of
  panicking.
- A failed data-directory migration now warns with instructions instead of
  silently starting an empty index.

## [0.16.1] - 2026-06-19

### Fixed
- crates.io README: the dark-mode banner now uses an absolute image URL so it
  renders on the crates.io page, which (unlike GitHub) does not rewrite relative
  `<source srcset>` paths. Docs only; no code change.

## [0.16.0] - 2026-06-19

### Added
- `aider` adapter (11th tool): indexes Aider sessions from per-repo
  `.aider.chat.history.md`. Markdown-derived (roles reconstructed from line
  prefixes, no per-message timestamps); edited files come from aider's
  `Applied edit to` / `Creating empty file` lines. Discovery is a bounded,
  capped, symlink-safe walk (home by default, `SESSIONWIKI_AIDER_ROOTS` to
  scope) that opens only `.aider.chat.history.md` and logs nothing.
- Recall loop (Claude Code plugin): a SessionStart hook auto-injects a small,
  fenced "prior work in this project" brief at the start of a new session, so the
  agent gets long-term memory without being asked. Exact-project scoped,
  `--no-sync` (tens of ms), zero output on fresh projects, always exits 0. The
  injected recall is fenced as untrusted data and sanitized; the LLM synopsis is
  not auto-injected. New internal `sessionwiki hook session-start` command.

### Changed
- Schema stability on the road to 1.0: the durable index tables (summaries,
  tags, notes, archive) now version independently of the disposable cache via a
  `meta.durable_version` and a forward-only, additive-only migration runner, so
  user curation and archived sessions survive every upgrade. All index
  connections now set a `busy_timeout`. No behavior change in this release (zero
  migrations registered).

### Security
- `search` strips control bytes (ESC/OSC/C1/DEL) from terminal snippets, so an
  untrusted session body can no longer inject terminal escape sequences into the
  operator's terminal. The `--json` output and other commands already did this.

## [0.15.0] - 2026-06-18

### Added
- `blame <file> [-L start,end]`: git blame for the AI era - attributes each line
  to the AI session most likely behind the commit that last changed it, by
  joining `git blame --line-porcelain` with the index's per-file touch records
  and session time windows. Best-effort by design (`ambiguous`/`unattributed`
  are normal) and it falls back to file-level `trace` whenever git can't carry
  the weight. The git child runs with a hardened environment (no system config,
  no pager, `core.fsmonitor`/hooks neutralized, inherited `GIT_*` cleared), the
  path is passed after `--`, and `-L` is validated. `--json` for agents.

### Security
- `truncate()` - the choke point that renders session titles to the terminal in
  `list`/`search`/`trace`/`resume` - now strips C0/C1/DEL control characters, not
  just newlines and tabs. A session title is untrusted input (a planted session
  can set any title), so an unstripped ESC could have injected ANSI/terminal
  escape sequences into output. The web UI was already safe (it builds the DOM
  with `textContent`, never `innerHTML`).

## [0.14.0] - 2026-06-18

### Added
- **gptme adapter** (10th tool): indexes sessions from [gptme](https://github.com/gptme/gptme)
  (`~/.local/share/gptme/logs/<session>/conversation.jsonl`). Drops `pinned: true`
  system-prompt boilerplate and bare `system` role lines; handles Python's naive
  `datetime.now().isoformat()` timestamps (no UTC offset) by falling back to
  UTC-assumed parsing. Size-capped against `MAX_SESSION_FILE_BYTES`.
- Windows install: `scripts/install.ps1`, a PowerShell one-liner (`irm ... | iex`)
  that downloads + checksum-verifies the latest Windows binary and adds it to
  PATH. The shell installer already covers WSL, which is Linux.

## [0.13.0] - 2026-06-18

### Security
Hardening from a red-team pass of the launch surface (all confirmed with PoCs):
- The local web server now rejects requests whose `Host` header isn't the
  loopback name it bound (defeats DNS rebinding) and whose `Origin` is a
  different site (defeats a plain cross-origin `fetch`), so a malicious page you
  visit while `web` is running can't read your sessions from `127.0.0.1`.
- `resume` no longer auto-launches Codex or Gemini in a directory the session
  file claims. Those tools aren't directory-scoped, so a planted session could
  name any directory (with an attacker's `AGENTS.md` there) and have `resume`
  load it; it now prints the command for you to run unless the directory is
  verified, which only Claude Code's store layout allows.
- `resolve` escapes `LIKE` wildcards in a session-id prefix, so a web request for
  id `%` can no longer match and dump an arbitrary session.
- install.sh documents honestly that its checksum only detects a corrupted
  download, not a malicious release (the hash is co-located with the binary).

## [0.12.0] - 2026-06-18

### Added
- `digest [--since 7d]`: a markdown rollup of recent sessions grouped by project
  &mdash; what you worked on, the files each session touched, and any cached
  synopsis. It composes the timeline, provenance, and summaries the index already
  has, over a time window (`--since 2w`/`24h`/`90m`, `--project`, `--tool`,
  `--json`). The standup / PR-description / "what did I ship this week" view.

### Security
- `resume` no longer auto-launches the upstream tool (`claude`/`codex`) in the
  directory a session file *claims* unless that directory can be verified as the
  session's own &mdash; for Claude Code, by matching the store folder the session
  lives in (the folder name encodes the cwd). A session file is untrusted input;
  before this, a planted or prompt-poisoned session could point its `cwd` at an
  attacker directory and have `resume` launch the agent there, loading that
  directory's `CLAUDE.md` / `.mcp.json` / settings. When the directory can't be
  verified, `resume` now prints the command for you to run instead of launching.
- Session-file reads are size-capped (256 MB) and the OpenCode SQLite message/
  part reads are `LIMIT`ed, so a malicious oversized file or a db packing
  millions of rows into one session can't exhaust memory.

### Changed
- `SECURITY.md` now documents that `migrate` writes copies into the target tool's
  store and that `resume` validates the session-derived directory, instead of
  implying the tool only ever reads.

## [0.11.0] - 2026-06-18

### Added
- `migrate <id> <dir>`: copy a session so it can be resumed from a different
  project directory. Each tool ties a session to a directory differently, so
  migrate does the right thing per tool: Claude Code's resume is scoped to the
  project folder, so the transcript is copied into the target's folder; Codex
  resumes by id from any directory, so nothing is copied (it just prints the
  command); Gemini copies the chat into the target project's store
  (`~/.gemini/tmp/<sha256(dir)>/chats/`) and rewrites its `projectHash`. The
  original session is never modified.

## [0.10.0] - 2026-06-17

### Added
- `recall <query>`: one-shot recall — searches, lists the candidate matches, and
  briefs the top one, collapsing the usual search -> pick id -> brief loop into a
  single command (`--tool`/`--project`/`-n`/`--max-chars`/`--json`/`--no-sync`).
- `sync [--tool]`: build or refresh the index on demand, so later queries can run
  with `--no-sync`.
- `--no-sync` on `search`/`list`/`recall`/`show`/`brief`/`resume`/`trace`: query
  the already-built index without walking the stores — the fast path when the
  index is kept warm (e.g. a cron running `sessionwiki sync`).

### Changed
- `show`/`brief`/`resume`/`recall` resolve the id against the existing index first
  and only sync (all tools) when it is genuinely unknown (no prefix match) - an
  already-indexed id, including an *ambiguous* prefix, no longer triggers a full
  walk of every store (notably the large Codex one). The tradeoff: a session that
  has grown since the last sync is served at its last-synced length until the next
  `sync`.
- Harness labeling (the oh-my-* tags from 0.9.0) is now detected from the
  filesystem only - the `.omc`/`.omo` orchestration directory in a session's
  project - dropping the transcript-text markers. Those markers were the tools'
  own source/doc literals, so a session that merely *discusses* a harness (e.g.
  while building OSS) was mislabeled as run by it; the filesystem signal cannot
  be confused that way. oh-my-codex leaves no directory and is no longer tagged.
- A tag filter (`list --tag`, web) now includes subagent transcripts, and `list`
  marks them `[subagent]`, so a tag carried only by a subagent is no longer shown
  in the tag cloud yet hidden from the listing.

### Fixed
- `recall --json` includes the plain `snippet` next to `snippet_marked` in each
  candidate, matching `search --json`; `recall`'s candidate list marks subagent
  transcripts `[subagent]`.
- `sync` reports the count of top-level live sessions (matching `stats`/`list`)
  instead of every file row, which had included subagent transcripts.

## [0.9.0] - 2026-06-17

### Added
- Five new adapters, bringing supported tools to nine: the **Cline family**
  (Cline, Roo Code, Kilo Code) from one parser over their shared VS Code
  `globalStorage/<ext>/tasks/<id>/` layout - handling both native `tool_use`
  blocks and the XML-in-text tool calls Cline writes, and pulling edited files
  from either; **gajae-code** (and upstream Pi) from `~/.gjc/agent/sessions`
  JSONL; and **Continue** from `~/.continue/sessions/*.json`. Each extracts the
  files a session edited so they show up in `trace`.
- Harness labeling for the Korean "oh-my-*" wrappers. oh-my-claudecode,
  oh-my-codex, and the oh-my-openagent / lazyclaudecode / lazycodex family run
  on top of Claude Code, Codex, and OpenCode, so their conversations are already
  indexed via those adapters; sessionwiki now detects which harness drove a
  session (from the markers each injects) and auto-tags it `oh-my-claudecode` /
  `oh-my-codex` / `oh-my-openagent`, so `list --tag oh-my-claudecode` works. No
  new adapter required.

### Changed
- The OpenCode adapter now reads OpenCode's SQLite store
  (`~/.local/share/opencode/opencode.db`, plus `opencode-<channel>.db` and
  `OPENCODE_DB`), which has been the default since OpenCode v1.2.0 - the
  previous JSON-only reader missed every session created on a current install.
  The legacy `storage/**` JSON layout is still read on pre-1.2.0 installs. This
  needed a small shared-store path in the indexer (one SQLite db holds many
  sessions, so the file-per-session + mtime model did not fit); `scan` sizes the
  db and re-indexes only sessions whose updated-time changed.

## [0.8.0] - 2026-06-17

### Added
- OpenCode adapter: indexes sst/opencode sessions from
  `~/.local/share/opencode/storage` (the multi-file session/message/part JSON
  layout, joined in id order), including the files each session edited (the
  `edit`/`write` tools' `filePath` and `patch` file lists) for `trace`. Brings
  supported tools to four.
- Provenance: sessions are linked to the files they edited or created, read
  from their tool calls (Claude's `Edit`/`Write`/`MultiEdit`, Codex's
  `apply_patch`). New commands: `files <id>` (a session's edits) and
  `trace <path>` (the sessions that touched a file, newest first, matched by
  suffix so a relative path resolves to the absolute one on disk). The scope is
  honest — sessions that *touched* a file, not line-level authorship.
- `related` now also links sessions that edited the same file, even across
  projects; `stats` reports the count of files linked to a session.
- Web UI: a session's touched files appear as chips in its header; clicking one
  lists every session that touched it (new `/api/trace` endpoint).
- Archive mode: when a tool deletes a session's original file, sessionwiki
  keeps the indexed copy instead of dropping it, so `search`, `trace`, and
  `brief` keep working for it. A durable `archive` table survives schema
  rebuilds; archived sessions are served from the index (`show`/`brief`/web),
  flagged `[archived]` in `list`/`show`/web, and counted in `stats`. `sync`
  reports how many were kept. New `forget <id>` purges a session for good;
  re-appearing files un-archive automatically; `SESSIONWIKI_NO_ARCHIVE` reverts
  to delete-on-prune. A store that vanishes wholesale (uninstall, unmount) is
  not mass-archived.
- Korean/CJK search: 2-syllable words (회사, 검색) - the most common Korean word
  length - are now searchable via a LIKE fallback below the trigram floor, and
  all indexed text + queries are NFC-normalized so macOS NFD input no longer
  silently returns nothing. "Zero-setup CJK search" is now actually true.
- `--json` on `search`, `list`, `related`, `brief`, `trace`, and `files`: stable
  snake_case output (matching the web API) for agent consumption, with the
  absolute path hidden. Snippets are control-code-free with a `snippet_marked`
  variant. The agent-native half of the tool.
- Claude Code plugin (`/plugin marketplace add youdie006/sessionwiki`): a
  `session-recall` skill + `/sessionwiki:recall` command that use the `--json`
  commands so an agent recalls past sessions as long-term memory, fully offline,
  degrading gracefully when the CLI isn't installed.

### Changed
- `show` pages long transcripts through your pager (`SESSIONWIKI_PAGER`, then
  `PAGER`, default `less -FRX`) when stdout is a terminal, so `show --full` of a
  huge session no longer floods the screen, and falls back to plain printing when
  no pager is installed; piped/redirected output is unchanged.
- `summarize` states up front that it pipes each transcript to the summarizer
  (the default `claude -p` sends them to the Anthropic API) - the one place data
  can leave the machine, and only on explicit `summarize`.
- CLI demo is a clean static full-frame terminal (no camera zoom). The web demo
  zooms to exact element regions measured from the live DOM, at 50fps with
  cubic ease-in-out moves and still holds.

### Fixed
- `tag` now rejects a tag containing a comma or an empty tag: a comma corrupted
  the comma-joined `tags` array in `--json` and the web API, and an empty tag
  emitted `""`. JSON serialization of session rows in `search`/`trace` can no
  longer panic mid-array.

## [0.7.0] - 2026-06-16

### Changed
- Renamed the project from `sessiondex` to **sessionwiki**, reframed around
  "session engineering": a session is a unit of context, and once you have
  hundreds they need curating, not just searching. The data directory migrates
  newest-name-first (`sessiondex` then `session-atlas`), carrying the index and
  curated tags/notes/summaries over.

### Added
- Curation layer (the editable "wiki" part): `tag` / `note`, stored in the
  index and surviving reindexing; the original session files are never touched.
- `related`: sessions about the same thing — same project first, then anything
  sharing a tag — surfaced in `show` and as a "see also" panel in the web UI.
- `projects` and `stats`: per-project and per-tool/per-month rollups.
- Web UI: clickable tag chips and a tag-filter bar, notes, a "see also" panel,
  a node-graph logo, and a globe-button language picker.
- Two demo GIFs: a narrated CLI recording (`docs/demo-cli.gif`) and a web UI
  tour (`docs/demo-web.gif`). `SECURITY.md`.

## [0.6.0] - 2026-06-16

### Added
- Library + binary split (`src/lib.rs`): the adapter and index logic is now a
  reusable crate, not just a CLI.
- Golden-file parser tests for all three adapters, covering boilerplate
  dropping, subagent detection, schema variants, multi-block content, and
  malformed-line tolerance (`tests/parse.rs`, `tests/fixtures/`).
- GitHub Actions: CI (fmt + clippy + test) and a release workflow that builds
  prebuilt binaries for Linux, macOS (x86_64 + arm64), and Windows on tag push.
- `scripts/install.sh` one-line installer that fetches the right prebuilt
  binary for the platform.
- A "how this differs from a single-tool viewer" section in the README.

## [0.5.0] - 2026-06-12

### Changed
- Renamed the project from `session-atlas` to **sessiondex**. The data
  directory migrates automatically on first run, carrying the existing index
  and cached summaries over.

### Added
- Multilingual web UI (English, Korean, Japanese, Chinese), auto-detected from
  the browser locale and switchable from the sidebar.
- Korean README (`README.ko.md`).

## [0.4.0] - 2026-06-12

### Added
- `summarize`: cache 1–2 sentence LLM synopses using your own LLM CLI. Stored
  in a table that survives index schema rebuilds.
- README polish: logo, light/dark adaptive hero, architecture diagram, FAQ.

## [0.3.0] - 2026-06-12

### Added
- Session previews (last assistant message) in the web sidebar.
- `show --outline`: a deterministic digest of a session (every user turn plus
  how it ended), and a clickable outline in the web transcript.

## [0.2.0] - 2026-06-12

### Added
- `resume`: reopen a session in its original tool (`claude --resume` /
  `codex resume`) in the right project directory.
- `brief`: emit a markdown briefing of a session to carry context across tools.

## [0.1.0] - 2026-06-12

### Added
- Initial release: `scan`, `list`, `search`, `show`, and a local web UI over an
  incremental SQLite FTS5 index. Adapters for Claude Code, Codex, and Gemini
  CLI. 100% local, no telemetry.

[0.15.0]: https://github.com/youdie006/sessionwiki/compare/v0.14.0...v0.15.0
[0.14.0]: https://github.com/youdie006/sessionwiki/compare/v0.13.0...v0.14.0
[0.13.0]: https://github.com/youdie006/sessionwiki/compare/v0.12.0...v0.13.0
[0.12.0]: https://github.com/youdie006/sessionwiki/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/youdie006/sessionwiki/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/youdie006/sessionwiki/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/youdie006/sessionwiki/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/youdie006/sessionwiki/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/youdie006/sessionwiki/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/youdie006/sessionwiki/compare/v0.5.0...v0.6.0
[0.5.0]: https://github.com/youdie006/sessionwiki/releases/tag/v0.5.0
[0.4.0]: https://github.com/youdie006/sessionwiki/releases/tag/v0.4.0
[0.3.0]: https://github.com/youdie006/sessionwiki/releases/tag/v0.3.0
[0.2.0]: https://github.com/youdie006/sessionwiki/releases/tag/v0.2.0
[0.1.0]: https://github.com/youdie006/sessionwiki/releases/tag/v0.1.0