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
During long-running Claude Code sessions in Canopy terminals (particularly with Codex MCP active), the terminal viewport intermittently bounces between the bottom and mid-buffer positions, with text selection locked during the bouncing phase. The behavior occurs in both Canopy and VS Code's integrated terminal, indicating it's triggered by Claude's escape sequences interacting with xterm.js rather than Canopy-specific scroll logic.
Current Behavior
Viewport bouncing:
Terminal scrolls to bottom where new output appears
Immediately jumps upward to a fixed position in the middle of chat history
Continues bouncing between bottom and mid-buffer region as new content arrives
Selection lock:
Text selection is disabled or severely impaired during bouncing
Mouse-based selection behaves as if terminal is in mouse-tracking mode
Dragging over text doesn't select as expected
Spontaneous recovery:
After additional output (often when MCP call finishes), bouncing stops
Selection functionality returns to normal
Subsequent output scrolls to bottom and stays there
When it occurs:
Most visible during active Claude Code work (e.g., /codex:plan with Codex MCP)
Requires long chat history in terminal
Typically starts mid-session, not from beginning
Reproducibility: Intermittent during intensive Claude sessions
Expected Behavior
When terminal is at bottom and user hasn't scrolled up:
Viewport should track new output and remain pinned to bottom
Routes mouse events to application instead of using for selection
Disabled with corresponding ...l sequences when bouncing stops
Scroll-region manipulation
CSI <top>;<bottom> r (set scrolling region)
Combined with cursor movement causes viewport repositioning
Supporting evidence:
Bouncing only occurs during intensive Claude work (Codex MCP calls)
Stops when additional output produced (mode exits)
Selection locked during bounce, returns after
Same behavior in VS Code terminal (CLI-driven, not app-specific)
Most plausible: Claude Code enters TUI-like mode for progress/status rendering, using cursor movement and mouse tracking for in-place updates. Xterm follows these sequences, causing visible bouncing and selection hijacking.
Deliverables
Code Changes
Diagnostic phase:
Add escape sequence logging to TerminalInstanceService for agent terminals
Capture raw PTY output to identify exact sequences causing bouncing
Mitigation (escape sequence filtering):
Create ANSI sequence sanitizer layer for agent terminals in "follow mode"
Strip problematic sequences before xterm receives them:
Mouse tracking enables (?1000h, ?1002h, ?1006h)
Off-screen cursor positioning when user is at bottom
Optional: scroll-region changes
Scope: Apply only when:
Terminal type is agent/Claude terminal
User is at bottom (not manually scrolled up)
Terminal is not focused
Tests
Integration test: capture known problematic sequences, verify filtering
Unit test: ANSI parser correctly identifies mouse tracking and cursor positioning
Regression test: ensure basic ANSI features (colors, bold) preserved
Manual test: long Claude Code session with Codex MCP shows no bouncing
Documentation
Add comment in TerminalInstanceService explaining sequence filtering rationale
Document configuration option for stabilization (if feature-flagged)
Summary
During long-running Claude Code sessions in Canopy terminals (particularly with Codex MCP active), the terminal viewport intermittently bounces between the bottom and mid-buffer positions, with text selection locked during the bouncing phase. The behavior occurs in both Canopy and VS Code's integrated terminal, indicating it's triggered by Claude's escape sequences interacting with xterm.js rather than Canopy-specific scroll logic.
Current Behavior
Viewport bouncing:
Selection lock:
Spontaneous recovery:
When it occurs:
/codex:planwith Codex MCP)Expected Behavior
When terminal is at bottom and user hasn't scrolled up:
When user has scrolled up:
Text selection:
Steps to Reproduce
/codex:planor other intensive MCP operationsReproducibility: Intermittent during Claude Code sessions with long history and active MCP calls
Environment
Evidence
Affected Files:
src/services/TerminalInstanceService.ts- SAB/frame buffering, scroll managementsrc/components/Terminal/TerminalPane.tsx- Terminal rendering and user interactionelectron/services/AgentStateMachine.ts- Agent state trackingObservations:
Related context:
PR #919 changes:
setAgentStateto no-op for scrollingsetFocusedno longer callsscrollToBottomon focus changesRoot Cause
Hypothesized: Claude Code CLI emits ANSI escape sequences that xterm.js interprets as viewport repositioning commands:
Cursor movement to earlier lines
CSI <row>;<col>H/CSI <row>;<col>f(absolute cursor position)CSI nA/CSI nB(cursor up/down)ESC 7/ESC 8(save/restore cursor)Mouse tracking enables (selection lock)
CSI ?1000h,CSI ?1002h,CSI ?1006h(mouse reporting modes)...lsequences when bouncing stopsScroll-region manipulation
CSI <top>;<bottom> r(set scrolling region)Supporting evidence:
Most plausible: Claude Code enters TUI-like mode for progress/status rendering, using cursor movement and mouse tracking for in-place updates. Xterm follows these sequences, causing visible bouncing and selection hijacking.
Deliverables
Code Changes
Diagnostic phase:
Mitigation (escape sequence filtering):
?1000h,?1002h,?1006h)Scope: Apply only when:
Tests
Documentation
Technical Specifications
Footprint:
src/services/TerminalInstanceService.ts- Add sequence filtering layerPerformance:
Dependencies
Blocking:
scriptcommand to confirm exact sequences:script -q -f /tmp/claude-bounce.log -c "claude <codex command>"Informational:
Tasks
scriptcommand to capture raw PTY outputTerminalInstanceService.ts?1000h,?1002h,?1006h)Acceptance Criteria
Edge Cases & Risks
Edge cases:
htop,vim)Risks:
Mitigation strategies:
Additional Context
Alternative mitigation approaches considered:
Pinned-bottom re-scroll - Allow sequences through but force scroll-to-bottom after detection
Plain-mode option - User toggle for no-TUI mode
Observability only - Add diagnostics without changing behavior
Recommended approach: Escape sequence sanitization (option 1 in proposal) scoped to agent terminals in follow mode, with feature flag for testing.
Diagnostic script for sequence extraction:
Next steps after issue creation:
scriptcommand