Document embedded terminal module in CLAUDE.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jonas H
2026-06-11 09:11:00 +02:00
parent 255c67de3f
commit d34496da0b

View File

@@ -16,6 +16,10 @@ src/sse.rs incremental SSE parser; tolerant of chunk splits mid-event/mid-UT
src/app.rs Arc<Mutex<App>> shared state; Tap = one in-flight tapped request,
translates SSE events → session Entries (Drop closes it out)
src/ui.rs ratatui rendering @ ~30fps; session list + scrollable feed
src/term.rs embedded claude pane: spawns `claude --session-id <uuid>` in a
portable-pty routed through the proxy; wezterm-term models the
screen (and answers terminal queries); renderer paints cells
into the ratatui buffer
```
Data flow: proxy task parses SSE chunks → `Tap::handle()` mutates shared state →
@@ -30,9 +34,17 @@ UI thread redraws on its own tick (no channel; just the mutex).
sends identity encoding we can parse in transit. Don't "fix" that.
- Hop-by-hop headers (`content-length`, `transfer-encoding`, etc.) are stripped
both directions; hyper re-frames.
- Sessions are keyed by the UUID after `session_` in request `metadata.user_id`.
- Sessions are keyed by the session UUID in request `metadata.user_id`
Claude Code ≥2.1.x sends a JSON blob with `"session_id":"<uuid>"`, older
builds `user_…_session_<uuid>`; `proxy::session_key` handles both.
Concurrent requests (subagents) share a session but each `Tap` tracks its own
current entry index — entries/sessions are append-only, so indices stay stable.
- The embedded pane's session is matched by the `--session-id` UUID we
generate; the tap drives pane behavior: grows it for AskUserQuestion /
ExitPlanMode (sized from the question's option count) before Claude Code
renders the prompt, shrinks when the tool_result echoes back, and schedules
a ctrl-l transcript wipe 400ms after each turn (the pane is prompt-only;
the feed shows the context).
- Tool input streams as raw JSON fragments; pretty-printed only on
`content_block_stop`. Text re-renders markdown every frame, so partial
markdown self-heals.
@@ -41,6 +53,15 @@ UI thread redraws on its own tick (no channel; just the mutex).
- `tui-markdown` is pinned `=0.3.5`: later versions use `ratatui-core` (0.30
alpha types), incompatible with ratatui 0.29.
- `wezterm-term`/`wezterm-surface` are not on crates.io: pinned to a git rev
of the wezterm monorepo (keep both revs identical).
- The pane's render window crops Claude Code chrome by *position*
(`term.rs`: `BOTTOM_CROP`, start ≥ 2, `PTY_PAD`) — tuned to the current
Claude Code UI; retune there if an update adds/removes chrome rows.
- Keybindings avoid Alt entirely: on layouts like dk_mac_fixed, Alt composes
characters (alt-c = ©) and never reaches the app as a modifier. Pane keys:
F2 toggle, ctrl-↓ focus claude, ctrl-↑ focus feed. `CT_DEBUG_KEYS=1` shows
raw key events in the status bar.
- ratatui needs feature `unstable-rendered-line-info` for `Paragraph::line_count`
(used for follow/auto-scroll).
- reqwest is `default-features = false` + `rustls-tls,stream` — don't enable
@@ -59,3 +80,8 @@ UI thread redraws on its own tick (no channel; just the mutex).
- Tool results only appear once the *next* request fires; if the session ends
right after a tool call, that result is never seen. Output is what Claude
Code sends the model (i.e. post-truncation).
- Embedded pane: no bracketed paste or mouse forwarding yet; no scrollback
view (live screen only); shift+enter needs kitty keyboard protocol pushed
on the outer terminal (not done); permission prompts aren't detected for
pane growth (not visible in the API stream — would need a Notification
hook hitting a local control endpoint).