-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
Background terminals — agent panels in inactive worktrees or panels not currently visible — hold their full scrollback buffer in memory indefinitely, even though they are not being viewed. Automatically reducing the scrollback limit for terminals in lower renderer tiers would free substantial memory in proportion to how many panels are backgrounded.
Problem Statement
Canopy's TerminalRendererPolicy already classifies terminals into FOCUSED, VISIBLE, and BACKGROUND tiers with hysteresis-debounced transitions. However, tier changes currently only affect rendering behavior and PTY activity signaling — they do not adjust the xterm.js scrollback buffer.
A backgrounded terminal retains its full allocated buffer (up to 10,000 lines for agents) even though no user is viewing it. When a user has 20 agent panels across several worktrees, only a handful are ever visible at once, yet all 20 hold full-size buffers. The memory is entirely idle.
xterm.js supports dynamic scrollback adjustment at runtime: setting terminal.options.scrollback to a lower value immediately trims the oldest lines from the circular buffer, freeing memory synchronously. The reverse — increasing the limit — expands capacity for new incoming lines without restoring lost history.
The tier system in TerminalRendererPolicy.applyRendererPolicyImmediate is the natural integration point. It already distinguishes "active" vs "background" backend states and triggers wake/restore cycles on tier upgrade. Scrollback adjustment fits this pattern.
Desired Behavior
When a terminal transitions to the BACKGROUND tier and remains there past the existing downgrade hysteresis window, its xterm.js scrollback should shrink to a lower limit, freeing the buffer memory it no longer needs. When the terminal is brought back to an active tier, its scrollback limit should expand again to accommodate new output.
The transition must be safe:
- If the user is currently scrolled up in the terminal's history, the reduction should be deferred or skipped to avoid a jarring scroll snap to the bottom
- If there is an active text selection, the reduction should be deferred to prevent selection index corruption
- The alternate buffer (vim, less, top) is unaffected — xterm.js enforces
scrollback: 0for alternate buffers regardless
The goal is transparent to the user: background terminals quietly use less memory; when the user switches back, the terminal continues streaming live output normally within the restored limit.
Context
Relevant infrastructure already in place:
TerminalRendererPolicy— tier management with debounced downgrade andonTierAppliedcallback hooksrc/utils/scrollbackConfig.ts— type-specific policies with multipliers and limits;PERFORMANCE_MODE_SCROLLBACK = 100shows the precedent for policy-driven scrollback reductionsrc/store/slices/terminalRegistry/index.ts#L304-L322— where the initial effective scrollback is computed from user settings and terminal type- The
ManagedTerminaltype holds the live xterm.jsterminalinstance, making it accessible to policy decisions
Acceptance Criteria
- Terminals that have been in BACKGROUND tier past the hysteresis window have a reduced xterm.js scrollback compared to their configured limit
- Terminals that return to an active tier have their scrollback limit restored to the configured value, so new output fills up to the full allowed buffer
- A terminal whose user is actively scrolled up in history is not trimmed while the user is reading it
- A terminal with an active text selection is not trimmed until the selection is cleared
- The alternate buffer (vim, less, top, etc.) is unaffected
- No visible jank, snap-to-bottom, or selection glitches during normal panel-switching workflows
- Agent state detection continues to function correctly (the detection window is the last ~50 lines, well within any reasonable background minimum)
Edge Cases & Risks
- Rapid worktree switching could cause many terminals to cycle through tiers quickly; the existing
TIER_DOWNGRADE_HYSTERESIS_MSdebounce already mitigates this but the scrollback changes should not add latency to tier upgrades - The background scrollback minimum must be high enough that new output from a still-running agent isn't immediately lost — the terminal keeps receiving data even while backgrounded
- History visible to the user when they switch to a background terminal will only extend back to what fit in the reduced buffer; this is a known tradeoff of trimming-based approaches