npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

throughline

v0.14.2

Published

Persistent memory hooks for Claude Code, Codex, Grok, and Cursor (/clear-safe context compression)

Readme

Throughline

npm version license node CI

English · 日本語

Cut ~90% of Claude Code's context usage while keeping nearly all the memory. Throughline separates conversation by type, not time — humans-readable text stays, machine-generated tool output retires to SQLite. Same decisions, same context, 90% lighter.

Built and maintained by Quo at kitepon.dev.

Codex Desktopの自動継続

throughline auto-handoff enable --project /absolute/project/path
throughline auto-handoff status --json
throughline auto-handoff disable

既定では無効です。enableは必要なPreCompact(auto)フックを登録し、そのフックの承認と有効状態を公式APIで確認します。--projectを省略すると全projectを対象にします。macOSのCodex Desktopで実機確認済みです。VS Code・CLI・他OSの自動継続は未検証です。

自動圧縮の開始前に旧ターンを停止し、同じprojectの新しいタスクへ記憶を注入して表示します。元のモデル・推論強度・権限・モードなどが表示後も一致することを確認してから、継続指示を一度だけ送ります。後継でその入力と作業の進捗を観測して完了とします。手動/compactは発火対象に含めません。

記憶は引き継ぎ全体の直近20ターンをL2全文、それより古いターンをL1で渡します。元のユーザー依頼と中断地点を保持し、tool結果とThinkingは注入しません。本文内のauto-handoff detailコマンドで、凍結したL2/L3を引き継ぎID・origin・turnから取得できます。A→B→Cの連続引き継ぎでも祖先の詳細を取得できます。

設定不一致、未処理入力、実行中の子agentや既知のnativeコマンド、追跡されていない旧handoff記憶では固定理由を残して停止します。失敗時はローカルの説明ページを開きます。新タスクだけで容量が尽きる場合も、新タスクを増やし続けません。結果不明の指示は自動で再送しません。

throughline auto-handoff status --operation <handoff-id> --json
throughline auto-handoff resume --operation <handoff-id> --json

原因を解消した後のresumeは同じ引き継ぎと既知の後継を再利用します。配送後の結果不明は実際の入力・開始を観測した場合だけ回復し、作成結果が不明な後継は再作成しません。従来の手動$throughlineとcurrent-thread実験の設定は独立しています。

実測と検証範囲を参照してください。

Claude Codeの自動継続

throughline auto-handoff enable --host claude --project /absolute/project/path
throughline auto-handoff status --host claude --json
throughline auto-handoff disable --host claude

既定では無効です。enableは必要なPreCompactとPreToolUseのフックを登録し、disableが外します。--projectを省略すると全projectを対象にします。Codexの設定とは別で、互いに影響しません。

自動圧縮を置き換えます。圧縮が走る前に旧い会話を止め、記憶を持った新しい会話で作業を続けます(ADR 0033)。

  1. 自動圧縮の直前に、圧縮を止めます。/tlと同じ印を残します。
  2. 旧い会話の次の道具を、実行させずに止めます。旧い会話は止めるだけで、空にしません。
  3. 同じprojectに、新しいClaudeの会話を裏で立てます(claude --bg)。モデル・推論強度・権限は旧い会話から引き継ぎます。
  4. 新しい会話へ継続の指示を1通送ります。届いた時に、止めた時点の依頼、そのターンでここまでにしたこと(発言と道具の呼び出し)、実行されなかった道具、直近の会話の原文を注入します(上限9,500字)。止めたターンの道具の入出力は、後継がthroughline detailで取り出せます。

続きは裏の会話で動きます。claude agentsの一覧とclaude attach <id>で見られます。Claude Desktopの画面には出ず、後継のターンが終わって入力待ちになった後にDesktopで開けます。手動/compact、subagentの中の圧縮、claude -pなどscriptから起動した会話は対象に含めません。

throughline auto-handoff status --host claude --operation <handoff-id> --json

後継の立ち上げや配送に失敗した時は、固定の理由を記録して止まります。結果が不明な指示は再送しません。圧縮を止めた後にモデルが道具を呼ばずにターンを終えた時は、後継を立てません。印は残るので、1時間以内に開いた新しい会話が記憶を引き継ぎます。

有効にした端末では、Claudeの道具の呼び出しのたびにPreToolUseフックが1回走ります。Linux・macOS・WindowsのClaude Code 2.1.289(macOSはClaude Desktop同梱の2.1.286も)で、端末から始めた会話を実機確認済みです。Claude Desktopの画面から始めた会話は未検証です。実測と検証範囲を参照してください。

Ownership boundary

This repository owns installation, configuration, state, schema and migrations, diagnostics, recovery, updates, and release decisions. Throughline works on its own through the documented CLI and does not require a factory controller. dotagents may wire Throughline into the kitepon.dev development factory, but it integrates the product rather than owning its state or controlling its lifecycle. MarkItDown is a separately managed third-party CLI.

In 30 seconds

npm install -g throughline
throughline install     # registers hooks/skills and provisions the VS Code monitor task

That's it. Open any Claude Code session and your turns flow into ~/.throughline/throughline.db automatically. In VS Code, /clear resumes through the SessionStart source='clear' auto path. Claude Desktop does not emit that source, so type /tl before /clear there. Use /tl before any other boundary, such as a brand-new chat or a VS Code restart, when you want to name the predecessor exactly.

Grok Desktop is also a first-class host. throughline install writes ~/.grok/hooks/throughline.json. On Grok, /tl does not inject into the current window — it starts a new Terminal seat. See below.

Cursor is also a first-class host. throughline install upserts sessionStart / beforeSubmitPrompt / stop into ~/.cursor/hooks.json and leaves factory hooks in place. Capture reads Cursor agent-transcripts jsonl. Handoff injection uses sessionStart additional_context. /tl does not auto-launch a successor Cursor chat — the next new conversation drinks the baton. See ADR 0022.

Global install also registers Codex UserPromptSubmit, PostToolUse, and Stop hooks in ~/.codex/hooks.json and enables [features].hooks = true in ~/.codex/config.toml. The deprecated [features].codex_hooks line is removed if present, because Codex warns about it and treats it as an alias of hooks. The Codex hooks invoke the installed bin/throughline.mjs through an absolute Node path, so Codex App Server PATH differences do not hide the command. They are registered synchronously (async: false), matching the Codex hook behavior verified in Caveat. Existing non-Throughline Codex hooks are preserved. The prompt and tool-loop hooks capture rollout memory and write monitor state, but they do not inject $throughline at usage thresholds; token-monitor is display-only and is never an auto-refresh trigger. It also installs a global $throughline Codex skill. Bare $throughline starts a new Codex thread through app-server, injects Throughline DB handoff memory as a developer item, and opens that thread in the selected host; ask explicitly for current-thread rollback diagnostics when you want the guarded trim --execute --host codex surface.

フック登録後の承認とWindowsでの起動条件は、Codexの診断と復旧を参照。

