[BUG] Persistent TUI render lag: entire-screen React model conflicts with keystroke responsiveness
Summary
Typing lag in Claude Code is persistent (always present at some level) and degrades with system load. The underlying cause is architectural: Claude Code renders the entire screen buffer on every frame (like a game engine or React app), which blocks keystroke processing during render cycles.
Environment
- Platform: Linux 6.12.25-amd64 (Kali GNU/Linux Rolling)
- Terminal: xterm-256color
- Shell: zsh
- Claude Code: 2.1.63
- Node.js: v20.19.2
- CPU: AMD Athlon 2850e (single-core, SSE2-only)
Observed behavior
Persistent: Typing lag is always present at some baseline level, not just during startup or spikes.
Degrades with load: Responsiveness gets worse as:
- Session context grows (related: #18943)
- System CPU load increases
- Session duration increases
Keystroke-specific: Backspace is disproportionately affected (related: #29366):
- Holding backspace produces sparse, buffered output
- Delete + left-arrow is more reliable
- Regular character input is more responsive than backspace
Root cause analysis
Claude Code is built as a React/Ink TUI app, not a traditional line-oriented CLI. This means:
- Full-screen re-renders: Every keystroke triggers a complete screen buffer rebuild (like rendering a frame in a game)
- Blocking render loop: While rendering, keystroke processing is blocked or buffered
- CPU-hungry design: Each frame requires ANSI sequence construction and terminal updates
- No framerate tuning: Unlike game engines, there's no way to lower framerate (e.g., 10 FPS instead of 30+ FPS) to give the CPU more time per frame
Why backspace is worse
Backspace requires:
- Keystroke delivery
- Character deletion from buffer
- Re-render of entire input line + all surrounding UI
- ANSI sequence generation
- Terminal write
This multi-step process is more likely to be starved during render cycles than simple character input.
Potential mitigations
- Lower framerate setting (e.g.,
--max-fps 10): More time per frame = fewer dropped keystrokes - Separate input thread: Process keystrokes on a separate thread from rendering
- Input buffering with priority: Ensure backspace/delete operations interrupt renders
- React batching: Render only changed screen regions, not entire buffer each frame
- Process niceness: Allow users to run Claude Code at higher priority (lower nice value)
Impact
Text input is painful on single-core or CPU-constrained systems. This is especially problematic for:
- Older hardware
- VMs / constrained containers
- Systems under load
- Remote SSH sessions
Related issues
- #18943: Input Lag When Context is Full
- #29366: Render loop causes startup input lag
- #22456: Terminal input lag increases with session length
- #25286: Terminal freezes with render loop
---
Question for maintainers: Is the full-screen re-render architectural choice intentional? Would you consider adding framerate throttling or input-thread separation as potential solutions?
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