throughline 0.3.25 → 0.4.1

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.
@@ -4,27 +4,12 @@ description: 次の新規セッションに現セッションの記憶を引き
4
4
 
5
5
  Throughline の UserPromptSubmit hook が `/tl` を検出し、バトン(現セッション ID)を保存しました。
6
6
 
7
- 次に必ずやること(スキップ厳禁):
7
+ これだけで完了です。**追加の操作は不要**。
8
8
 
9
- 1. 今この時点の「中断地点の状態」を自分の文脈から思い出し、以下 4 項目を Markdown で整理する:
10
- - **次の一手**: 今まさに何をやろうとしていたか(1-3 文、具体的に)
11
- - **現在の方針 / 仮説**: 追っているバグの原因、設計の方向性、調査中の観点など
12
- - **未解決の疑問**: 判断保留中の論点
13
- - **進行中 TODO**: 完了済みを除いた現行 TODO(TodoWrite の最新状態や Plan の内容を踏まえて、意味のあるものだけ)
9
+ このあと:
10
+ - 1 時間以内に新セッションを開く(新 chat / VSCode 再起動など)と、Throughline がバトンを消費して前セッションの記憶 (L1 + L2 + L3 references) を新セッションに自動注入します
11
+ - バトンは 1 時間で失効します
14
12
 
15
- 2. Bash ツールで次のコマンドを実行し、stdin で上記 Markdown を流し込む:
13
+ 通常は `/clear` だけで自動引継ぎが発火するため、`/tl` **`THROUGHLINE_DISABLE_AUTO_HANDOFF=1` で自動引継ぎを OFF にしているユーザー** または **`/clear` を経由せずに新セッションを開くケース** の明示意思マーカーとして使います。
16
14
 
