You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(screen): session:screen frames are 50% duplicate strings and 99% spinner-only diffs #746
session:screen is the highest-volume, highest-byte IPC channel and almost all of it is redundant.
Evidence (session recording 794dafdd, 13.2 min, one Claude session): 4,728 frames = 6 Hz, avg 8.3 KB/frame (p99 13.4 KB). Per frame: plain 2,109 B, recent 2,109 B, markdown 1,853 B, recentMarkdown 1,853 B — recent === plain in 4,728/4,728 frames and recentMarkdown === markdown in 4,728/4,728 (an alt-screen TUI has no scrollback). Consecutive frames: 78% differ in exactly one line and 21% in two — the spinner line (✻ Beboppin'… → ✽ Ionizing… → ✶ … (5s · thinking…)). 0% byte-identical, so the renderer's no-op bail never fires. This run: 21,700 frames, 285 MB recorded; one session 8,913 frames = 97 MB.
Mechanism
packages/claude-code-headless/src/terminal/HeadlessTerminal.ts:600-614 gates on exact equality of plain/recent, then computes both markdown walks and emits four strings every 100 ms; ClaudeCodeHeadless.ts:614 forwards every snapshot; src/providers/claude/runtime/claudeSession.ts:490-497 and src/main/sessions/forwarder.ts:57 send them through the 100 ms latest-wins coalescer; useIpcSubscriptions.ts:739-840 commits a new runtime object per frame (chrome-tick frames skip the feed-debug append but still re-render the workspace at 6 Hz × active sessions); SessionRecorderManager JSON-stringifies each frame.
Expected
Where recent === plain (and recentMarkdown === markdown), send the field once and let the renderer alias it — halves bytes and removes one markdown walk per frame. Can be done at the src forward point without touching the package.
Spinner-aware gate at the forward point: normalise the spinner glyph and the (Ns · …) timer before comparing to the last emitted frame; condition parsers keep running on the raw frame. Renderer: return prev for spinner-only diffs.
markdown is debug-only per the comment in useIpcSubscriptions.ts:786-800; consider not sending it unless a debug consumer is mounted.
Impact
~10× fewer screen IPC messages while an agent is thinking, −50% bytes on the rest, half the markdown conversion CPU in main, ~−250 MB per hour of session-recording IO, far fewer workspace re-renders.
Screen-frame gate #761 now preserves real content edits and seeds late/reloaded local renderers from the raw snapshot cache after successful recovery. Both full host CI gates pass on 2e561bf, with 26 focused gate/recovery/wire tests. Awaiting owner merge confirmation.
Activity
fix(sessions): key the screen gate on the picker and reset it when a …
fix(sessions): preserve content changes and seed recovered renderer s…
Juliusolsson05 commentedon Sep 5, 2026
Screen-frame gate #761 now preserves real content edits and seeds late/reloaded local renderers from the raw snapshot cache after successful recovery. Both full host CI gates pass on 2e561bf, with 26 focused gate/recovery/wire tests. Awaiting owner merge confirmation.