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.
- package/.claude/commands/tl.md +6 -21
- package/CHANGELOG.md +88 -0
- package/README.ja.md +46 -58
- package/README.md +85 -81
- package/bin/throughline.mjs +9 -11
- package/docs/INHERITANCE_ON_CLEAR_ONLY.md +22 -0
- package/docs/PUBLIC_RELEASE_PLAN.md +4 -1
- package/docs/THROUGHLINE_CLEAR_AUTO_HANDOFF_PLAN.md +304 -0
- package/package.json +1 -1
- package/src/baton.mjs +17 -45
- package/src/baton.test.mjs +4 -41
- package/src/cli/install.mjs +2 -2
- package/src/cli/install.test.mjs +1 -3
- package/src/db-schema.test.mjs +2 -3
- package/src/db.mjs +14 -1
- package/src/hook-entrypoints.test.mjs +61 -18
- package/src/prompt-submit.mjs +24 -2
- package/src/prompt-submit.test.mjs +66 -0
- package/src/resume-context.mjs +31 -48
- package/src/resume-context.test.mjs +18 -13
- package/src/session-start.mjs +77 -21
- package/.claude/commands/tl-trim.md +0 -42
- package/src/cli/save-inflight.mjs +0 -81
package/.claude/commands/tl.md
CHANGED
|
@@ -4,27 +4,12 @@ description: 次の新規セッションに現セッションの記憶を引き
|
|
|
4
4
|
|
|
5
5
|
Throughline の UserPromptSubmit hook が `/tl` を検出し、バトン(現セッション ID)を保存しました。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
これだけで完了です。**追加の操作は不要**。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **未解決の疑問**: 判断保留中の論点
|
|
13
|
-
- **進行中 TODO**: 完了済みを除いた現行 TODO(TodoWrite の最新状態や Plan の内容を踏まえて、意味のあるものだけ)
|
|
9
|
+
このあと:
|
|
10
|
+
- 1 時間以内に新セッションを開く(新 chat / VSCode 再起動など)と、Throughline がバトンを消費して前セッションの記憶 (L1 + L2 + L3 references) を新セッションに自動注入します
|
|
11
|
+
- バトンは 1 時間で失効します
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
通常は `/clear` だけで自動引継ぎが発火するため、`/tl` は **`THROUGHLINE_DISABLE_AUTO_HANDOFF=1` で自動引継ぎを OFF にしているユーザー** または **`/clear` を経由せずに新セッションを開くケース** の明示意思マーカーとして使います。
|
|
16
14
|
|
|
17
|
-
|
|
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
|
-
##
|
|
129
|
+
## 引き継ぎ: `/clear` で自動、env で OFF、`/tl` で明示
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
渡したいときは、現セッションで `/clear` または新規チャットを開く **前に** `/tl` を打ちます。
|
|
133
|
-
`/tl` 無しの場合、新セッションはまっさらな状態で始まり、過去メモリは引き継がれません。
|
|
131
|
+
Throughline 0.4.0 から引き継ぎは 2 経路:
|
|
134
132
|
|
|
135
|
-
`/
|
|
133
|
+
### auto path (デフォルト): `/clear` で自動引き継ぎ
|
|
136
134
|
|
|
137
|
-
1.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
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
|
-
-
|
|
164
|
-
|
|
165
|
-
-
|
|
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
|
-
|
|
166
|
+
注入は **「中断されたタスクの再開」** として再フレーミングされます。L2 verbatim に
|
|
167
|
+
最終 assistant turn (= 次に何をしようとしていたか) が含まれるため、別途 memo /
|
|
168
|
+
extended thinking セクションは注入されません。
|
|
169
|
+
|
|
170
|
+
各マージ行は `origin_session_id` を保持するので、繰り返し引き継ぐと
|
|
173
171
|
記憶がチェーン状に蓄積します:
|
|
174
172
|
|
|
175
173
|
```
|
|
176
|
-
S1 (4 ターン) --/
|
|
177
|
-
|
|
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 と
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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 command は v0.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` |
|
|
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` |
|
|
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
|
-
>
|
|
261
|
-
>
|
|
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,
|
|
26
|
-
`/clear`
|
|
27
|
-
|
|
28
|
-
|
|
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** |
|
|
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
|
-
##
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`/clear`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
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) --/
|
|
198
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
384
|
-
|
|
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`
|
|
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
|
|
686
|
-
| `/
|
|
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
|
-
>
|
|
690
|
-
>
|
|
691
|
-
>
|
|
692
|
-
>
|
|
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
|
|
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
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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
|
-
|
|
922
|
-
|
|
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
|
|
package/bin/throughline.mjs
CHANGED
|
@@ -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 --
|
|
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
|
|
230
|
-
|
|
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
|
|
235
|
-
throughline trim --execute
|
|
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
|
}
|