Global install writes ~/.grok/hooks/throughline.json with absolute node + installed bin/throughline.mjs for SessionStart, UserPromptSubmit, and Stop. Do not register a bare throughline command: Grok Desktop's GUI PATH will not see it. On Windows, Grok runs hook commands through PowerShell, so each command starts with the call operator (& "C:\...\node.exe" ...).

Turns are stored as grok:<sessionId>. L2 is recovered from ~/.grok/sessions/<encodeURIComponent(cwd)>/<id>/chat_history.jsonl. Grok does not feed UserPromptSubmit stdout or a rewritten chat_history.jsonl into the live model prompt.

After /tl on a Grok session whose handoff-context is ready, Throughline writes the baton and then runs:

throughline grok-continue --session grok:<id>

cwd is the source session's project_path, not the caller's cwd. The first user text is preamble + the handoff-context body + continue + wait. Missing context or project_path does not spawn. Claude /tl, Codex /tl, and Grok /clear do not launch this CLI. Do not use aiterm, --rules, or --from. macOS Terminal only.

The new seat is a top-level directory under ~/.grok/sessions/<encodeURIComponent(cwd)>/. Desktop Inactive folding is not the success condition. A source with no L2 (including a merged_into chain member with zero bodies) does not spawn — open a fresh chat, exchange one or two turns, then /tl.

How it compares

| | Throughline | /clear (built-in) | /compact (built-in) | MemGPT / SummaryBufferMemory | |---|---|---|---|---| | What it does | retire tool I/O to SQLite, keep text in-context | wipe the whole window | LLM-summarize the whole window | recency-based summarize | | Compression axis | content type (text vs tool I/O) | none — full wipe | recency (uniform) | recency (uniform) | | Memory after the boundary | ✅ recent turns verbatim (whole, budget-packed) + everything older via recall pull + L3 on demand | ❌ zero | △ lossy single summary | △ lossy summary | | Tool I/O handling | retired to L3, retrievable by /sc-detail HH:MM:SS | gone | folded into summary, unreadable | folded into summary | | Coding-assistant fit | high — tool I/O is the heavy 80% | low — you lose the thread | medium — but irreversible | medium | | Auto-inheritance risk | low (/tl names the predecessor; VS Code /clear freezes one transcript-backed candidate) | n/a | n/a | high | | Runtime deps | zero (Node 22.13+ built-in node:sqlite) | n/a | n/a | many | | Multi-session token monitor | ✅ real message.usage / Codex rollout token_count | — | — | — |

Short version: /clear throws everything away, /compact blurs everything together, Throughline keeps the text you wrote verbatim and only retires the tool output — which is where 80% of the bloat lives.

In a typical Claude Code session, 80% of the context window is tool I/O — file reads, Bash output, grep results. This data is consumed the moment Claude acts on it, but it stays in the context forever, pushing you toward the window limit.

xychart-beta
    title "Context after 50 turns of coding work (typical session)"
    x-axis ["Without Throughline", "After /clear + Throughline resume"]
    y-axis "Tokens in context" 0 --> 140000
    bar [125000, 13000]
Without Throughline (50 turns, no /clear):
  user/assistant text  ~25,000 tok  ████
  tool I/O (80%)      ~100,000 tok  ████████████████
                       ≈ 125,000 tok total

With Throughline (50 turns → /clear → resume):
  resume injection      ~3,000 tok  ▌  (recent L2 turns, whole, ≤ 9,500 chars)
  older memory          0–10,000 tok   (pulled only when needed: recall --l2 / --l1)
  tool I/O                  0 tok      (retired to SQLite, on-demand via detail)
                       ≈ 13,000 tok worst case — 90% lighter

Throughline separates conversation content by type, not time: human-readable conversation stays in-context, machine-generated tool output retires to L3. Unlike MemGPT or LangChain's SummaryBufferMemory which compress by recency (old = summarized), this is purpose-built for coding assistants where tool I/O is heavy but transient.

The retired L3 data isn't lost — Claude can pull it back on demand via throughline detail <time> when a past turn's tool output becomes relevant again.

Throughline also ships a multi-session token monitor that reads real Anthropic API usage from the transcript JSONL (no length / 4 heuristics).


Three-layer memory model

flowchart LR
    T["Live turn<br/>user · assistant · tools · thinking"]
    T --> H["Stop hook"]
    H --> L2[("L2 · bodies<br/>verbatim text")]
    H --> L3[("L3 · details<br/>tool I/O · thinking")]
    H -. "async<br/>summarizer" .-> L1[("L1 · skeletons<br/>one-liners")]

    L2 -- "recent turns, whole<br/>(9,500-char budget)" --> S["Next session's first prompt<br/>injection"]
    L2 -. "rest of the window<br/>throughline recall --l2" .-> S
    L1 -. "everything older<br/>throughline recall --l1" .-> S
    L3 -. "on demand · throughline detail" .-> S

    classDef l1 fill:#3aa0ff,stroke:#1a1f2e,color:#fff
    classDef l2 fill:#7c5cff,stroke:#1a1f2e,color:#fff
    classDef l3 fill:#4a5568,stroke:#1a1f2e,color:#fff
    class L1 l1
    class L2 l2
    class L3 l3

| Layer | Name | Where it lives | Content | Cost per turn | | ----- | ---------- | --------------------- | --------------------------------------------------------------------- | ------------- | | L1 | Skeleton | pulled on demand (recall --l1) | one-line summary of the turn (default backend: Codex CLI gpt-5.6-luna, fallbacks per ADR 0015) | ~10 tok | | L2 | Body | injected while the budget lasts; rest via recall --l2 | user text + assistant reply, verbatim | full natural | | L3 | Detail | SQLite only | tool I/O, system messages, images, extended thinking (on-demand) | heavy, retired |

The layers are complementary and disjoint — nothing is duplicated across them. Extended thinking blocks are stored at L3 (kind='thinking') so the next session can see what the previous Claude was thinking at the moment it was interrupted, not just what it said aloud. Thinking is never injected — it stays retrievable via throughline detail <time>.

At the first user prompt of the next session (two-phase handoff, ADR 0014), Throughline rebuilds the context from SQLite and injects it as plain text (push/pull design, ADR 0016):

  • The most recent turns are injected as full L2 (bodies) text — packed whole-turn, newest-first, as many as fit the ~9,500-char budget
  • L1 (skeletons) one-liners are not injected — a guidance section with ready-to-run throughline recall --l2|--l1 commands is injected instead, so older memory is pulled only when needed
  • L3 stays in SQLite and is retrieved on demand via /sc-detail <time>

L1 summaries are generated lazily: for sessions that stay under 20 turns, no external summarizer is invoked. Summaries target a compression ratio (default 1/5 of the source turn, configurable via THROUGHLINE_L1_RATIO; invalid values are an explicit error, not a silent default). In the Claude-primary path the backend order is: Codex CLI (default gpt-5.6-luna at reasoning effort low, chosen by measured evaluation — see ADR 0015; override via THROUGHLINE_L1_MODEL / THROUGHLINE_L1_EFFORT) → Claude Haiku 4.5 via a subprocess (claude -p), reusing your Claude Max login — no API key required. Each attempted backend records its result. For Codex-primary capture, the L1 backend is the Codex CLI only; failures are explicit and do not fall back to Claude Haiku or raw L2.

