Skip to content

Move terminal VT state into the daemon (per design 01) #158

Description

@MasonRhodesDev

Tracking issue for docs/designs/01-daemon-canonical-terminal.md (Accepted).

Problem

When a single agent harness emits sustained PTY output, the desktop GPUI thread becomes unresponsive until the harness calms down. The render thread is on the parse path: LiveTerminalRuntime::apply_output (app/src/terminal_runtime.rs:283) runs alacritty_terminal::vte::ansi::Processor::advance synchronously inside drain_terminal_launch_replies (app/src/app.rs:6059) and drain_session_events (app/src/app.rs:5910). Existing mitigations (DRAIN_OUTPUT_BYTE_CAP, watchdog from #125) limp under typical load.

Decision

Per the design doc:

  • One alacritty_terminal::Term per PTY, owned by a per-tab tokio task in the daemon.
  • New wire: SessionEvent::TerminalFrame { Full | Diff } with monotonic seq, pull-paced via Control::TerminalSubscribe { max_fps, since_seq }.
  • Scrollback + search become RPCs (Control::TerminalReadScrollback, Control::TerminalSearch).
  • Bell/title via dedicated WorkerReply::Push variants.
  • PTY spawn moves to the daemon; GPUI-side fulfillment (pending_tab_launches, TabResizeRequest) goes away.
  • Inactive tabs still parse daemon-side; no frames emitted for unsubscribed (viewer, tab) pairs.
  • terminal-wrapping-principle refined: ANSI/VT parsing may live daemon-side; per-agent semantic parsing still forbidden.

Phases (see design doc for sub-phase breakdown)

  • Phase 1 — Wire types + principle clarification (1 PR; 4 commits)
  • Phase 2 — Daemon-side Term task (1 PR; 5 commits)
  • Phase 3 — Per-viewer pacer + dispatch wiring (1 PR; 3 commits)
  • Phase 4 — PTY spawn moves to daemon, flag-gated (1 PR; 3 commits)
  • Phase 5 — Desktop cutover (6 PRs: 5a–5f)
  • Phase 6 — Warm launches + Claude session restore migration (1 PR)
  • Phase 7 — Mobile viewer cutover (separate; possibly own repo)
  • Phase 8 — Diff frame emission (deferred; own issue when triggered)
  • Phase 9 — Per-viewer max_fps honoring (deferred; own issue when triggered)

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions