Feature/vt (#6)

VT emulation instead of clipping sync blocks.
This commit is contained in:
David Beesley
2026-01-19 17:40:09 +13:00
committed by GitHub
parent c7ab4aa06b
commit a824eaea77
9 changed files with 594 additions and 139 deletions

View File

@@ -7,7 +7,7 @@
![Windows](https://img.shields.io/badge/Windows-unsupported-red)
![Rust](https://img.shields.io/badge/rust-2024-orange)
A PTY proxy that tames Claude Code's massive terminal updates.
A PTY proxy that tames Claude Code's massive terminal updates using VT-based rendering.
## The Problem
@@ -15,25 +15,13 @@ Claude Code uses synchronized output to update the terminal atomically. It wraps
The problem: Claude Code sends *entire* screen redraws in these sync blocks - often thousands of lines. Your terminal receives a 5000-line atomic update when only 20 lines are visible. This causes lag, flicker, and makes scrollback useless since each update clears history.
Analysis of terminal recordings confirms Claude Code wraps 100% of its output in sync blocks - every byte of visible output goes through synchronized updates.
Sync blocks start with one of three patterns (from a 3.5GB recording sample):
| Pattern | Count | Frequency | Avg Size |
|---------|-------|-----------|----------|
| Line clearing (`2K` + `1A` repeated) | 3,544 | 55% | 2.7 KB |
| Full screen clear (`2J` + `3J` + `H`) | 2,891 | 45% | 94.5 KB |
| CRLF + color codes | 1 | <1% | 2.0 KB |
The full screen clears are 35x larger than incremental line clears - these are the real problem.
## The Solution
claude-chill sits between your terminal and Claude Code:
1. **Intercepts sync blocks** - Catches those massive atomic updates
2. **Truncates full screen clears** - Only the 45% that are full redraws (94.5 KB avg) get truncated to the last N lines (default: 100). The 55% incremental updates (2.7 KB avg) pass through unchanged.
3. **Preserves history** - Accumulates content in a buffer. Clears on full screen clear, accumulates otherwise.
2. **VT-based rendering** - Uses a VT100 emulator to track screen state and renders only the differences
3. **Preserves history** - Accumulates content in a buffer for lookback
4. **Enables lookback** - Press a key to pause Claude and view the full history buffer
## Installation
@@ -47,7 +35,6 @@ cargo install --path crates/claude-chill
```bash
claude-chill claude
claude-chill -- claude --verbose # Use -- for command flags
claude-chill -l 50 -- claude # Set max lines to 50
```
## Lookback Mode
@@ -66,11 +53,12 @@ When you exit lookback mode, any cached output is processed and the current stat
Create `~/.config/claude-chill.toml`:
```toml
max_lines = 100 # Lines shown per sync block
history_lines = 100000 # Lines stored for lookback
history_lines = 100000 # Max lines stored for lookback
lookback_key = "[ctrl][6]"
```
Note: History is cleared on full screen redraws, so lookback shows output since Claude's last full render.
### Key Format
`[modifier][key]` - Examples: `[f12]`, `[ctrl][g]`, `[ctrl][shift][j]`
@@ -97,9 +85,9 @@ claude-chill creates a pseudo-terminal (PTY) and spawns Claude Code as a child p
1. **Input handling**: Keystrokes pass through to Claude, except for the lookback key which toggles lookback mode
2. **Output processing**: Scans output for sync block markers. Non-sync output passes through directly
3. **Sync block buffering**: Accumulates sync block content until the end marker arrives
4. **Truncation decision**: If the sync block contains a full screen clear (`ESC[2J` + `ESC[H`), truncates to the last N lines. Otherwise passes through unchanged
5. **History tracking**: Maintains a rolling buffer of output for lookback mode
3. **VT emulation**: Feeds output through a VT100 emulator to track the virtual screen state
4. **Differential rendering**: Compares current screen to previous and emits only the changes
5. **History tracking**: Maintains a buffer of output for lookback mode since the last full redraw
6. **Signal forwarding**: Window resize (SIGWINCH), interrupt (SIGINT), and terminate (SIGTERM) signals are forwarded to Claude
## Disclaimer