Swap the rendering core. The previous backend (vt100 0.16) only stored
six attributes — fg/bg color, bold, dim, italic, underline, inverse —
and silently dropped everything else when re-emitting the screen. With
modern Claude Code that meant losing OSC 8 hyperlinks, strikethrough,
fancy underline styles, underline color, and so on.
New stack:
* wezterm-term::Terminal handles the byte-driven VT emulation. Its
cell model preserves the full modern attribute set including
hyperlinks and underline color.
* termwiz::surface::Surface is used as a "mirror of last emitted
state." Each render diffs the terminal's current visible lines
against this mirror to compute the minimum change set.
* termwiz::render::TerminfoRenderer encodes those Changes as bytes
using a TrueColor + hyperlink-capable capability profile.
A defensive OSC 8 close is appended to every render to handle the case
where the diff ends inside a hyperlinked region (the renderer only
emits the close on transition to a non-hyperlinked cell).
Both termwiz and wezterm-term are pulled from the wezterm git repo at
a pinned rev so the Line types unify across the dep graph.
Test results, against the color-preservation harness from the previous
commit (run via cargo test color_preservation -- --ignored on master):
baseline (vt100): 0 / 5 passing
after this commit: 3 / 5 passing (osc8, strikethrough, double underline)
The two still-ignored tests (curly underline, underline color) are
upstream renderer limitations: termwiz's TerminfoRenderer only emits
Single/Double underline and never emits SGR 58. The cell model stores
both correctly; only the emit step drops them. Tests are kept #[ignore]
with comments calling out the upstream gap.
Total: 118 passed, 4 ignored, 0 failed.
Pin the baseline: feed OSC 8 hyperlinks, strikethrough, curly underline,
underline color, and double underline through Proxy, force a render,
and capture what the proxy emits to its stdout side. Each test asserts
the styling survives the round-trip.
All five fail on the current vt100 0.16 backend because its cell model
only stores fg/bg color, bold, dim, italic, underline, inverse — every
other attribute is dropped at render time. Tests are #[ignore]-gated so
CI stays green; run with --ignored to see the baseline failures. Once
the emulator is swapped to termwiz, remove the gates.
A truecolor-foreground sanity test runs by default and confirms the
parts of the SGR space vt100 does support are still working.
Adds Proxy::force_render as a #[cfg(test)] wrapper around the private
render_vt_screen method.
Add a pty-mock workspace crate (echo/alt-screen/paste-echo/buffer-fill/
sync-blocks subcommands) plus an in-process integration test suite that
drives Proxy directly via a new_for_test constructor and #[cfg(test)]
state accessors. Sets up the regression net needed before swapping the
underlying VT emulator from vt100 to termwiz.
Pulled from upstream draft PR #35; the alt-screen feed-order semantic
change is intentionally deferred (its dedicated test is left #[ignore]).
* fix: bracketed paste passthrough and pty write deadlock prevention
Enable bracketed paste on the real terminal at startup so tmux/Ghostty
wraps paste content in markers. Detect paste markers in process_input
and forward directly to the child pty, skipping byte-by-byte lookback
matching. Replace blocking write_all with write_to_pty_draining that
interleaves output reads to prevent the classic pty buffer deadlock
when forwarding large input.
* Fix clippy/fmt, buffer drained PTY output through VT parser, handle split paste end markers
- Fix clippy collapsible_if warning and cargo fmt issues
- Drained child output during PTY writes now buffers into pty_drain_buffer
and is processed through process_output after process_input returns,
keeping VT parser state, history, and alt-screen tracking in sync
- Add paste_remainder buffer to handle paste end markers split across
read() boundaries, preventing permanent stuck-in-paste-mode state
- Add split_trailing_marker_prefix helper with tests
---------
Co-authored-by: Dave Beesley <david.beesley@pm.me>
* Fix auto-lookback trigger and add version tracking
- Trigger on stdin inactivity instead of render time
- Only dump when new output exists since last dump
- Default timeout 5s -> 15s
- Embed git hash in version output
- Document macOS config path
* feat: add auto lookback mode
Automatically shows full terminal history after idle timeout,
returns to truncated view when new output arrives.
- Add auto_lookback_timeout_ms config option (default: 1000ms)
- Add --auto-lookback-timeout CLI flag
- Set to 0 to disable the feature
* intermediate
* auto lookback
---------
Co-authored-by: Ilya Sinkin <ilyasinkin2002@yandex.kz>