Terminal render loop causes unresponsive input in idle session
Environment
- Claude Code: v2.1.87
- macOS: 26.3.1 (ARM64)
- Terminal: Ghostty
- StatusLine:
ccstatusline(global install)
Symptom
Session completes work normally, shows the ❯ prompt, but keyboard input becomes completely unresponsive. The session appears idle but the process is actively consuming CPU.
Evidence
1. Terminal write rate (idle session should write 0)
| | Hung Session | Healthy Session |
|--|-------------|-----------------|
| Terminal writes | ~2,082 bytes/sec (continuous) | 0 bytes |
| Total in ~10 min | ~530KB | 0 |
Measured via lsof fd offset on the terminal device — offset increases continuously on the hung session while healthy sessions remain static.
2. CPU escalation
| Time | Hung | Healthy |
|------|------|---------|
| T+0 | 15% | 0.1% |
| T+3m | 20% | 0.1% |
| T+8m | 35.6% | 0.1% |
3. Memory growth
244MB → 287MB over ~10 minutes (healthy session stable).
4. Process thinks it's active
caffeinate -i -t 300 child process is respawned every 5 minutes — the session believes it's still doing work.
5. Stale API connections
2 ESTABLISHED TCP connections to the API remain open. Healthy idle sessions have 0 TCP connections.
Call Stack (sample output)
The main thread's active time (outside kevent64 idle) goes through:
JIT-compiled JS → icu::RuleBasedBreakIterator (Unicode text segmentation)
→ __write_nocancel (terminal write)
The process is continuously re-rendering the terminal UI — running full Unicode text layout and writing the result to the terminal — while the display appears unchanged.
Suspected Trigger
The session had undergone context compression ("Churned for 1m 3s") shortly before the issue appeared. The render loop may be triggered by post-churn UI state that fails to settle.
Diagnostic Commands
Others can verify with:
# Compare terminal write offset (should be static for idle session)
lsof -p <PID> | grep "0u.*ttys"
# Take two samples 3 seconds apart — offset should NOT increase
# CPU check
ps -p <PID> -o pid,%cpu,stat
# Process sample
sample <PID> 3
# Look for icu::RuleBasedBreakIterator and __write_nocancel in call stackThis issue has 4 comments on GitHub. Read the full discussion on GitHub ↗