17
- ```bash
18
- throughline save-inflight <<'EOF'
19
- **次の一手**: ...
20
- **現在の方針**: ...
21
- **未解決の疑問**: ...
22
- **進行中 TODO**:
23
- - [ ] ...
24
- - [ ] ...
25
- EOF
26
- ```
27
-
28
- Bash の出力 (`[throughline] in-flight memo saved (N chars) for next session`) がそのまま完了確認になります。追加のユーザーへの報告テキストは不要です。ツール呼び出し後は何も返さずターンを終えて構いません(必要なら一言だけ)。
29
-
30
- バトン(および in-flight メモ)は 1 時間で失効します。失効後に新セッションを開いた場合は引き継ぎは発火しません。
15
+ ユーザーへの追加報告テキストは不要です。一言だけ完了を伝えるか、何も返さずターンを終えて構いません。
package/CHANGELOG.md CHANGED
@@ -10,6 +10,94 @@ shipped to npm but were not individually tagged on GitHub.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.4.1] — 2026-05-09
14
+
15
+ ### Changed
16
+
17
+ - **`/clear` も baton を書き込むように変更**。UserPromptSubmit hook で `/clear`
18
+ を検出した時点で当該セッションの `session_id` を `handoff_batons` に書き、
19
+ 次の新規 SessionStart が確定的にそのセッションを引き継ぐ。これにより、複数
20
+ VSCode ウィンドウなどで「最新更新セッション ≠ /clear したセッション」になる
21
+ シナリオで `findLatestClaudePredecessor` heuristic が誤った前任を選ぶ問題を
22
+ 解消。
23
+ - **2 経路の優先順位を入れ替え**: baton path が **primary**、`source='clear'`
24
+ の auto path は **fallback**。auto path は `/clear` が UserPromptSubmit hook
25
+ に届かない経路 (例: VSCode 拡張のメニュー由来) のためのフォールバック扱い。
26
+
27
+ ### Added
28
+
29
+ - `src/prompt-submit.mjs`: `isClearCommand` 判定 (`/clear`, `/clear ...`,
30
+ 前後空白許容、`/cleared` / `/clearcache` 等の prefix 偽陽性は拒否)。
31
+ - `~/.throughline/logs/baton-write.log` の `trigger` フィールドに
32
+ `'tl' | 'clear'` を記録。
33
+ - `src/prompt-submit.test.mjs`: `isBatonCommand` / `isClearCommand` の判定
34
+ テスト 14 件。
35
+ - `src/hook-entrypoints.test.mjs`: `/clear` baton の subprocess+DB 実体テスト
36
+ 3 件 (`/clear` 書き込み / `/tl` → `/clear` 後勝ち上書き / 通常 prompt は no-op)。
37
+
38
+ ### Notes
39
+
40
+ - 既存の `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` env は **fallback path のみに作用**
41
+ するようになった。typed `/clear` は env に関係なく baton 書き込み → 引継ぎ発火
42
+ する (= ユーザーが明示的に `/clear` を打った時点で「続けたい」という意思表示
43
+ と解釈する)。auto path (VSCode メニュー由来) には引き続き env が効く。
44
+
45
+ ### Repository hygiene
46
+
47
+ - `.vscode/tasks.json` を git 追跡から外す (`.gitignore` に追加)。
48
+ `ensureMonitorTaskFile` が hook 発火ごとに絶対パスを書き換えるため、追跡
49
+ 対象に置くと別 OS / 別マシンで毎回 dirty diff が出続けていた。各マシンでは
50
+ 初回 hook 発火時に自動生成される。
51
+
52
+ ## [0.4.0] — 2026-05-08
53
+
54
+ ### Breaking changes
55
+
56
+ - **`/clear` で自動引継ぎがデフォルト ON** に変更。Claude Code 2.1.128 で
57
+ SessionStart hook の `source='clear'` が reliable になったため、`/clear` 後の
58
+ 新セッションは自動的に前セッションの memory を merge + 注入する。
59
+ ([GitHub issue #49937](https://github.com/anthropics/claude-code/issues/49937)
60
+ は解決済み)
61
+ - **`THROUGHLINE_DISABLE_AUTO_HANDOFF=1`** env var で auto path を OFF にできる。
62
+ - **`/tl` の役割を明示意思マーカーに簡素化**。memo 4 項目入力の指示を削除し、
63
+ baton を立てるだけの slash command に。`/tl` は env で auto OFF にしている
64
+ ユーザー、または `/clear` を経由しない引継ぎに使う逃げ道。
65
+ - **`/tl-trim` slash command 廃止**。memo 入力 + dry-run preview の役割を持って
66
+ いたが、memo 廃止と軽量化方針で役割なしに。Codex 経路の `throughline trim`
67
+ CLI は維持 (`--host codex` での guarded execute / preflight など)。
68
+ - **`throughline save-inflight` CLI 削除**。memo 廃止に伴う除去。
69
+ - **`updateBatonMemo` 関数削除**。`src/baton.mjs` の export から外した。
70
+ - **schema v8 migration**: `handoff_batons.memo_text` 列を drop。
71
+ - **注入内容を L1 + L2 + L3 references のみに簡素化**。memo セクション、
72
+ 中断直前 thinking セクション、Claude 向け footer の使い方説明を削除。L2 全文
73
+ に「次に何をしようとしていたか」が含まれているため redundant。
74
+
75
+ ### Added
76
+
77
+ - `src/db.mjs`: schema v8 migration (handoff_batons.memo_text 列 drop)。
78
+ - `src/session-start.mjs`: 引継ぎ判定の 2 経路ロジック:
79
+ 1. baton path: `consumeBaton` 先発で baton ありなら merge + 注入
80
+ 2. auto path: baton 無し + `source='clear'` + env disable 無し で同 project の
81
+ 最新 Claude unmerged session を自動 predecessor に merge + 注入
82
+ - `inheritance-decision.log` に `triggered_path` / `auto_handoff_disabled`
83
+ フィールドを追加。`baton_has_memo` フィールドは削除。
84
+ - `src/resume-context.mjs`: L3 references 一覧を注入テキストに追加
85
+ (Codex `renderCodexRolloutMemoryPreview` 形式の `- ${kind}:
86
+ \`throughline detail <time>\``)。Reading Contract / Continuation Instruction
87
+ も Codex 風 framing に揃えた。
88
+
89
+ ### Notes
90
+
91
+ - `src/handoff-record.mjs` の memo / thinking projection は **維持**: Codex 側
92
+ (`codex-handoff.mjs`, `codex-resume.mjs`, `codex-handoff-smoke.mjs` など) が
93
+ `memory.inflightMemo` / `memory.latestThinking` を参照しているため。Claude
94
+ 側は resume-context.mjs で「使わない」だけ。
95
+ - `src/cli/trim.mjs` は **維持**: Codex 経路 (`--host codex`) と doctor
96
+ (`--trim --host claude`) で使う `describeTrimHost('claude')` の dry-run 表示
97
+ が依存しているため。`/tl-trim` slash command が無くなっても CLI は残る。
98
+ - 既存 `~/.throughline/logs/inflight-memo.log` ファイルは新版で書き込まれない。
99
+ ユーザー側で手動削除可能。
100
+
13
101
  ## [0.3.25] — 2026-05-08
14
102
 
15
103
  ### Added
package/README.ja.md CHANGED
@@ -126,60 +126,58 @@ L3 に保存された `kind` 別 (ツール入力 / ツール出力 / hook 出
126
126
 
127
127
  ---
128
128
 
129
- ## 明示的引き継ぎ `/tl` (in-flight メモ付き)
129
+ ## 引き継ぎ: `/clear` で自動、env で OFF、`/tl` で明示
130
130
 
131
- 引き継ぎは **明示的** であり、自動ではありません。次セッションへ「ここから続けてほしい」と
132
- 渡したいときは、現セッションで `/clear` または新規チャットを開く **前に** `/tl` を打ちます。
133
- `/tl` 無しの場合、新セッションはまっさらな状態で始まり、過去メモリは引き継がれません。
131
+ Throughline 0.4.0 から引き継ぎは 2 経路:
134
132
 
135
- `/tl` は 2 つの仕事をします:
133
+ ### auto path (デフォルト): `/clear` で自動引き継ぎ
136
134
 
137
- 1. **引き継ぎバトンの書き込み**。現在の `session_id` `handoff_batons` テーブルへ、
138
- `UserPromptSubmit` hook 経由で記録します。
139
- 2. **現 Claude in-flight メモを書かせる**。`/tl` は Claude に対し、
140
- *次に何をしようとしていたか、現在の仮説、未解決の問い、進行中 TODO* を Markdown で
141
- 要約し、`throughline save-inflight` 経由でバトンの `memo_text` カラムに添付するよう
142
- 指示します。これにより、トランスクリプト再生だけでは保てない「いま考え中だった内容」を保存できます。
135
+ Claude Code 2.1.128 以降は `/clear` 直後の SessionStart hook に
136
+ `source='clear'` が確実に乗ります。Throughline がこれを検出して、前セッションの
137
+ メモリを新セッションに自動 merge します。**ユーザー操作不要** `/clear`
138
+ だけで新チャットが「途中から」再開されます。
143
139
 
144
- 次の `SessionStart` では、hook がバトンを読み、**1 時間以内** であれば
145
- そのセッションのメモリを `BEGIN IMMEDIATE` トランザクション内で
146
- `UPDATE session_id = ?` を使って決定論的にマージします。バトンはマージと
147
- 原子的に消費 (削除) されるため、二重発火しません。注入される再開コンテキストは
148
- **「中断されたタスクの再開」** として再フレーミングされ、in-flight メモと最終ターンの
149
- 拡張思考が先頭に来ることで、新 Claude は思考の途中から拾えます。
140
+ `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` を環境変数に立てると auto path を OFF にできます。
141
+
142
+ ### baton path (`/tl`): 明示意思マーカー
143
+
144
+ 次のいずれかのユーザー向け:
145
+
146
+ - `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` を立てている、**または**
147
+ - `/clear` 経由しないで引き継ぎたい (新 chat / VSCode 再起動など)
148
+
149
+ 新セッションを開く前に `/tl` を打つと `UserPromptSubmit` hook が baton を書き、
150
+ 次の `SessionStart` (1 時間以内) が baton を消費して merge します。
151
+ `source` 値関係なく発火します。
150
152
 
151
153
  ```
152
- Session A (/tl を打つ) -----------> バトン書き込み
153
- |
154
- /clear |
155
- | ▼
156
- Session B ---- バトン読込 → A を B にマージ → バトン削除 ---->
157
- |
158
- (もう一度 /tl で更に渡せる)
154
+ auto path: Session A /clear → Session B (A を auto-merge)
155
+ baton path: Session A → /tl → (新 chat / 再起動) → Session B (baton を消費して A を merge)
159
156
  ```
160
157
 
161
- 明示的バトン方式を選んだ理由:
158
+ ### 注入されるもの
159
+
160
+ 両経路で同じ curated memory が注入されます:
162
161
 
163
- - **誤継承ゼロ**。並行ウィンドウや VSCode 再起動、同じリポジトリでの新規タスクが、
164
- 前セッションのメモリを誤って引き継ぐことはありません。`/tl` 明示時のみ発火。
165
- - **VSCode 拡張対応**。`SessionStart` hook `source` フィールドは VSCode 拡張で
166
- `/clear` 後も `"startup"` に書き換えられてしまう
167
- ([issue #49937](https://github.com/anthropics/claude-code/issues/49937))。
168
- source 判定は信用できないため、ユーザー駆動のバトンで回避。
169
- - **決定論的**。時間窓ヒューリスティック、PID 推測、祖先プロセス追跡なし。
170
- ユーザーが意思を宣言し、hook が実行する。それだけ。
162
+ - L1 サマリー (古い turn の一行要約)
163
+ - L2 verbatim (直近 20 turn の本文)
164
+ - L3 references (`throughline detail <時刻>` で引き出すコマンド一覧、本文は SQLite に残置)
171
165
 
172
- 各マージ行は `origin_session_id` を保持するので、`/tl` を繰り返すと
166
+ 注入は **「中断されたタスクの再開」** として再フレーミングされます。L2 verbatim に
167
+ 最終 assistant turn (= 次に何をしようとしていたか) が含まれるため、別途 memo /
168
+ extended thinking セクションは注入されません。
169
+
170
+ 各マージ行は `origin_session_id` を保持するので、繰り返し引き継ぐと
173
171
  記憶がチェーン状に蓄積します:
174
172
 
175
173
  ```
176
- S1 (4 ターン) --/tl,/clear--> S2 (S1 をマージ + 3 ターン追加) --/tl,/clear--> S3 (S2 をマージ + 5 ターン追加)
177
- origin=S1×4 origin=S1×4, S2×3, S3×5
174
+ S1 (4 ターン) --/clear--> S2 (S1 auto-merge + 3 ターン追加) --/clear--> S3 (S2 auto-merge + 5 ターン追加)
175
+ origin=S1×4 origin=S1×4, S2×3, S3×5
178
176
  ```
179
177
 
180
178
  ---
181
179
 
182
- ## Codex sidecar と `/tl-trim` プレビュー
180
+ ## Codex sidecar と Codex trim
183
181
 
184
182
  Throughline の主軸は引き続き **Claude Code** です。Codex 対応は、Claude hooks /
185
183
  slash command / transcript / baton / resume behavior を置き換えるものではなく、
@@ -189,20 +187,11 @@ adapter / projection として追加されます。
189
187
  `codex-sidecar` が `summarize-l1` preset で設定されている場合はその要約に
190
188
  Codex sidecar を使えます。使えない場合は、従来どおり Claude Haiku 経路を使います。
191
189
 
192
- `/tl-trim` は現在 **dry-run のみ** です。何ターンを trim 候補にするか、
193
- どの recent context を残すか、どの curated memory を戻す必要があるかを表示します。
194
- automatic rollback / inject host primitive の検証が終わるまで無効です。
195
-
196
- ```bash
197
- throughline doctor --trim --host claude
198
- printf '**次の一手**: 今の実装を続ける\n' \
199
- | throughline trim --dry-run --host claude --memo-stdin
200
- ```
201
-
202
- 重要なのは current-work framing です。L1/L2 をそのまま戻すだけだと、
203
- モデルがそれを「過去ログ」として読んでしまうことがあります。Throughline は recent L2 を
204
- active work thread として構造化し、古い仮説は後続の判断で上書きされ得ること、
205
- そして中断地点から続行することを、注入 memory の先頭と末尾で明示します。
190
+ Codex 側 trim (= same-thread context trim) は `throughline trim --execute --host codex`
191
+ で発火します。Claude 側は `/clear` での auto path 引継ぎが本線になったため、
192
+ `/tl-trim` slash commandv0.4.0 で廃止されました。current-work framing は
193
+ SessionStart 注入の Reading Contract / Continuation Instruction で同じ意図を
194
+ 継承しています。
206
195
 
207
196
  ---
208
197
 
@@ -238,13 +227,13 @@ throughline monitor --session <id-prefix>
238
227
  | `throughline monitor` | マルチセッション監視を起動 |
239
228
  | `throughline monitor --diag` | TTY/columns/env 診断ダンプ (描画バグ切り分け用) |
240
229
  | `throughline detail <時刻>` | あるターンの L2 本文と L3 ツール I/O を取得 (Claude が使う) |
241
- | `throughline save-inflight` | `/tl` から呼ばれ、現バトンに in-flight メモを添付 (stdin 経由) |
242
230
  | `throughline doctor` | Node バージョン、hook 登録状況、DB、PATH をチェック |
243
231
  | `throughline doctor --trim --host claude` | trim boundary と手動手順を診断 |
244
232
  | `throughline handoff-preview --session <id>` | Codex 向け `throughline_handoff` JSON projection を表示 |
245
233
  | `throughline codex-sidecar-diagnostics` | この project の `codex-sidecar` diagnostics status を確認 |
246
234
  | `throughline codex-sidecar-dry-run` | App Server を呼ばずに read-only sidecar request を正規化表示 |
247
- | `throughline trim --dry-run` | `/tl-trim` 用の dry-run preview。自動 rollback はしない |
235
+ | `throughline trim --dry-run --host codex` | Codex same-thread trim dry-run preview |
236
+ | `throughline trim --execute --host codex` | Codex 同 thread の guarded rollback + DB memory inject |
248
237
  | `throughline doctor --session <id-prefix>` | 特定セッションの state/transcript ズレを診断 |
249
238
  | `throughline status` | DB 統計表示 (sessions / skeletons / bodies / details) |
250
239
  | `throughline --version` | インストール済みバージョンを表示 |
@@ -253,13 +242,12 @@ throughline monitor --session <id-prefix>
253
242
 
254
243
  | コマンド | 役割 |
255
244
  | --- | --- |
256
- | `/tl` | 引き継ぎバトンを書き込み + Claude in-flight メモを書かせる |
257
- | `/tl-trim` | 現 Claude が current-work memo を書き、trim dry-run を実行 |
245
+ | `/tl` | 引き継ぎバトンを書き込む (auto path OFF にしているユーザー / `/clear` 経由しない引継ぎの逃げ道) |
258
246
  | `/sc-detail <時刻>` | 過去ターンの L2 本文と L3 ツール I/O を取得 |
259
247
 
260
- > `/tl` 発火時、Claude Bash 経由で `throughline save-inflight` を呼びます。
261
- > 初回は許可確認が出るので、`Bash(throughline save-inflight:*)` allowlist
262
- > 追加すると以後の確認はスキップできます。
248
+ > v0.4.0 から auto-handoff がデフォルト ON です。`/clear` だけで新セッションが
249
+ > 「途中から」再開されます。`THROUGHLINE_DISABLE_AUTO_HANDOFF=1` OFF にできます。
250
+ > `/tl` は OFF 設定下、または `/clear` 経由しない引継ぎ用の明示マーカー。
263
251
 
264
252
  ---
265
253
 
package/README.md CHANGED
@@ -22,10 +22,10 @@ throughline install # registers Claude hooks, Codex Stop hook, and Codex ski
22
22
  ```
23
23
 
24
24
  That's it. Open any Claude Code session and your turns flow into
25
- `~/.throughline/throughline.db` automatically. After 50 turns of work, type
26
- `/clear` (or just open a new chat), then `/tl` first if you want the next
27
- session to inherit the memory the new session resumes mid-thought instead
28
- of starting from zero.
25
+ `~/.throughline/throughline.db` automatically. After 50 turns of work, just
26
+ type `/clear` the new session resumes mid-thought instead of starting from
27
+ zero. (For non-`/clear` boundaries such as a brand-new chat or a VSCode
28
+ restart, type `/tl` first to mark the predecessor.)
29
29
 
30
30
  Global install also registers a Codex Stop hook in `~/.codex/hooks.json` and
31
31
  enables `[features].codex_hooks = true` in `~/.codex/config.toml`. The Codex
@@ -42,8 +42,8 @@ status, resume, summarize, or trim without typing the full guarded command.
42
42
  |---|---|---|---|
43
43
  | **Compression axis** | content **type** (text vs tool I/O) | **recency** (old → summarized) | none |
44
44
  | **Coding-assistant fit** | high — tool I/O is the heavy 80% | medium — also compresses what you want to keep | — |
45
- | **`/clear` survival** | ✅ via SQLite + `/tl` baton | depends on host | ❌ |
46
- | **Auto-inheritance risk** | zero (explicit `/tl`) | high | — |
45
+ | **`/clear` survival** | ✅ via SQLite + typed `/clear` / `/tl` baton | depends on host | ❌ |
46
+ | **Auto-inheritance risk** | low (typed `/clear` or `/tl` names the predecessor) | high | — |
47
47
  | **Runtime deps** | **zero** (Node 22.5+ built-in `node:sqlite`) | many | — |
48
48
  | **Multi-session token monitor** | ✅ Claude real `message.usage`; Codex rollout `token_count` when available | — | — |
49
49
 
@@ -141,66 +141,67 @@ of tool inputs, tool outputs, and hook output captured at L3 for that turn.
141
141
 
142
142
  ---
143
143
 
144
- ## Explicit handoff via `/tl` (with in-flight memo)
145
-
146
- Inheritance is **opt-in**, not automatic. When you want the next session to
147
- pick up where this one left off, type `/tl` in the current session before you
148
- `/clear` or open a new chat. Without `/tl`, new sessions start fresh — no
149
- memory is carried over.
150
-
151
- The `/tl` slash command does two things:
152
-
153
- 1. **Writes a handoff baton** (the current `session_id`) into the
154
- `handoff_batons` table via the `UserPromptSubmit` hook.
155
- 2. **Asks the current Claude to write an in-flight memo.** `/tl` instructs
156
- Claude to summarize *what it was about to do next, its current hypothesis,
157
- open questions, and in-progress TODOs*, then pipe that Markdown into
158
- `throughline save-inflight`, which attaches it to the baton's `memo_text`
159
- column. This captures the "currently thinking" state that plain transcript
160
- replay cannot preserve.
161
-
162
- On the next `SessionStart`, the hook reads the baton, and if it is less than
163
- **1 hour old**, merges that session's memory into the new session using a
164
- deterministic `UPDATE session_id = ?` inside a `BEGIN IMMEDIATE` transaction.
165
- The baton is consumed (deleted) atomically with the merge, so it cannot fire
166
- twice. The injected resume context is reframed as **"resuming an interrupted
167
- task"** rather than *"reading past logs"*, and the in-flight memo plus the
168
- final turn's extended thinking appear at the top so the new Claude picks up
169
- mid-thought.
144
+ ## Inheritance: typed `/clear` and `/tl` write a baton, source-`clear` is the fallback
145
+
146
+ Throughline 0.4.1+ supports two inheritance paths. The **baton path is the
147
+ primary route**; the source-`clear` auto path is the fallback for cases where
148
+ the user's `/clear` does not reach the `UserPromptSubmit` hook (for example
149
+ the VSCode extension's menu-driven `/clear`).
150
+
151
+ ### baton path (primary): typed `/clear` or `/tl` deterministic inheritance
152
+
153
+ When the user types `/clear` or `/tl` in the prompt, the `UserPromptSubmit`
154
+ hook writes a handoff baton with **that session's `session_id`** into the
155
+ `handoff_batons` table. The next `SessionStart` (within the 1-hour TTL)
156
+ consumes the baton and merges that exact predecessor's memory into the new
157
+ session, regardless of the `source` value.
158
+
159
+ This path is deterministic: it names the predecessor by id rather than
160
+ guessing, so multi-window scenarios where "most recently updated session"
161
+ does not equal "the session you just `/clear`-ed" still inherit correctly.
170
162
 
171
163
  ```
172
- Session A (type /tl) -----------> baton written
173
- |
174
- /clear |
175
- | ▼
176
- Session B ---- reads baton, merges A into B, deletes baton ---->
177
- |
178
- (type /tl again to hand off further)
164
+ typed /clear: Session A /clear → Session B (consumes A's baton, merges A)
165
+ typed /tl: Session A → /tl → (new chat / restart) → Session B (consumes baton, merges A)
179
166
  ```
180
167
 
181
- Why explicit baton instead of auto-inherit:
168
+ ### auto path (fallback): `source='clear'` → heuristic inheritance
169
+
170
+ Since Claude Code 2.1.128, the SessionStart hook receives `source='clear'`
171
+ reliably after `/clear`. When no baton is present (for example because the
172
+ `/clear` was triggered by the VSCode extension's menu and never reached
173
+ `UserPromptSubmit`), Throughline falls back to `findLatestClaudePredecessor`
174
+ to pick the most recent unmerged session for the same project and merges it.
182
175
 
183
- - **Zero false positives.** A parallel window, a VSCode restart, or a genuine
184
- new task in the same repo won't accidentally inherit the previous session's
185
- memory. Only an explicit `/tl` triggers inheritance.
186
- - **VSCode extension compatibility.** The `SessionStart` hook's `source` field
187
- is rewritten to `"startup"` by the Claude Code VSCode extension even after
188
- `/clear` (see [issue #49937](https://github.com/anthropics/claude-code/issues/49937)),
189
- so source-based detection is unreliable. A user-driven baton sidesteps this.
190
- - **Deterministic.** No time-window heuristic, no PID guessing, no ancestor
191
- walking. The user declares intent; the hook carries it out.
176
+ Set `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` in your environment to opt out of
177
+ this fallback. **The env var only affects the fallback**; typed `/clear` and
178
+ `/tl` still write a baton and inherit because the user explicitly signalled
179
+ "continue this work".
192
180
 
193
- Each merged row keeps its `origin_session_id`, so repeated `/tl` handoffs
181
+ ### What gets injected
182
+
183
+ Both paths inject the **same** curated memory:
184
+
185
+ - L1 summaries (older turns, one-line)
186
+ - L2 verbatim (most recent 20 turns, full text)
187
+ - L3 references (`throughline detail <time>` retrieval commands; bodies stay in SQLite)
188
+
189
+ The injection is reframed as **"resuming an interrupted task"** rather than
190
+ "reading past logs". The L2 verbatim already contains the last assistant
191
+ turn — what Claude was about to do next — so no separate memo or extended
192
+ thinking section is injected.
193
+
194
+ Each merged row keeps its `origin_session_id`, so repeated handoffs
194
195
  accumulate memory through chains:
195
196
 
196
197
  ```
197
- S1 (4 turns) --/tl,/clear--> S2 (merges S1, adds 3 turns) --/tl,/clear--> S3 (merges S2, adds 5 turns)
198
- origin=S1×4 origin=S1×4, S2×3, S3×5
198
+ S1 (4 turns) --/clear--> S2 (auto-merges S1, adds 3 turns) --/clear--> S3 (auto-merges S2, adds 5 turns)
199
+ origin=S1×4 origin=S1×4, S2×3, S3×5
199
200
  ```
200
201
 
201
202
  ---
202
203
 
203
- ## Codex sidecar and `/tl-trim` preview
204
+ ## Codex sidecar and Codex trim
204
205
 
205
206
  Throughline is still **Claude Code first**. Codex support is an adapter layer:
206
207
  it can project the same `HandoffRecord` into a `throughline_handoff` JSON block,
@@ -241,11 +242,7 @@ summarization. When `codex-sidecar` is configured for `summarize-l1`,
241
242
  Throughline can use it for that step; otherwise it keeps the existing Claude
242
243
  Haiku path. This is an explicit compatibility mode, not silent auto-detection.
243
244
 
244
- `/tl-trim` starts from dry-run. It previews how many captured turns would be
245
- trimmed, what recent turns would remain, and what curated memory would need to
246
- be injected back.
247
-
248
- **Codex rollback / inject is enabled again.** The 2026-05-06 incident initially
245
+ **Codex rollback / inject is enabled.** The 2026-05-06 incident initially
249
246
  looked like a rolled-back user prompt could reappear after VS Code restart /
250
247
  reconnect, but controlled model-visible rollback smokes did not reproduce that
251
248
  path. `throughline trim --execute --host codex` now sends the guarded
@@ -311,12 +308,9 @@ rollout text, not an exact host tokenizer measurement. If rollback candidate
311
308
  turns are `0`, there is no current trim saving under the active keep-recent
312
309
  setting.
313
310
 
314
- Claude primary remains manual-only for conversation rewind. Throughline can
315
- prepare the current-work memory preview, but it does not drive Claude Code's
316
- interactive rewind UI or claim an automatic Claude rewind path. After a manual
317
- conversation-only rewind, give Claude the preview from `/tl-trim` / `trim
318
- --dry-run`; the preview uses the same active-work framing as Codex so restored
319
- L1/L2 reads as the current task rather than as a passive archive.
311
+ Claude-side rewind UI itself is not driven by Throughline. The auto-handoff
312
+ flow is `/clear` new SessionStart automatic injection of curated memory.
313
+ Throughline does not invoke `/rewind` or any Claude Code internal command.
320
314
 
321
315
  Codex-primary setup has an installed Stop hook after global
322
316
  `throughline install`. In real sessions, verify capture rather than assuming it:
@@ -380,8 +374,8 @@ references while pointing back to the full `codex-resume` context. `--format
380
374
  item-json` returns a Codex developer-message item for hosts that accept
381
375
  structured item injection; it is a rendering surface only and does not mutate
382
376
  the Codex thread by itself. `--memo-stdin` prepends an explicit Codex-primary
383
- in-flight memo to that rendered context; this is the first Codex-side equivalent
384
- of `/tl`'s "what was I about to do next" signal, without touching Claude batons.
377
+ current-work memo to that rendered context; this is a Codex-side opt-in for
378
+ "what was I about to do next" signal, independent from the Claude `/tl` baton.
385
379
  `throughline codex-visibility-smoke` is the experimental mutation check for
386
380
  that rendered memory: it injects the active-work developer message and starts a
387
381
  marker-check model turn through the Codex app-server, so it requires the
@@ -650,7 +644,6 @@ entry to the `tasks` array yourself:
650
644
  | `throughline monitor [--all] [--session <id>]` | Run the multi-session token monitor |
651
645
  | `throughline monitor --diag` | Dump TTY/columns/env diagnostics (for debugging monitor render bugs) |
652
646
  | `throughline detail <time>` | Retrieve L2 body text and L3 tool I/O for a turn (see below) |
653
- | `throughline save-inflight` | Called by `/tl` to attach an in-flight memo (stdin) to the current baton |
654
647
  | `throughline doctor` | Check Node version, hook registration, DB writability, PATH |
655
648
  | `throughline doctor --session <id-prefix>` | Diagnose a specific session — detect state/transcript drift, idle vs. stuck |
656
649
  | `throughline doctor --trim --host claude\|codex` | Diagnose trim host boundaries, manual procedure, and Codex host primitive blockage |
@@ -672,7 +665,7 @@ entry to the `tasks` array yourself:
672
665
  | `throughline codex-threads` | List read-only Codex thread id candidates for the current project |
673
666
  | `throughline codex-sidecar-diagnostics` | Check `codex-sidecar` diagnostics status for this project |
674
667
  | `throughline codex-sidecar-dry-run` | Print a normalized read-only sidecar request without running the app server |
675
- | `throughline trim --dry-run` | Preview `/tl-trim` context trim memory and host boundary; does not rollback automatically |
668
+ | `throughline trim --dry-run --host codex` | Preview Codex same-thread context trim memory and host boundary; does not rollback automatically |
676
669
  | `throughline trim --preflight --host codex` | Read/resume the explicit Codex thread and verify turn-count guards without rollback/inject |
677
670
  | `throughline trim --execute --host codex` | Explicit Codex rollback-inject path; requires Codex thread identity, injectable DB memory, and rollout/app-server turn-count agreement |
678
671
  | `throughline status` | Print DB statistics (sessions, skeletons, bodies, details) |
@@ -682,18 +675,20 @@ Slash commands (invoked by the user in Claude Code):
682
675
 
683
676
  | Command | What it does |
684
677
  | ------------- | ----------------------------------------------------------------- |
685
- | `/tl` | Write a handoff baton + ask Claude to save an in-flight memo for the next session |
686
- | `/tl-trim` | Ask Claude to write a current-work memo and run trim dry-run |
678
+ | `/tl` | Write a handoff baton (explicit inheritance signal across non-`/clear` boundaries new chat / VSCode restart) |
679
+ | `/clear` | Built-in Claude Code reset. Throughline's `UserPromptSubmit` hook also writes a baton so the next session inherits the cleared session's memory |
687
680
  | `/sc-detail <time>` | Retrieve L2 body text and L3 tool I/O for a past turn |
688
681
 
689
- > When `/tl` triggers, Claude will call `throughline save-inflight` via its
690
- > Bash tool. Claude Code will prompt for permission the first time; add
691
- > `Bash(throughline save-inflight:*)` to your allowlist to skip the prompt on
692
- > subsequent `/tl` invocations.
682
+ > Since v0.4.1, both `/clear` and `/tl` typed in the prompt write a baton
683
+ > identifying the current session, so the next `SessionStart` deterministically
684
+ > inherits that exact predecessor. The `source='clear'` auto path remains as a
685
+ > fallback for `/clear` triggered outside `UserPromptSubmit` (for example via
686
+ > the VSCode extension menu); `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` only opts
687
+ > out of that fallback.
693
688
 
694
689
  Hook subcommands (invoked by Claude Code, not by humans):
695
690
  `session-start` (SessionStart), `process-turn` (Stop),
696
- `prompt-submit` (UserPromptSubmit — detects `/tl` and writes baton).
691
+ `prompt-submit` (UserPromptSubmit — detects `/tl` and `/clear` and writes a baton).
697
692
 
698
693
  ### `throughline detail` — for AI, not humans
699
694
 
@@ -743,7 +738,7 @@ Schema v7:
743
738
  - `skeletons` — L1 one-liners, keyed by `(session_id, origin_session_id, turn, role)`
744
739
  - `bodies` — L2 verbatim text (user + assistant), same key shape
745
740
  - `details` — L3 records with `kind` column (`tool_input` / `tool_output` / `system` / `image` / `thinking`) and `source_id` for idempotent re-processing
746
- - `handoff_batons` — one row per `project_path`, with `session_id`, `created_at`, and `memo_text` (the in-flight memo written by `save-inflight` after `/tl`). Consumed and deleted by the next `SessionStart` if within the 1-hour TTL.
741
+ - `handoff_batons` — one row per `project_path`, with `session_id` and `created_at`. Written by the `UserPromptSubmit` hook when the user types `/tl` or `/clear`. Consumed and deleted by the next `SessionStart` if within the 1-hour TTL. (v8 dropped the `memo_text` column when memo was retired in v0.4.0.)
747
742
  - `injection_log` — audit trail of injection events
748
743
 
749
744
  All memory tables carry an `origin_session_id` so rebonded rows keep their
@@ -895,9 +890,15 @@ and `~/.throughline/state/*.json`. A fresh database with schema v7 is created on
895
890
  the next hook fire.
896
891
 
897
892
  **New session didn't inherit memory from the previous one**
898
- This is the designed behavior inheritance requires an explicit `/tl` in the
899
- previous session. If you forgot to type it before `/clear`, the memory is still
900
- in SQLite but won't auto-inject. You can still retrieve specific turns with
893
+ Since v0.4.1, both typed `/clear` and `/tl` write a baton, and the auto path
894
+ falls back on `source='clear'` for menu-driven `/clear`. If inheritance still
895
+ did not happen, the most likely cause is one of: (a) the previous session was
896
+ never recorded (no Stop hook fired — check `throughline status`), (b) the
897
+ 1-hour baton TTL expired before the new session opened, (c) the new session's
898
+ `project_path` (cwd) differs from the previous one, so they live in different
899
+ session chains, or (d) you set `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` and the
900
+ `/clear` came from the VSCode menu which never reaches `UserPromptSubmit`.
901
+ Memory is still in SQLite — you can retrieve specific turns with
901
902
  `/sc-detail <time>`.
902
903
 
903
904
  ---
@@ -918,8 +919,11 @@ Run the monitor directly without a global install:
918
919
  node src/token-monitor.mjs
919
920
  ```
920
921
 
921
- The `.vscode/tasks.json` in this repo auto-launches the monitor when you open
922
- the folder in VS Code.
922
+ When any Throughline hook fires for the first time in a folder, it
923
+ auto-generates `.vscode/tasks.json` with an absolute path to the monitor
924
+ executable for the current machine. The file is **gitignored** (since v0.4.1)
925
+ because the absolute path is per-machine. Reload the VS Code window after
926
+ the first generation to pick up the auto-start task.
923
927
 
924
928
  ---
925
929
 
@@ -27,7 +27,7 @@
27
27
  * throughline codex-threads # List read-only Codex thread id candidates
28
28
  * throughline codex-sidecar-diagnostics # Check codex-sidecar availability
29
29
  * throughline codex-sidecar-dry-run # Print normalized sidecar request
30
- * throughline trim --dry-run # Preview same-session context trim plan
30
+ * throughline trim --execute --host codex # Codex same-thread guarded trim
31
31
  * throughline doctor # 環境チェック
32
32
  * throughline status # DB 統計表示
33
33
  * throughline --version # バージョン表示
@@ -60,9 +60,6 @@ switch (cmd) {
60
60
  case 'detail':
61
61
  (await import('../src/sc-detail.mjs')).run(rest);
62
62
  break;
63
- case 'save-inflight':
64
- await (await import('../src/cli/save-inflight.mjs')).run();
65
- break;
66
63
  case 'handoff-preview':
67
64
  await (await import('../src/cli/handoff-preview.mjs')).run(rest);
68
65
  break;
@@ -149,7 +146,6 @@ Usage:
149
146
  throughline uninstall Remove hooks
150
147
  throughline monitor Multi-session token monitor (use --all, --session <id>)
151
148
  throughline detail <time> Retrieve L2+L3 detail for a turn (e.g. 14:23:05 or 14:23-14:30)
152
- throughline save-inflight Save in-flight memo (stdin) to the current /tl baton
153
149
  throughline handoff-preview Print Codex-facing throughline_handoff JSON
154
150
  throughline codex-capture Capture active Codex rollout turns into DB
155
151
  (requires --codex-thread-id or env thread id)
@@ -226,13 +222,15 @@ Usage:
226
222
  Check codex-sidecar diagnostics status
227
223
  throughline codex-sidecar-dry-run
228
224
  Print normalized read-only sidecar request
229
- throughline trim --dry-run Preview same-session context trim plan
230
- (Codex: accepts --codex-thread-id <id> or
225
+ throughline trim --dry-run --host codex
226
+ Preview Codex same-thread context trim plan
227
+ (accepts --codex-thread-id <id> or
231
228
  THROUGHLINE_CODEX_THREAD_ID / CODEX_THREAD_ID)
232
229
  (text preview accepts --preview-max-chars <n>)
233
- throughline trim --preflight
234
- Codex-only app-server read/resume guard; does not rollback
235
- throughline trim --execute Codex rollback/inject guard; requires a Codex
230
+ throughline trim --preflight --host codex
231
+ Codex app-server read/resume guard; does not rollback
232
+ throughline trim --execute --host codex
233
+ Codex rollback/inject guard; requires a Codex
236
234
  thread id, injectable DB memory, and matching
237
235
  rollout/app-server turns
238
236
  throughline doctor Check environment
@@ -244,7 +242,7 @@ Usage:
244
242
  Hook subcommands (called by Claude Code / Codex):
245
243
  throughline session-start SessionStart hook
246
244
  throughline process-turn Stop hook
247
- throughline prompt-submit UserPromptSubmit hook (/tl baton writer)
245
+ throughline prompt-submit UserPromptSubmit hook (/tl & /clear baton writer)
248
246
  throughline codex-hook stop Codex Stop hook
249
247
  `);
250
248
  }