All three layers (L1/L2/L3) have working write paths as of schema v5. /sc-detail HH:MM:SS returns user/assistant text (L2) plus a kind-grouped view of tool inputs, tool outputs, and hook output captured at L3 for that turn.


Inheritance: /tl writes a baton; VS Code /clear uses source='clear'

Throughline supports two inheritance paths. A /tl baton names one predecessor exactly. If no eligible baton exists, the VS Code /clear path can use the SessionStart source='clear' signal to freeze one transcript-backed predecessor. The baton is checked first.

flowchart LR
    U["User types<br/>/tl"] -->|UserPromptSubmit| W["writeBaton<br/>(session_id + TTL 1h)"]
    W --> B[("handoff_batons<br/>SQLite")]
    M["VS Code<br/>/clear"] -->|SessionStart source='clear'| X["freeze predecessor<br/>no baton"]
    D["Claude Desktop<br/>/clear"] -->|source='startup'| N["no automatic handoff<br/>use /tl first"]
    NS["Next SessionStart<br/>(registers intent only)"] --> FP["First user prompt<br/>(proof the session is real)"]
    FP --> C{"baton<br/>present?"}
    B -.-> C
    X -.-> C
    C -->|yes| P1["baton path<br/>(primary)<br/>merge that exact predecessor"]
    C -->|no, source='clear'| P2["auto path<br/>(fallback)<br/>predecessor frozen at SessionStart"]
    C -->|no, source!='clear'| P3["fresh session<br/>no merge"]
    P1 --> INJ["inject L2 turns + recall guidance<br/>(budgeted ≤ 9,500 chars)"]
    P2 --> INJ

    classDef primary fill:#7c5cff,stroke:#1a1f2e,color:#fff
    classDef fallback fill:#3aa0ff,stroke:#1a1f2e,color:#fff
    classDef neutral fill:#4a5568,stroke:#1a1f2e,color:#fff
    class P1 primary
    class P2 fallback
    class P3,INJ neutral

baton path: /tl → deterministic inheritance

When the user types /tl, the UserPromptSubmit hook writes a handoff baton with that session's session_id into the handoff_batons table. The next new session consumes the baton at its first user prompt (eligibility: the session must have been born within the 1-hour TTL after the baton was written) and merges that exact predecessor's memory, regardless of the source value.

Why the first prompt and not SessionStart itself: Claude Code can fire multiple SessionStart hooks for the same project within a few hundred milliseconds, and some of them never materialize into a real session (no transcript is ever written). At SessionStart time a real session and such a "ghost" are indistinguishable — even a real session's transcript file appears only ~0.5s after the hook fires. A ghost that consumed the baton first would silently swallow the predecessor's memory while the real session started empty. Deferring consumption to the first user prompt closes this: a ghost never submits a prompt, so it can never take the baton (ADR 0014).

This path is deterministic: it names the predecessor by id rather than guessing, so it is the explicit path for multi-window work and for hosts that do not emit source='clear'.

