From d417a27f2dcbc3f1025f8e924566d5f0e0ecf86b Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Tue, 18 Aug 2026 08:14:17 +0100 Subject: [PATCH] feat: make the clipboard work across tmux, ssh and hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tmux copy bindings piped to xclip, which is X11-only and never worked under Hyprland or over SSH, and set-clipboard was never enabled, so the vi-mode `y` binding was dead too. Route both through OSC 52 instead. terminal-features has to name the outer terminal explicitly: tmux skips OSC 52 silently when the terminfo entry does not claim the capability, which is the common case for an SSH session on xterm-256color. Neovim only falls back to OSC 52 when it finds no clipboard tool, but wl-clipboard is installed on every host, so over SSH it wrote the remote clipboard. Pin the OSC 52 provider for SSH sessions only. Moonlight and Sunshine have no clipboard channel in the protocol, so nothing at the terminal layer can help there. Add kdeconnect on all three hosts for that, and start its indicator from Hyprland — kdeconnectd is DBus-activated and nothing else brings it up at login. Co-Authored-By: Claude Opus 5 (1M context) --- home/common/programs/hyprland/default.nix | 3 +++ home/common/programs/neovim/default.nix | 9 +++++++++ home/common/programs/tmux.conf | 22 +++++++++++++++++++--- hosts/arrakis/default.nix | 1 + hosts/common/features/kdeconnect.nix | 10 ++++++++++ hosts/konishi/default.nix | 1 + hosts/yolo/default.nix | 1 + 7 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 hosts/common/features/kdeconnect.nix diff --git a/home/common/programs/hyprland/default.nix b/home/common/programs/hyprland/default.nix index fca6131..22b7843 100644 --- a/home/common/programs/hyprland/default.nix +++ b/home/common/programs/hyprland/default.nix @@ -219,6 +219,9 @@ in hl.exec_cmd("hyprctl setcursor Nordzy-cursors ${toString cfg.cursorSize}") hl.exec_cmd("hyprsunset") hl.exec_cmd("noctalia") + -- kdeconnectd is only DBus-activated; nothing starts it at login, + -- so clipboard sync stays dead until the indicator runs. + hl.exec_cmd("kdeconnect-indicator") end) -- layer rules diff --git a/home/common/programs/neovim/default.nix b/home/common/programs/neovim/default.nix index 089e7e8..7a3abe9 100644 --- a/home/common/programs/neovim/default.nix +++ b/home/common/programs/neovim/default.nix @@ -12,5 +12,14 @@ programs.nvchad = { enable = true; + + # Neovim only auto-picks OSC 52 when it finds no clipboard tool, but + # wl-clipboard is on every host — so over SSH it writes the *remote* + # clipboard instead. Locally wl-copy stays: kitty refuses OSC 52 reads. + extraConfig = '' + if vim.env.SSH_TTY and vim.env.SSH_TTY ~= "" then + vim.g.clipboard = "osc52" + end + ''; }; } diff --git a/home/common/programs/tmux.conf b/home/common/programs/tmux.conf index d0deef9..fb194d9 100644 --- a/home/common/programs/tmux.conf +++ b/home/common/programs/tmux.conf @@ -101,6 +101,20 @@ setw -g mode-keys vi bind -T copy-mode-vi v send -X begin-selection bind -T copy-mode-vi y send -X copy-selection-and-cancel +# ------------------------------------------------------------------- +# Clipboard (OSC 52) +# ------------------------------------------------------------------- +set -g set-clipboard on + +# tmux silently skips OSC 52 unless the outer terminal's terminfo claims the +# capability. kitty's does; SSH sessions usually land on a bare +# xterm-256color that does not, so declare both. +set -ag terminal-features ",xterm-kitty:clipboard" +set -ag terminal-features ",xterm-256color:clipboard" + +# Let nvim's OSC 52 provider reach the outer terminal through tmux. +set -g allow-passthrough on + # tmux-resurrect settings set -g @resurrect-capture-pane-contents 'on' @@ -142,7 +156,9 @@ bind-key -T copy-mode-vi WheelDownPane send-keys -X scroll-down bind-key -T copy-mode WheelUpPane send-keys -X scroll-up bind-key -T copy-mode WheelDownPane send-keys -X scroll-down -# Clipboard integration (drag-to-copy) -bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -in -selection clipboard" -bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -in -selection clipboard" +# Clipboard integration (drag-to-copy). No external command: set-clipboard +# above routes this through OSC 52, which works on Wayland and over SSH. +# xclip did neither. +bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel +bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel # End agent-deck configuration diff --git a/hosts/arrakis/default.nix b/hosts/arrakis/default.nix index 696727a..c003706 100644 --- a/hosts/arrakis/default.nix +++ b/hosts/arrakis/default.nix @@ -17,6 +17,7 @@ ../common/features/docker.nix ../common/features/appimage.nix ../common/features/fonts.nix + ../common/features/kdeconnect.nix ../common/features/nix-ld.nix ../common/features/bluetooth.nix ../common/features/ledger.nix diff --git a/hosts/common/features/kdeconnect.nix b/hosts/common/features/kdeconnect.nix new file mode 100644 index 0000000..0cda8fc --- /dev/null +++ b/hosts/common/features/kdeconnect.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: +{ + # Clipboard (and file) sync between hosts over the LAN. Moonlight/Sunshine + # carry no clipboard channel at all, so this is the only path between the + # streaming client and its host. + programs.kdeconnect = { + enable = true; + package = pkgs.kdePackages.kdeconnect-kde; + }; +} diff --git a/hosts/konishi/default.nix b/hosts/konishi/default.nix index 445cb26..a294364 100644 --- a/hosts/konishi/default.nix +++ b/hosts/konishi/default.nix @@ -13,6 +13,7 @@ ../common/features/pipewire.nix ../common/features/docker.nix ../common/features/fonts.nix + ../common/features/kdeconnect.nix ../common/features/nix-ld.nix ../common/features/bluetooth.nix ../common/features/ledger.nix diff --git a/hosts/yolo/default.nix b/hosts/yolo/default.nix index 482f20f..e02e193 100644 --- a/hosts/yolo/default.nix +++ b/hosts/yolo/default.nix @@ -14,6 +14,7 @@ ../common/features/remote-desktop.nix ../common/features/docker.nix ../common/features/fonts.nix + ../common/features/kdeconnect.nix ../common/features/nix-ld.nix ../common/features/appimage.nix ../common/features/home