Sessions panel now shows on-disk JSONL history for the current directory
(background scanner, ~1/s, deduped against live sessions). space/→ expands
a session into a lazygit-style turn tree; j/k walks sessions and turns; v
anchors a visual range; b materialises a new fully-decoupled branch file.
ctrl-↓ is the commit point for attach/resume/spawn; live external sessions
get a 3-second liveness guard (past_embeds skips the guard for sessions we
killed ourselves).
n opens a model-picker popup and spawns a fresh --session-id session;
model aliases are auto-discovered by scanning the installed claude binary
(no API call, no exec). ctrl-f toggles fullscreen for the embedded pane.
Mouse is now captured: wheel always scrolls the feed, left-drag selects
screen text copied on release via OSC 52 (like Claude Code). Native
selection needs shift held.
FeedCache stores per-entry rendered lines + wrapped heights, rebuilt only
when the content fingerprint changes — work while holding the app mutex is
proportional to what changed, and feed scroll now works past u16::MAX lines.
Kind::User entries (deep-blue ❯ prefix) surface user prompts from request
bodies via record_user_prompt.
src/markdown.rs added: GFM table rendering (box-drawing, width-fitted
columns) and heading # marker stripping, compensating tui-markdown 0.3.5
gaps without upgrading.
The proxy tap now runs on a dedicated tokio task via a bounded mpsc channel
(try_send; drop-on-full) so it never delays forwarded bytes. Listener is
bound before the TUI starts so multi-instance port coexistence works from
launch; CT_UPSTREAM added for fully offline testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
metadata.user_id is now a JSON-ish blob containing "session_id":"<uuid>"
(verified against the 2.1.173 binary: user_id is built from an object
with device_id/account_uuid/session_id). split("session_") was matching
inside "session_id":" and producing mangled keys like `id":"a78…`,
which broke the embed-session match — so the pane never grew for
interactive prompts. New session_key() handles both the JSON blob and
the legacy user_…_session_<uuid> format, with tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Render window is now content-anchored instead of the raw screen top:
ends BOTTOM_CROP(2) rows above the last non-blank row (hides the
"? for shortcuts"/mode hint rows) and starts no higher than row 2
(hides "✻ Worked for 1s"; the streaming spinner stays visible since it
sits next to the input box). The PTY gets PTY_PAD(4) extra rows so
Claude Code still has room to draw what we crop. Compact pane shrinks
12 → 8 rows.
AskUserQuestion pane height is now estimated from the tool input
(max over questions of: question text + 2 rows per option incl. the
implicit "Other" + submit/hint rows + tab header), replacing the flat
75% — which remains the fallback for ExitPlanMode/parse failures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pane was showing Claude Code's own transcript (tool calls, diffs) —
redundant with the feed above. Two measures:
- Default pane height is now compact (12 rows): room for the input box
and status, (almost) none for transcript. Interactive grow to 75% is
unchanged.
- When a turn of the embedded session finishes streaming (Tap drop),
schedule a ctrl-l into the PTY 400ms later: Claude Code clears the
screen but keeps the conversation, leaving just the prompt UI.
Residual: while a response is streaming, a few transcript rows can
still scroll through the compact pane until the turn-end wipe fires.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude Code clips AskUserQuestion option lists to the rows available;
60% was still cutting options off. Also relax the upper clamp so small
terminals give the prompt as much as possible (6 rows reserved).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- src/term.rs: self-contained module spawning `claude --session-id <uuid>`
with ANTHROPIC_BASE_URL pointed at our proxy, inside a portable-pty;
wezterm-term models the screen (and answers terminal queries), a small
renderer paints cells into the ratatui buffer.
- Toggle with alt-c; off by default, hiding keeps the session alive.
- Modifier-split input: plain keys go to claude, alt-keys drive the feed
(alt-q quit, alt-j/k scroll, alt-f filter, alt-n/p session).
- Dynamic pane height: the tap flags AskUserQuestion/ExitPlanMode in the
embedded session (matched via --session-id) before Claude Code renders
the prompt → pane grows 35%→60%; shrinks when the tool_result echoes
back in the next request.
- wezterm-term isn't on crates.io: pinned git rev of the monorepo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>