0.9.1 Windows input rework breaks empty-bracketed-paste decode: clipboard image bridge on ctrl+v silently dead in herdr --remote (Windows Terminal)
Summary
On Windows, clipboard image paste into herdr --remote panes via the default ctrl+v binding silently stopped working after upgrading the client to 0.9.1. The same setup works when keys.remote_image_paste is rebound to a raw key (e.g. f8), and it works again on ctrl+v after unbinding ctrl+v from Windows Terminal's own paste action. On 0.9.0-era clients the default ctrl+v binding worked fine.
Environment
- Client: Windows 11 (build 26200), Windows Terminal (ctrl+v explicitly bound to
Terminal.PasteFromClipboard), PowerShell 7.6.6 - herdr client 0.9.1 (stable); remote servers on macOS (macmini / macbook), both herdr 0.9.1
- Bridge triggers verified against
herdr-client.log/ remoteherdr-server.log(staged client clipboard image ...)
Symptom
With defaults (keys.remote_image_paste = "ctrl+v"), pressing ctrl+v in a --remote attach window with an image on the clipboard does nothing at all:
- no
bridging local image to remote serverline in the client log - no
clipboard image paste trigger received, but local clipboard has no imageline either - no
staged client clipboard imageon the remote server
So the trigger function never matches — the keypress/paste never arrives as a bridging candidate. Everything else is healthy: the same client bridges fine via source="file drop", and rebinding to f8 produces immediate, correctly-sized stagings.
Mechanism (as far as I can trace it)
- Windows Terminal consumes ctrl+v itself (bound to
Terminal.PasteFromClipboard), so herdr never sees a ctrl+v key event. - Herdr's designed path for WT is the empty-bracketed-paste side channel: WT pasting an image-only clipboard emits
ESC[200~ESC[201~, which decodes toPaste { text: "" }, andshould_bridge_clipboard_image_eventstreats an empty paste as an image-paste trigger. - That empty-paste decode worked on 0.8.2/0.9.0 clients (I have
bridging local image ... source="clipboard paste"log lines from those versions) and stopped with the 0.9.1 client. src/client/clipboard_images.rs(the trigger) is byte-identical between v0.9.0 and master — I diffed it. What did change massively in 0.9.1 is the Windows input decoder:src/client/input/windows_vti.rsgrew from 3243 to ~3899 lines across 25 hunks (new default-mouse-candidate machinery that can swallow key records, severalflush_timeout()→flush_interrupted()swaps, framer drain changes). An empty paste has no content bytes, so it is the most fragile case: if any record boundary takes a semantic/flush path that discards pending framer state, the empty paste never completes and noPasteevent is emitted.
This is the same 0.9.1 input rework that fixed Alt+V pass-through (#3702) and reportedly regressed Shift+Enter (#3269 / the Win32 input reporting hotfix).
Workarounds (both confirmed working)
- Rebind:
[keys] remote_image_paste = "f8"in config.toml — raw function keys bypass the terminal paste action entirely. - Unbind ctrl+v in Windows Terminal settings (move
Terminal.PasteFromClipboardto ctrl+shift+v): ctrl+v then reaches herdr as a real key event, and the defaultctrl+vcombo trigger (the key-combo branch ofshould_bridge_clipboard_image_events) fires normally. This restores the muscle-memory key. ctrl+alt+vdoes not work as a middle ground (chord arrives mangled — AltGr/IME territory).
Fix directions
- Restore empty-bracketed-paste decoding on the Win32 record path (the 0.9.1 windows_vti.rs rework looks like the regression window; bisecting the 25 hunks around
PasteAwareKey/flush_interrupted/ default-mouse-candidate handling should find it). - Consider allowing
keys.remote_image_pasteto accept multiple bindings, so users can keep bothctrl+vand a fallback raw key. - Document the WT ctrl+v interaction on the Windows docs page (that image paste needs ctrl+v unbound in WT, or a non-terminal-consumed key).
Related
- #3702 (Alt+V arrives as bare
von WT — fixed by the same 0.9.1 rework that appears to break this) - #4230 (conhost: ctrl+v / ctrl+shift+v paste broken without WT)
- #4005 (multi-attach clipboard routing)
Source: herdrdev/herdr