Pasting multi-line text into a tmux session reached over ssh from inside another tmux (client → tmux → ssh → tmux) replaced every newline with a literal CSI 27;5;106~. That sequence is C-j — the pasted newline — rendered in modifyOtherKeys form rather than sent as a newline. The same paste through a single tmux (client → tmux → ssh) was fine.
Cause
tmux 3.5 rewrote extended-key handling and encodes keys inside a bracketed paste. The layer further in passes those bytes through verbatim instead of decoding them, so the application receives the escape as text.
A hop only corrupts when whatever sits downstream of it has asked for modifyOtherKeys mode 2. A nested tmux always asks, because of the *:extkeys terminal-feature this config sets; an application running directly under screen-256color generally does not. That asymmetry is the whole reason one tmux in the chain worked and two did not — the extra tmux is itself a mode-2 requester.
How it was verified
Built tmux 3.2a, 3.3a, 3.4, 3.5a, 3.6b and 3.7c from source, then drove a real bracketed paste through a pty into each chain and recorded the exact bytes the innermost application received. Only 3.5 and 3.5a corrupt, and only on the requesting hop:
outer → inner
paste
outer → app
paste
3.4 → 3.5a
BAD
3.4
OK
3.5a → 3.5a
BAD
3.5a
BAD
3.5a → 3.7c
BAD
3.6b
OK
3.6b → 3.5a
BAD
3.7c
OK
3.6b → 3.6b
OK
3.7c → 3.7c
OK
Fixed upstream in 3.6, so upgrading is the real answer wherever that is available. Debian bookworm ships 3.3a and is unaffected; trixie and recent Ubuntu ship 3.5a and are.
Change
For hosts pinned to a distro tmux, disable extended keys on exactly those two versions. Nothing narrower works, and both plausible alternatives were tested and rejected: extended-keys-format csi-u only changes which escape lands in the text (ESC[106;5u instead), and withholding the extkeys terminal-feature stops a tmux asking its own parent for extended keys without stopping it encoding them for its pane.
With the guard in place all sixteen outer/inner version combinations paste correctly, and extended keys stay on everywhere except 3.5/3.5a.
The version test uses an awk END block rather than a bare exit, so that empty input — a tmux -V that failed for any reason — leaves extended keys on rather than silently disabling them. Verified against 3.3a, 3.4, 3.5a, 3.6b and 3.7c, plus the empty-input case, and the full config was re-parsed to confirm no syntax errors.
This also corrects the comment that attributed the corruption to a Claude Code paste-tokenizer bug. It reproduces just as readily pasting into neovim, and the earlier attempts looked exculpatory only because the setting has to be off on the layer doing the encoding.
**Summary generated by LLM agent**
Pasting multi-line text into a tmux session reached over ssh from inside another tmux (client → tmux → ssh → tmux) replaced every newline with a literal `CSI 27;5;106~`. That sequence is `C-j` — the pasted newline — rendered in modifyOtherKeys form rather than sent as a newline. The same paste through a single tmux (client → tmux → ssh) was fine.
## Cause
tmux 3.5 rewrote extended-key handling and encodes keys *inside a bracketed paste*. The layer further in passes those bytes through verbatim instead of decoding them, so the application receives the escape as text.
A hop only corrupts when whatever sits downstream of it has asked for modifyOtherKeys mode 2. A nested tmux always asks, because of the `*:extkeys` terminal-feature this config sets; an application running directly under `screen-256color` generally does not. That asymmetry is the whole reason one tmux in the chain worked and two did not — the extra tmux is itself a mode-2 requester.
## How it was verified
Built tmux 3.2a, 3.3a, 3.4, 3.5a, 3.6b and 3.7c from source, then drove a real bracketed paste through a pty into each chain and recorded the exact bytes the innermost application received. Only 3.5 and 3.5a corrupt, and only on the requesting hop:
| outer → inner | paste | outer → app | paste |
| --- | --- | --- | --- |
| 3.4 → 3.5a | BAD | 3.4 | OK |
| 3.5a → 3.5a | BAD | 3.5a | BAD |
| 3.5a → 3.7c | BAD | 3.6b | OK |
| 3.6b → 3.5a | BAD | 3.7c | OK |
| 3.6b → 3.6b | OK | | |
| 3.7c → 3.7c | OK | | |
Fixed upstream in 3.6, so upgrading is the real answer wherever that is available. Debian bookworm ships 3.3a and is unaffected; trixie and recent Ubuntu ship 3.5a and are.
## Change
For hosts pinned to a distro tmux, disable extended keys on exactly those two versions. Nothing narrower works, and both plausible alternatives were tested and rejected: `extended-keys-format csi-u` only changes which escape lands in the text (`ESC[106;5u` instead), and withholding the `extkeys` terminal-feature stops a tmux asking its *own parent* for extended keys without stopping it encoding them for its pane.
With the guard in place all sixteen outer/inner version combinations paste correctly, and extended keys stay on everywhere except 3.5/3.5a.
The version test uses an awk `END` block rather than a bare `exit`, so that empty input — a `tmux -V` that failed for any reason — leaves extended keys on rather than silently disabling them. Verified against 3.3a, 3.4, 3.5a, 3.6b and 3.7c, plus the empty-input case, and the full config was re-parsed to confirm no syntax errors.
This also corrects the comment that attributed the corruption to a Claude Code paste-tokenizer bug. It reproduces just as readily pasting into neovim, and the earlier attempts looked exculpatory only because the setting has to be off on the layer doing the encoding.
Pasting multi-line text into a tmux session reached over ssh from inside
another tmux replaced every newline with a literal CSI 27;5;106~, i.e.
C-j -- the pasted newline -- rendered in modifyOtherKeys form rather than
sent as a newline.
tmux 3.5 rewrote extended-key handling and encodes keys inside a
bracketed paste; the layer further in passes those bytes through verbatim
instead of decoding them, so the application receives the escape as text.
A hop only corrupts when whatever sits downstream of it has asked for
modifyOtherKeys mode 2. A nested tmux always asks, because of the
"*:extkeys" terminal-feature above it; an application running directly
under screen-256color generally does not. That is why one tmux in the
chain was fine and two were not.
Confirmed by building 3.2a, 3.3a, 3.4, 3.5a, 3.6b and 3.7c and driving a
real bracketed paste through a pty into every outer/inner combination:
only 3.5 and 3.5a corrupt, and only on the requesting hop. Fixed upstream
in 3.6, so upgrading is the real answer where it is available.
For hosts pinned to a distro tmux, disable extended keys on exactly those
two versions. Nothing narrower works: extended-keys-format csi-u only
changes which escape lands in the text, and withholding the extkeys
terminal-feature stops a tmux asking its own parent for extended keys
without stopping it encoding them for its pane. With the guard in place
all sixteen version combinations paste correctly, and extended keys stay
on everywhere except 3.5/3.5a.
The guard tests the version with an awk END block rather than a bare
exit, so that empty input -- a tmux -V that failed for any reason --
leaves extended keys on instead of silently disabling them.
Also corrects the comment that attributed this to a Claude Code paste
tokenizer bug. It reproduces just as readily pasting into neovim.
branderson
approved these changes 2026-08-17 14:27:51 -07:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary generated by LLM agent
Pasting multi-line text into a tmux session reached over ssh from inside another tmux (client → tmux → ssh → tmux) replaced every newline with a literal
CSI 27;5;106~. That sequence isC-j— the pasted newline — rendered in modifyOtherKeys form rather than sent as a newline. The same paste through a single tmux (client → tmux → ssh) was fine.Cause
tmux 3.5 rewrote extended-key handling and encodes keys inside a bracketed paste. The layer further in passes those bytes through verbatim instead of decoding them, so the application receives the escape as text.
A hop only corrupts when whatever sits downstream of it has asked for modifyOtherKeys mode 2. A nested tmux always asks, because of the
*:extkeysterminal-feature this config sets; an application running directly underscreen-256colorgenerally does not. That asymmetry is the whole reason one tmux in the chain worked and two did not — the extra tmux is itself a mode-2 requester.How it was verified
Built tmux 3.2a, 3.3a, 3.4, 3.5a, 3.6b and 3.7c from source, then drove a real bracketed paste through a pty into each chain and recorded the exact bytes the innermost application received. Only 3.5 and 3.5a corrupt, and only on the requesting hop:
Fixed upstream in 3.6, so upgrading is the real answer wherever that is available. Debian bookworm ships 3.3a and is unaffected; trixie and recent Ubuntu ship 3.5a and are.
Change
For hosts pinned to a distro tmux, disable extended keys on exactly those two versions. Nothing narrower works, and both plausible alternatives were tested and rejected:
extended-keys-format csi-uonly changes which escape lands in the text (ESC[106;5uinstead), and withholding theextkeysterminal-feature stops a tmux asking its own parent for extended keys without stopping it encoding them for its pane.With the guard in place all sixteen outer/inner version combinations paste correctly, and extended keys stay on everywhere except 3.5/3.5a.
The version test uses an awk
ENDblock rather than a bareexit, so that empty input — atmux -Vthat failed for any reason — leaves extended keys on rather than silently disabling them. Verified against 3.3a, 3.4, 3.5a, 3.6b and 3.7c, plus the empty-input case, and the full config was re-parsed to confirm no syntax errors.This also corrects the comment that attributed the corruption to a Claude Code paste-tokenizer bug. It reproduces just as readily pasting into neovim, and the earlier attempts looked exculpatory only because the setting has to be off on the layer doing the encoding.