/tl: Session A → /tl → (/clear, new chat, or restart) → Session B (consumes A's baton)

auto path: VS Code source='clear' → frozen predecessor

The built-in /clear command does not reach UserPromptSubmit on the tested Claude Code clients. VS Code instead sends SessionStart source='clear'. When no baton is present, Throughline resolves the most recent unmerged session for the same project at SessionStart time (freezing that choice, and skipping candidates that have no transcript — i.e. ghosts) and performs the merge + injection at the session's first user prompt.

Set THROUGHLINE_DISABLE_AUTO_HANDOFF=1 in your environment to opt out of this path. The env var does not disable explicit /tl batons.

Claude Desktop neither forwards built-in /clear to UserPromptSubmit nor emits SessionStart source='clear'; use /tl before /clear there. The cross-client measurements and upstream report are recorded in the archived docs/12_desktop_clear_handoff_plan.md.

What gets injected

Both paths inject the same curated memory (push/pull design, ADR 0016):

  • A "現在地 (latest exchange)" anchor (added in v0.4.12) re-surfaces the most recent user directive and the most recent assistant turn directly under the header, each truncated to 600 characters
  • A pull guidance section (always present) with ready-to-run throughline recall commands — session id, an ISO-ms boundary, and turn counts are baked in at injection time
  • L2 verbatim: as many of the most recent turns as fit the ~9,500-char injection budget, packed whole-turn (typically 7–8 turns; more for light conversations). L1 summaries are not injected — the rest of the 20-turn window is retrieved verbatim via throughline recall --l2, and everything older via throughline recall --l1 (summarized turns show their L1 line; unsummarized ones are listed explicitly with a throughline detail pointer)
  • L3 references (throughline detail <time> retrieval commands, attached inline to each L2 row; bodies stay in SQLite)

The injection is reframed as "resuming an interrupted task" rather than "reading past logs". The L2 verbatim already contains the last assistant turn — what Claude was about to do next — so no separate memo or extended thinking section is injected. The current-state anchor exists because, on long L2 windows, attention can fixate on the first L2 entry (the oldest turn in the window) and misread an old plan discussion as the current task; pinning the latest exchange at the top of the injection prevents that drift.

Each merged row keeps its origin_session_id, so repeated handoffs accumulate memory through chains:

VS Code:
S1 (4 turns) --/clear--> S2 (auto-merges S1, adds 3 turns) --/clear--> S3 (auto-merges S2, adds 5 turns)
                         origin=S1×4                                   origin=S1×4, S2×3, S3×5

Codex trim

Codex support projects the same HandoffRecord into a throughline_handoff JSON block. Claude hooks, slash commands, transcript parsing, and /tl baton handoff remain available.

Useful inspection commands:

throughline handoff-preview --session <id>
throughline codex-summarize --session codex:<thread-id> --json
throughline codex-resume --session codex:<thread-id>
throughline codex-resume --session codex:<thread-id> --format handoff
throughline codex-handoff-start --session codex:<thread-id>
throughline codex-handoff-start --session codex:<thread-id> --execute --open-host desktop
throughline codex-handoff-smoke --session codex:<thread-id>
throughline codex-handoff-model-smoke --session codex:<thread-id> --dry-run --json
THROUGHLINE_EXPERIMENTAL_CODEX_HANDOFF_MODEL_SMOKE=1 \
  throughline codex-handoff-model-smoke --session codex:<thread-id> --json
throughline codex-resume --session codex:<thread-id> --format item-json
printf '**Next move**: continue the Codex implementation\n' \
  | throughline codex-resume --session codex:<thread-id> --memo-stdin
printf '**Next move**: continue the Codex implementation\n' \
  | THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1 \
      throughline codex-visibility-smoke --session codex:<thread-id> --memo-stdin \
        --request-timeout-ms 150000 --json
THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1 \
  throughline codex-visibility-smoke --session codex:<thread-id> \
    --resume-after-inject --request-timeout-ms 180000 --json
throughline codex-threads --limit 5

The L2→L1 summarizer uses Codex CLI for Claude-primary capture, then Claude Haiku if Codex CLI fails. Codex-primary capture uses Codex CLI only and reports its failures.

Codex current-thread rollback / inject is explicit-only. The 2026-05-06 incident initially looked like a rolled-back user prompt could reappear after VS Code restart / reconnect, and later live experiments showed token usage can drop briefly and then return in the same thread. For that reason, Codex hooks do not perform automatic current-thread refresh. throughline trim --execute --host codex remains available as an explicit diagnostic current-thread path when injectable DB memory is available. Bare $throughline instead starts a new thread with the handoff prompt, matching the safer Claude-style handoff model.

throughline codex-host-primitive-audit can inspect the installed Codex app-server schema read-only. On the current tested Codex CLI, it finds thread/rollback, thread/inject_items, and new-thread primitives, but no current-thread primitive that either clears/rewrites retained rollback sources or isolates/projects them away from model-visible input. This is now diagnostic evidence only, not an execute blocker. The audit also emits a host-agnostic same-thread repair contract: a passing design needs a current-thread non-resurrection primitive, rollback non-resurrection guarantee, memory reinjection, post-repair read verification, and a restart / reconnect non-resurrection smoke. VS Code evidence can inform that contract, but it is not itself the repair primitive.

Dry-run and preflight also inspect planned rollback risk. If the user text that would be removed is already present in Codex compacted.replacement_history, Throughline reports Planned rollback restore safety: risk as diagnostic context, but it no longer refuses preflight or execute on that basis.

The intended memory contract remains: older turns come back as L1 summaries, the latest 20 turns come back as full L2 conversation bodies, and L3 remains detail references instead of inline tool payloads. Throughline never guesses the active Codex thread: use throughline codex-threads to inspect read-only rollout candidates, then pass the chosen id explicitly. If a wrapper or host exports THROUGHLINE_CODEX_THREAD_ID or CODEX_THREAD_ID, throughline trim --host codex treats that as a current-thread identity signal; the CLI flag still wins when both are present. Throughline does not fall back to "latest rollout" guessing. When the chosen Codex thread has a current-project rollout, throughline trim can use the rollout as the trim source even if the Throughline DB has no captured Codex turn bodies; rollback events in the rollout are applied before the rollback plan is built. When DB memory exists, the injected memory is built from the Throughline DB rather than from the rollout preview; guarded execute refuses instead of injecting a rollout preview when Throughline DB memory is absent. During Codex preflight, Throughline also compares the rollout active-turn count with app-server thread/read / thread/resume counts. The separate read-only codex-restore-smoke also checks paginated thread/turns/list counts across fresh app-server processes. These are live app-server guards only; they are not by themselves a durable restart-safe proof. The guarded execute path is enabled by explicit --execute; it may still report execute-sent-live-only or execute-unverified if durable rollout evidence is not observed. Throughline reports execute-durable-verified when the rollout records a new rollback marker and records the injected active-work memory. Developer memory injection is item-level on current Codex hosts and may not add a host-visible turn during the immediate post-inject read; Throughline therefore uses the thread/inject_items response shape to decide whether a turn-count increase should be expected. doctor --codex also reports this context-refresh readiness explicitly: rollback source, inject memory source, the L1/L2/L3 memory contract, current L1/L2/L3 counts, the heuristic reduction estimate when rollout text is available, and the host primitive audit status as diagnostic context. L3 is reported as references-only; L3 bodies and tool payloads are not injected.

Codex trim dry-run reports a context reduction estimate when rollout text is available: rollback-candidate estimated tokens, injected-memory estimated tokens, and net estimated reduction. This is a chars / 4 heuristic from the rollout text, not an exact host tokenizer measurement. If rollback candidate turns are 0, there is no current trim saving under the active keep-recent setting.

Claude-side rewind UI itself is not driven by Throughline. In VS Code, the auto-handoff flow is /clear → new session → automatic injection of curated memory at the session's first user prompt. Claude Desktop requires /tl before /clear. Throughline does not invoke /rewind or any Claude Code internal command.

Codex-primary setup has an installed Stop hook after global throughline install. In real sessions, verify capture rather than assuming it: doctor --codex compares the current Codex thread with the latest captured DB session, and makes any missing Throughline DB advance visible. A Codex VSCode session that was already open before hook shape changes may not be a clean natural Stop smoke; use a newly started session or codex exec smoke for that check. A newly started VSCode-origin Codex session has been verified with matching current Codex thread and latest DB session in doctor --codex. The following commands are the explicit diagnostic, resume, smoke, and guarded trim surfaces:

throughline doctor --trim --host claude
throughline doctor --trim --host codex
throughline doctor --codex
throughline codex-capture --codex-thread-id <id> --json
throughline codex-summarize --session codex:<id> --json
throughline codex-resume --session codex:<id> --format handoff
throughline codex-handoff-start --session codex:<id>
throughline codex-handoff-start --session codex:<id> --print-prompt
throughline codex-handoff-smoke --session codex:<id> --json
throughline codex-handoff-model-smoke --session codex:<id> --dry-run --json
# optional model smoke; uses codex exec --ephemeral --sandbox read-only:
# THROUGHLINE_EXPERIMENTAL_CODEX_HANDOFF_MODEL_SMOKE=1 throughline codex-handoff-model-smoke --session codex:<id> --json
printf '**Next move**: continue the current Codex task\n' \
  | throughline codex-resume --session codex:<id> --memo-stdin
printf '**Next move**: continue the current implementation\n' \
  | throughline trim --dry-run --host claude --memo-stdin
throughline codex-threads --json --limit 5
throughline trim --dry-run --host codex --codex-thread-id <id>
throughline trim --dry-run --host codex --codex-thread-id <id> --preview-max-chars 4000
throughline trim --preflight --host codex --codex-thread-id <id>
CODEX_THREAD_ID=<id> throughline trim --preflight --host codex
throughline trim --execute --host codex --all
# read-only app-server process restart smoke; not full VS Code restart-safe proof:
# THROUGHLINE_EXPERIMENTAL_CODEX_RESTORE_SMOKE=1 throughline codex-restore-smoke --codex-thread-id <id> --json
# read-only local restore source inventory; not full VS Code restart-safe proof:
# throughline codex-restore-source-audit --codex-thread-id <id> --json
# manual two-phase VS Code reload/reconnect smoke:
# THROUGHLINE_EXPERIMENTAL_CODEX_VSCODE_RESTORE_SMOKE=1 throughline codex-vscode-restore-smoke --prepare --codex-thread-id <id> --json
# after reloading/reconnecting VS Code and sending the printed prompt:
# throughline codex-vscode-restore-smoke --verify --codex-thread-id <id> --marker <marker> --prepared-at <iso> --after-vscode-restart --json
# explicit current-thread trim:
throughline trim --execute --host codex --all --codex-thread-id <id>

For Codex trim, the default memory session is the current Codex thread: codex:<CODEX_THREAD_ID> / codex:<THROUGHLINE_CODEX_THREAD_ID>. Throughline does not fall back to the latest project session for Codex injection, because that can mix Claude-side memory into a Codex rollback. Pass --session only when deliberately injecting a different captured session.

That current-work framing matters: the original /tl design learned that L1/L2 memory alone can read like past logs rather than "the work in progress". The memo is one strong signal, but the broader mechanism is explicit structure: recent L2 is labeled as an active work thread, older hypotheses may be superseded by later entries, and the continuation instruction appears at the top and bottom of the injected memory.

For Codex-primary sessions, throughline codex-capture --codex-thread-id <id> stores active rollout turns under codex:<thread_id>, and throughline codex-summarize --session codex:<thread_id> can write older captured L2 turns to L1 with the Codex CLI backend. throughline codex-resume --session codex:<thread_id> renders that memory as an active-work context. --format handoff renders a shorter prompt for starting a new Codex thread without mutating the old one; it caps recent L2 entries, long body text, and detail references while pointing back to the full codex-resume context. --format item-json returns a Codex developer-message item for hosts that accept structured item injection; it is a rendering surface only and does not mutate the Codex thread by itself. --memo-stdin prepends an explicit Codex-primary current-work memo to that rendered context; this is a Codex-side opt-in for "what was I about to do next" signal, independent from the Claude /tl baton. throughline codex-visibility-smoke is the experimental mutation check for that rendered memory: it injects the active-work developer message and starts a marker-check model turn through the Codex app-server, so it requires the THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1 opt-in. In local real-host smoke testing, the marker appeared in item/agentMessage/delta; use --resume-after-inject to verify injected memory still survives a second thread/resume before turn/start, and use --request-timeout-ms / --timeout-ms when the model turn may take longer than the default wait. throughline codex-restore-smoke is the read-only restart diagnostic for the same boundary: it starts fresh Codex app-server processes and compares thread/read / thread/resume / paginated thread/turns/list turn counts with the rollout active turn count. Its proof scope is app_server_process_restart_only; even a passing result is not VS Code restart-safe proof for rollback / inject. With --inspect-risky-rollout, it can inspect a risky rollout read-only; if retained rollback text appears in app-server responses, the status becomes app-server-restore-text-retained when it appears in blocking candidates such as direct turn text or replacement_history, or app-server-restore-text-quoted when it appears only inside quoted/tool-output fields such as aggregatedOutput. The text-match report includes sample JSON paths, location kinds, risk classes, and blocking-candidates so quoted old output is not confused with resurrected user message fields. throughline codex-restore-source-audit is the local inventory companion: it checks the Codex rollout, session_index.jsonl, state_*.sqlite, and VS Code globalStorage / workspaceStorage candidates, VS Code settings.json, and VS Code logs for the chosen thread id and retained rollback text. SQLite-backed VS Code storage candidates such as .vscdb, .sqlite, .sqlite3, and .db are opened read-only and summarized by table / column / needle matches. It also scans installed OpenAI/Codex VS Code extension bundles for restore-path signals such as thread/read, thread/resume, thread/turns/list, reconnect needs_resume, persisted webview atoms, follow-up queue signals, and explicit rollback non-resurrection projection candidates such as replacement_history filter / tombstone paths. A match here is static evidence only; current tested storage roots can still report VS Code storage matches: 0 for the selected thread and retained rollback text. VS Code log matches are also classified into thread-id hits, retained rollback text hits, patch-apply failures, thread stream broadcasts, and replacement_history signals so incidental log mentions can be separated from restore-path evidence. Its proof scope is local_restore_source_inventory_only; it can narrow the restore-source hypothesis, but it still does not prove VS Code restart safety. These VS Code scans are diagnostics only. The product repair path remains the host-agnostic same-thread contract reported by codex-host-primitive-audit, not a VS Code-only implementation path. throughline codex-vscode-restore-smoke is the manual full-boundary protocol: --prepare injects a hidden active-work developer-memory marker, then VS Code must be reloaded or reconnected and asked a prompt that does not contain the marker. --verify scans the rollout for a marker answer after the prepare timestamp and rejects the proof if the marker leaked through the user prompt. Only a marker-free smoke prompt followed by an assistant answer whose trimmed text exactly equals the marker, plus --after-vscode-restart, is treated as restartSafe: true; prepare remains an explicit experiment gated by THROUGHLINE_EXPERIMENTAL_CODEX_VSCODE_RESTORE_SMOKE=1. A real VS Code reload/reconnect run has passed this marker proof, showing hidden developer memory can remain model-visible after reconnect. That is not the same as proving rollback-targeted user turns cannot resurrect, so rollback-specific smokes remain the stronger diagnostic boundary. throughline codex-vscode-rollback-smoke --verify --after-vscode-restart is the read-only verifier for that next proof: it requires a rollback event, rolled-back user text, a later user turn, and restoreSafety: ok before it will report restartSafe: true. throughline codex-rollback-model-visible-smoke is a stricter controlled experiment for the current thread: --prepare creates a unique user marker and rolls that turn back, while --verify later starts a model turn that contains only the marker prefix, not the full marker. It reports reproduced only if the model returns the hidden full marker. This mutates the thread and is gated by THROUGHLINE_EXPERIMENTAL_CODEX_ROLLBACK_MODEL_VISIBLE_SMOKE=1. Use --marker-file <path> for live runs so the full marker is stored locally instead of being printed into the same conversation being tested. Verify output reports rolledBackMarkerModelVisible separately from restartSafe. In a controlled 2026-05-08 current-thread run, both the immediate fresh app-server verify and the post VS Code reload/reconnect verify returned not-reproduced with no full marker in the prompt or observed assistant output.

A 2026-05-07 incident-shaped live rollback run produced useful risk evidence: thread_rolled_back and injected active-work memory were recorded in the rollout, but rollback-targeted user text remained in compacted.replacement_history, and the verifier later observed rolled-back user text reappearing in rollout/app-server diagnostics (restoreSafety: risk). A later risky restore inspection found those retained matches only inside aggregatedOutput, so this is not yet proof that the text is sent as a fresh user message or model-visible input. Because the controlled reproduction smoke stayed clean across app-server restart and VS Code reload/reconnect, Throughline no longer blocks Codex trim solely on this diagnostic risk.

For Codex, fresh-thread handoff remains an explicit continuation path in trim plans and trim diagnostics, but it is not a replacement for current-thread trim. The guided entrypoint is throughline codex-handoff-start --session codex:<thread-id>; it shows the structural smoke, model-smoke dry-run boundary, handoff render command, optional live model smoke, and can include the prompt with --print-prompt. With --memo-stdin, it also propagates --memo-stdin into the replay commands and reminds you to pipe the same memo when using them separately. Add --execute to create a new Codex app-server thread, inject the handoff memory as a developer item, and open it with --open-host auto|desktop|vscode|cli|none. auto opens the new task in Codex Desktop when invoked there, while preserving the existing VS Code and CLI routes. The result reports both the requested and resolved host. The installed $throughline skill passes the current Codex surface explicitly so a persistent shell or PTY cannot redirect the handoff. WindowsのDesktop引き継ぎは、稼働中のCodex Desktopが使う実行ファイルを選びます。 PATH上の別バージョンによる設定読取りエラーを避け、選んだ実行元を結果へ表示します。 Desktopを起動してから実行してください。実行ファイルが見つからない場合や、異なる実行ファイルの Desktopが複数稼働している場合は理由を出して停止します。明示した--codex-app-server-binは優先します。 The individual commands remain available: validate the fresh-thread handoff with throughline codex-handoff-smoke --session codex:<thread-id>, optionally audit the model-smoke boundary with throughline codex-handoff-model-smoke --session codex:<thread-id> --dry-run --json, render it with throughline codex-resume --session codex:<thread-id> --format handoff, then start a new Codex thread with that context. This does not mutate the current thread. trim --execute --host codex is the current-thread mutation path and still requires explicit execution, injectable Throughline DB memory, and explicit Codex thread identity. Human-readable dry-run output truncates the inline memory preview for scanability; the full text remains in --json as memoryPreview.text, and for Codex the fresh-thread continuation can be guided with codex-handoff-start or rendered directly with the codex-resume command shown in the fresh-thread continuation path.


Multi-session token monitor

Run:

throughline monitor            # all active sessions in the current project
throughline monitor --all      # every project, every session
throughline monitor --session <id-prefix>

Example output:

[Throughline] 1 セッション
▶ Throughline       Claude 2ed5039c just now ██░░░░░░░░  205.1k /   1.0M  claude-opus-4-6
  Throughline       Codex  019e085c just now ██████░░░░  151.9k / 258.4k  gpt-5.5
  • Claude token counts are accurate. Read straight from the latest message.usage field in the session transcript JSONL, which is what Anthropic's API actually reported (input_tokens + cache_creation_input_tokens + cache_read_input_tokens). No length / 4 approximation.
  • Codex token counts use the rollout token_count event when present. The monitor discovers live Codex rollouts directly from ~/.codex/sessions/**/rollout-*.jsonl, so a current Codex session can appear even before the Codex Stop hook writes codex:<thread_id> monitor state. While the monitor is running it reads the live rollout every tick and prefers the latest verified token_count sample. During an open Codex turn, the monitor overlays transient output_tokens on top of input_tokens; when task_complete arrives it drops back to verified input_tokens only. If a Codex rollout has no token-count event, Throughline can show an explicit estimate with estimated: true and the monitor marks it with est; it is not presented as exact usage.
  • Codex auto-refresh is disabled. The Codex UserPromptSubmit and PostToolUse hooks capture rollout memory and write monitor state, but they do not inject $throughline instructions. The Codex Stop hook also captures DB memory, writes monitor state, and stays quiet instead of sending rollback + injection above a threshold.
  • 1M-context detection is automatic. It checks the [1m] suffix in the transcript, falls back to string matching on 1M context, and finally promotes to 1M if observed usage exceeds 200k.
  • Multi-session view. Each Claude Code or Codex session writes its own state file (~/.throughline/state/<session_id>.json), and active Codex rollouts are discovered directly from the Codex session directory. Codex session ids are stored as codex:<thread_id> in JSON state, while the display shows the raw first 8 thread-id characters (for example 019e085c) to avoid the ambiguous codex:01 prefix slice. The monitor scans every second and displays one row per live session, sorted by last activity. The most recent one is highlighted with ▶.
  • Stale hiding. Sessions that haven't been touched in 15 minutes drop out of the default view; files older than 24 hours are deleted entirely. This is the only time threshold in the system and is used solely for display hygiene — no memory decisions are made from it.
  • Line-wrap safe. Each line is truncated to process.stdout.columns - 1 before drawing, preserving ANSI color codes. The redraw cursor math cannot desync on narrow terminals.
  • Resize resilient via OSC 18t. Windows ConPTY + VS Code task terminals freeze process.stdout.columns at the PTY's initial size and never propagate panel resizes into Node, so polling or resize events can't catch them. Throughline queries the terminal itself with the CSI 18 t escape (\x1b[18t) every tick, parses the \x1b[8;rows;cols t reply off stdin in raw mode, and uses the real current width for truncation. On terminals that don't answer the query, the renderer falls back to process.stdout.columns → env.COLUMNS → 80. When the width changes the viewport is cleared in full (\x1b[2J\x1b[3J\x1b[H) before the next frame so the previous, wrongly-sized frame can't stack beneath it.
  • Per-row "last updated" stamp. Each session row carries an 8-cell just now / 24m ago stamp right after the session id, placed before the bar so narrow terminals don't truncate it. It follows the newest state, transcript, or Codex rollout mtime, so active sessions stay visible and the stamp can move before the next Stop hook completes. When you need more detail, throughline doctor --session <id-prefix> compares the state file against the actual transcript JSONL and flags drift, idle time, and /clear-induced transcript path staleness.
  • Live usage first, state snapshot as fallback. When the Stop hook finishes a turn it persists the latest tokens / model / contextWindowSize back into the state file. The monitor now prefers live Claude transcript / Codex rollout reads and uses the snapshot only when the live file cannot provide usage, so the display no longer waits for Stop to update.
  • Host-aware state. Missing host means an older Claude state file. Codex states use host: "codex", keep transcriptPath: null, and store the Codex rollout path separately as rolloutPath so the Claude transcript parser is never pointed at a Codex rollout.
  • Non-blocking Claude Stop hook (v0.3.22+). The Claude Stop hook is registered with "async": true so throughline process-turn runs in the background and does not delay Claude's reply from reaching you. L1 Haiku summarization (claude -p subprocess + inference, seconds to tens of seconds) would otherwise stall the user-facing response of every turn; since L1 is only needed for the next session's injection, there is no reason to block the current turn on it. Existing installs need throughline uninstall && throughline install to promote the flag (the dedup logic skips entries that match by command string).

VS Code auto-start (automatic)

After throughline install, the current VS Code / Cursor / VSCodium project gets .vscode/tasks.json provisioned immediately when VS Code environment variables are present. Any other VS Code project you work in also gets the file on the first session event. The file configures runOn: folderOpen so the monitor appears in a dedicated terminal panel the next time you open that folder.

How it works. ensureMonitorTaskFile is called from throughline install and from all three Claude hooks (SessionStart, UserPromptSubmit, Stop). Whichever one fires first in your environment creates the file; the rest are idempotent no-ops. Once per project it inspects .vscode/tasks.json:

  • No file yet → creates one with a single Throughline Monitor task, and emits a one-time <system-reminder> to stdout so Claude tells you a Developer: Reload Window is needed to activate the folderOpen task once (v0.3.19+).
  • Plain JSON with other tasks → appends the monitor task, preserves your existing entries, version, and indentation (same notice fires once).
  • JSONC (comments or trailing commas) → does not touch the file. Prints a one-time notice to stderr asking you to paste the snippet below.
  • Already contains a Throughline Monitor task → does nothing (idempotent; this is the common path on every subsequent turn; notice is silent).

For Codex-primary projects, hook stdout is not always surfaced in the chat. throughline doctor --codex therefore reports the VS Code monitor task status, its runOn value, and the same Reload Window note in a visible diagnostic.

The generated task uses type: 'shell' with the absolute path to Node and bin/throughline.mjs. VS Code wraps shell tasks in a PTY (xterm.js) so the monitor sees isTTY=true, real columns, and resize events. Windows .cmd shims and missing PATH entries cannot break it because the command is already an absolute Node binary path.

Opt out: set THROUGHLINE_NO_VSCODE=1 in the environment used by Claude Code. Delete .vscode/tasks.json (or just the monitor entry) if you want to stop auto-start for a project that already has one.

Manual snippet for JSONC tasks.json files. If Throughline refused to edit your tasks.json because it contains comments or trailing commas, add this entry to the tasks array yourself:

{
  "label": "Throughline Monitor",
  "type": "shell",
  "command": "throughline monitor",
  "isBackground": true,
  "presentation": {
    "reveal": "always",
    "panel": "dedicated",
    "group": "throughline",
    "close": false,
    "echo": false,
    "focus": false,
    "showReuseMessage": false,
    "clear": true
  },
  "runOptions": { "runOn": "folderOpen" },
  "problemMatcher": []
}

Commands

公開版は冒頭のnpmバッジ、開発中の版は package.json、版ごとの変更は CHANGELOG.md を参照。Throughline supports Claude Code, Codex, Grok, and Cursor as documented host adapters. The versioned, read-only handoff-context boundary opens only an existing database and leaves baton state, session ownership, and memory rows unchanged. Factory diagnostics, Observer, runtime-error, capture, and normal handoff behavior remain available under the same explicit-failure and local-only contracts.

Normal handoffs announce inherited continuity once in the first response and explicitly forbid repeating that line in later responses. A project-bound launcher may pass --disclosure silent for an embedded product that keeps continuity metadata out of its chat. A supplement may also set handoffDisclosure to silent. Legacy Throughline disclosure lines in assistant memory are omitted from the next handoff; user quotations and the actual reply body remain intact.

| Command | What it does | | ---------------------------------------------- | ------------------------------------------------------------ | | throughline install | Register Claude user hooks/slash commands, the global Codex UserPromptSubmit/PostToolUse/Stop hooks, the global $throughline Codex skill, ~/.grok/hooks/throughline.json, and the current VS Code monitor task when applicable | | throughline install --project | Register Claude hooks/slash commands in this repo only | | throughline self-update [--json] | Update the official npm package, verify that public PATH resolves to that new CLI/version, reapply product-owned integrations, migrate an existing database, and verify public diagnostics in one call | | throughline uninstall | Remove Throughline-managed Claude hooks/slash commands, only the Throughline-managed Codex hook, and the $throughline Codex skill |

Versions before v0.10.5 do not contain self-update. Upgrade those versions once with npm install --global throughline@latest, then run throughline self-update. Later updates use throughline self-update alone. | throughline monitor [--all] [--session <id>] | Run the multi-session token monitor | | throughline monitor --diag | Dump TTY/columns/env diagnostics (for debugging monitor render bugs) | | throughline detail <time> | Retrieve L2 body text and L3 tool I/O for a turn (see below) | | throughline recall --l2\|--l1 --session <id> --before <ISO> ... | Pull older memory referenced by the injection's guidance section (read-only; the exact command is baked into each injection) | | throughline caveat-context --session <id> --project <root> --json | Return three completed dialogue turns and available Thinking for Caveat, without tool logs; --host claude\|codex --transcript <path> checks freshness | | throughline room-context --json | Record a room turn from JSON stdin and return the latest three turns through that message as throughline.room_context.v1 | | throughline observer-read --project <absolute-directory> [--wire v2] --json | Read one completed-turn Observer page through the JSON-only public boundary; --wire v2 returns full bodies, the real harness, and how each turn started | | throughline observer-wait --project <absolute-directory> --after-cursor <opaque> [--timeout-seconds 3600] --json | Wait up to 3600 seconds for a completed-turn Observer cursor change | | throughline doctor | Check Node version, hook registration, DB writability, PATH | | throughline doctor --session <id-prefix> | Diagnose a specific session — detect state/transcript drift, idle vs. stuck | | throughline doctor --trim --host claude\|codex | Diagnose trim host boundaries, manual procedure, and Codex host primitive blockage | | throughline doctor --codex | Diagnose Codex primary entry state, captured DB sessions, context-refresh memory contract, new-thread handoff readiness, safe continuation status, and host primitive audit | | throughline factory-diagnostics --json | Versioned read-only native factory readiness JSON for database schema/migration, connector hooks, and representative capture/restore/handoff; does not emit bodies, secrets, absolute paths, or raw state | | throughline migrate --json | Migrate only an existing Throughline database to the current schema and emit a versioned bounded result; a missing database is not created, while future schemas and migration failures exit non-zero | | throughline runtime-errors enable --json | Enable product-owned local runtime error collection in Throughline's own config; default is disabled | | throughline runtime-errors disable --json | Disable product-owned local runtime error collection | | throughline runtime-errors snapshot --json | Read the bounded product-owned runtime error aggregate; this command performs no network I/O | | throughline runtime-errors diagnostics --json | Read bounded collection/store status without exposing the state path or raw errors | | throughline runtime-errors ack <cursor> --json | Explicitly acknowledge records through a monotonic cursor; unacknowledged records are never compacted | | throughline runtime-errors resolve <fingerprint> --json | Explicitly resolve an aggregate; observing the same fingerprint again reopens it | | throughline runtime-errors reopen <fingerprint> --json | Explicitly reopen a resolved aggregate without fabricating a new occurrence | | throughline runtime-errors compact --json | Remove only acknowledged, resolved aggregates after retention; open or unacknowledged records remain | | throughline runtime-errors report-enable --credential-file <path> --json | Opt in to sending aggregates to the receiver named in that credential file; sending is disabled by default | | throughline runtime-errors report-disable --json | Stop sending aggregates | | throughline runtime-errors report --json | Send unacknowledged aggregates once now (or an empty report when the receiver has not seen this version yet); exits 0 only for sent or nothing_pending | | throughline runtime-errors report-status --json | Read the last attempt time and fixed result code without exposing the receiver, credential, or paths | | throughline handoff-preview --session <id> | Print a Codex-facing throughline_handoff JSON projection | | throughline handoff-context (--session <id> \| --project <path>) --json | Print the SessionStart inheritance context without moving memory rows. Project mode selects the newest captured session with dialogue, supports --disclosure silent, and returns empty when no dialogue exists. Session mode may add a project-bound supplement inside the same 9,500-character budget | | throughline latest-session --project <absolute-path> --json | Read the latest session id strictly scoped to one project; opens the existing database read-only and returns empty when the project has no captured session | | throughline grok-continue --session <id> | Spawn a person-facing Grok seat whose first user text is the handoff-context body. cwd is the source session project_path. Does not spawn without ready context. No --rules. macOS Terminal only | | throughline codex-capture --codex-thread-id <id> | Capture active Codex rollout turns into a codex:<thread_id> DB session | | throughline codex-summarize --session codex:<id> | Summarize captured Codex L2 into L1 with the Codex CLI backend | | throughline codex-resume --session codex:<id> | Render Codex active-work context from a captured Codex session | | throughline codex-resume --session codex:<id> --format handoff | Render a concise fresh-thread handoff prompt without mutating the current thread | | throughline codex-handoff-start --session codex:<id> | Guided start plan for moving handoff memory into a new Codex thread; add --execute to create the thread through app-server, inject developer memory, and open it with --open-host auto\|desktop\|vscode\|cli\|none; output includes requested and resolved host, and the installed $throughline skill passes the current Codex surface explicitly; use --print-prompt to include the prompt and --memo-stdin to carry a current-work memo | | throughline codex-handoff-smoke --session codex:<id> | Read-only validation that the fresh-thread handoff prompt is pasteable before starting a new thread | | throughline codex-handoff-model-smoke --session codex:<id> | Experimental marker smoke for the handoff prompt. --dry-run checks readiness / command boundary without starting Codex exec; --memo-stdin carries a current-work memo; live codex exec --ephemeral --sandbox read-only requires explicit env opt-in | | throughline codex-visibility-smoke --session codex:<id> | Experimental Codex app-server marker smoke; injects memory and starts a model turn | | throughline codex-restore-smoke --codex-thread-id <id> | Experimental read-only app-server restart restore smoke; --inspect-risky-rollout classifies retained rollback text as blocking retained text or quoted/tool-output text; does not prove VS Code restart safety | | throughline codex-restore-source-audit --codex-thread-id <id> | Read-only local restore-source inventory, including VS Code projection-candidate facts; does not prove VS Code restart safety | | throughline codex-host-primitive-audit | Read-only Codex app-server schema audit for same-thread rollback non-resurrection primitives and the host-agnostic repair contract | | throughline codex-vscode-restore-smoke --prepare/--verify --codex-thread-id <id> | Manual VS Code reload/reconnect marker proof protocol | | throughline codex-vscode-rollback-smoke --verify --codex-thread-id <id> | Manual VS Code rollback non-resurrection verifier | | throughline codex-threads | List read-only Codex thread id candidates for the current project | | throughline trim --dry-run --host codex | Preview Codex same-thread context trim memory and host boundary; does not rollback automatically | | throughline trim --preflight --host codex | Read/resume the explicit Codex thread and preview any app-server-count rollback adjustment without rollback/inject | | throughline trim --execute --host codex | Explicit diagnostic Codex current-thread rollback + Throughline DB memory inject; bare $throughline does not run this automatically | | throughline status | Print DB statistics (sessions, skeletons, bodies, details) | | throughline --version | Print the installed version |

Product-owned runtime error collection

Collection is off by default. Enable it through Throughline's own CLI:

throughline runtime-errors enable --json
throughline runtime-errors diagnostics --json

The product-owned config is $XDG_CONFIG_HOME/throughline/runtime-errors.config.json on macOS/Linux (~/.config/throughline/... when XDG_CONFIG_HOME is unset) and %LOCALAPPDATA%\throughline\runtime-errors.config.json on Windows. The CLI writes the versioned throughline.runtime_error_config.v1 shape with private permissions. disable --json changes only this product config. Throughline does not read dotagents configuration; factory integration consumes the public runtime-errors ... --json contract.

Sending runtime errors to your own receiver (opt-in)

Throughline never sends anything unless you opt in on that machine. There is no built-in receiver address. To send the aggregates to a receiver you operate, place a credential file {"url": "...", "key_id": "...", "secret": "..."} that only you can read, then:

throughline runtime-errors report-enable --credential-file /absolute/path/credential.json --json
throughline runtime-errors report --json
throughline runtime-errors report-status --json

Once enabled, the Claude and Codex hook entry points start a detached sender at most once per hour; the hooks do not wait for it. It contacts the receiver when unacknowledged records exist, or once after the installed version changed (a report with empty runtime_errors and resolutions, so the receiver learns the version; see ADR 0030). The body carries the public snapshot fields only (fixed error code, template, count, timestamps, version, resolutions). The secret is never transmitted: the body is signed with HMAC-SHA256(secret, ts + "\n" + SHA-256(body)), redirects are not followed, and records are acknowledged only when the receiver answers 200 with accepted: true, the same report_id, and a valid HMAC-SHA256(secret, report_id + "\n" + received_at) response signature. The reporting switch lives in runtime-errors.report.config.json next to the collection config; the credential file is read in place and not copied. On macOS/Linux the credential file must be owned by you with no group/other permissions and must not be a symlink. See ADR 0025.

Read-only handoff context for local launchers

Use this boundary when a local launcher needs Throughline memory without performing a normal handoff:

throughline handoff-context --session codex:<thread-id> --json
throughline handoff-context --project /absolute/bot/project --json --disclosure silent

The throughline.handoff_context.v1 object contains only schema, status, sessionId, and context. With --project, Throughline selects the newest session in that project that has dialogue context; it returns status: "empty" when none exists. --disclosure silent removes the Throughline announcement without adding long-term memory. The context uses the same budget as SessionStart. With --session, a launcher may append --supplement-file <path> with a throughline.handoff_supplement.v1 JSON object:

{
  "schema": "throughline.handoff_supplement.v1",
  "projectPath": "/absolute/bot/project",
  "handoffDisclosure": "silent",
  "sections": [
    { "title": "Long-term memory", "content": "..." },
    { "title": "Relevant knowledge", "content": "..." }
  ]
}

handoffDisclosure is optional and accepts visible (the default) or silent. The supplement is included only when projectPath matches the source session and shares the 9,500-character budget with conversation memory. If the captured session has no dialogue context yet, a valid project-bound supplement is returned by itself. The command does not create or migrate a database, consume a baton, merge sessions, change sessions.merged_into, or reassign L1/L2/L3 rows. AIterm uses this boundary for its optional cross-harness portable fork; the Observer feed is a separate completed-turn projection and is not a substitute.

Slash commands (invoked by the user in Claude Code):

| Command | What it does | | ------------- | ----------------------------------------------------------------- | | /tl | Write a handoff baton that names the predecessor exactly (use before a new chat, restart, or Claude Desktop /clear). On Grok, also launches grok-continue after a successful baton write | | /clear | Built-in Claude Code reset. VS Code can auto-inherit through SessionStart source='clear'; Claude Desktop requires /tl first | | /sc-detail <time> | Retrieve L2 body text and L3 tool I/O for a past turn |

Built-in /clear does not reach the tested clients' UserPromptSubmit hook. /tl is the deterministic baton path. VS Code /clear uses the separate source='clear' auto path; THROUGHLINE_DISABLE_AUTO_HANDOFF=1 disables only that auto path.

Hook subcommands (invoked by Claude Code, not by humans): session-start (SessionStart), process-turn (Stop), prompt-submit (UserPromptSubmit — executes pending handoff and writes /tl batons; Grok /tl also launches grok-continue).

Caveat context (read-only)

throughline caveat-context --session <id> --project <root> --json returns throughline.caveat_context.v1. ready contains exactly the last three completed user/assistant pairs in their original order, with any captured Thinking for each turn. User and assistant bodies are bo