Give remote Neovim the same clipboard behavior as local - #125
Open
dhh wants to merge 1 commit into
Open
Conversation
LazyVim empties 'clipboard' whenever SSH_CONNECTION is set, so a plain `y`
stayed in the unnamed register and never reached the OSC 52 provider this
package ships. Yanks in an SSH or tmux session simply never left the machine;
only an explicit `"+y` did. Upstream leaves the option empty so Neovim's own
OSC 52 autodetection can win, but that autodetection is irrelevant here since
this file assigns g:clipboard directly, and it is skipped inside tmux anyway.
Set 'unnamedplus' so yanking, deleting and putting reach the clipboard exactly
as they do locally. That puts the provider's paste path on every `p`, which the
old one could not carry:
- It answered a read with an OSC 52 query. Terminals and tmux mostly refuse
those, and Neovim blocks 1s, prints "Waiting for OSC 52 response...", then
blocks 9s more before giving up -- a 10s stall per put. Reads now use the
transport the session actually has: tmux's own clipboard request, wl-paste
where there is a display, and an OSC 52 query only when Neovim itself
detected support.
- `"+y` followed by `"+p` failed with E353 once a read could come back empty,
because nothing kept what was copied. Each register now retains its last
{ lines, regtype }, which answers a put when no clipboard can be read and
keeps linewise yanks linewise.
Copies inside tmux go through `tmux load-buffer -w -` so tmux emits the escape
sequence itself. The payload never crosses tmux's input parser, which discards
any sequence over input-buffer-size, 1 MiB by default.
Over SSH a read prefers the far end of the connection, since that is the
machine the person is sitting at. A box with its own display still gets every
copy through wl-copy, so both clipboards stay usable.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dhh
force-pushed
the
nvim-clipboard-parity
branch
from
August 7, 2026 22:08
e1078f9 to
47d31f2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
LazyVim empties
'clipboard'wheneverSSH_CONNECTIONis set:So a plain
ystayed in the unnamed register and never reached the OSC 52provider this package ships. In an SSH or tmux session yanks never left the
machine — only an explicit
"+ydid.Upstream leaves the option empty so Neovim's own OSC 52 autodetection can win,
gated on
&clipboard ==# ''inprovider/clipboard.vim. That gate isirrelevant here, because
remote_clipboard.luaassignsg:clipboarddirectlyand takes the explicit branch well before it — and inside tmux Neovim picks its
tmux provider instead, never reaching the OSC 52 branch at all. Two mechanisms
solving the same problem, each unaware of the other.
The fix
Set
'unnamedplus'so yanking, deleting and putting behave exactly as they dolocally. That puts the provider's paste path on every
p, which the old onecould not carry, so it grew two fixes:
Reads no longer stall. The old path answered every read with an OSC 52
query. Terminals and tmux mostly refuse those, and Neovim blocks 1s, prints
Waiting for OSC 52 response..., then blocks 9s more — a 10 second stall perput. Reads now use whatever transport the session has: tmux's own clipboard
request,
wl-pastewhere there is a display, and an OSC 52 query only whenNeovim itself flagged
termfeatures.osc52."+ythen"+pno longer fails withE353. Nothing kept what was copied,so a read that came back empty lost the text. Each register now retains its
last
{ lines, regtype }, which answers a put when no clipboard is readableand keeps linewise yanks linewise.
Copies inside tmux go through
tmux load-buffer -w -, so tmux emits the escapesequence itself and the payload never crosses tmux's input parser, which
discards any sequence over
input-buffer-size(1 MiB default).Over SSH a read prefers the far end of the connection, since that is the machine
the person is sitting at. A box with its own display still receives every copy
via
wl-copy, so both clipboards stay usable.Behavior change worth calling out
'unnamedplus'routes deletes and changes through the clipboard too, soddand
xnow overwrite the host clipboard and, in shared tmux, reach everyattached client. That is what local behavior is, but it is new for remote
sessions and means ordinary editing exports text off the machine.
One parity gap remains:
wl-copy --sensitivekeeps clipboard managers fromrecording these values, while a purely local Neovim uses the built-in provider
without that flag. Dropping it would complete the parity but reverses a
deliberate choice, so it is left alone here.
Existing installs are updated by a migration in
basecamp/omarchy, whichreinstalls the provider from
/usr/share/omarchy-nvim/config. That migrationneeds to ship alongside this package bump —
omarchy updateruns packagesfirst, then migrations.
— 🤖 Claude, posting on behalf of @dhh