Copy in Lazygit when using SSH

Copy in Lazygit when using SSH

When using Lazygit on a headless server (no screen, no X11/Wayland) over SSH, pressing y to copy (e.g. copying a commit hash, file name…) will produce this error:

Error
write |1: broken pipe

Root cause

Lazygit copies data to the clipboard by calling an external system clipboard program such as xclip, xsel (X11) or wl-copy (Wayland), then writes the data into that program’s stdin.

On a headless server:

  • There is no $DISPLAY or $WAYLAND_DISPLAY environment variable.
  • The xclip/xsel/wl-copy commands cannot connect to a display server, so they exit immediately.
  • Lazygit still tries to write data into the stdin of the already-exited process → the pipe is closed → error write |1: broken pipe.

Solution: use OSC 52

OSC 52 is an escape sequence that allows a program inside a terminal to send data straight into the local machine’s clipboard (the machine you SSH from), without needing a clipboard backend on the server. It is supported by modern terminals: iTerm2, kitty, WezTerm, Windows Terminal, newer Alacritty, and more.

Step 1 — Find the config directory

lazygit -cd

(prints the config directory, e.g. /root/.config/lazygit)

Step 2 — Write the OSC 52 config into config.yml

cat > "$(lazygit -cd)/config.yml" << 'EOF'
os:
  copyToClipboardCmd: "printf '\x1b]52;c;%s\a' \"$(cat {{filename}} | base64 | tr -d '\n')\""
EOF

Important note: use \x1b (hex escape) and not \033 (octal escape). YAML only supports hex/unicode escapes, not octal. If you use \033, YAML will misinterpret it as the character \0 (NUL) followed by 33, inserting a null byte into the command string, causing Go’s exec to fail:

fork/exec /bin/bash: invalid argument

(because the command string contains a NUL byte — which C strings / exec do not permit).

Step 3 — Restart Lazygit and try copying

Open Lazygit again, press y on the commit or file you want to copy. The content will be sent directly to your local machine’s clipboard via the terminal.

Notes for tmux/screen users

If you run Lazygit inside tmux, the OSC 52 escape sequence may be blocked in transit. Enable:

set -g set-clipboard on

in ~/.tmux.conf, or configure pass-through separately depending on your tmux version.

Notes for Herdr users

Herdr is a terminal workspace manager for AI coding agents, and it also acts as an intermediate terminal layer. When Lazygit runs inside Herdr, the OSC 52 sequence must pass through Herdr before being forwarded to the host’s real terminal.

This is a known bug in Herdr itself (issue #2399): when copying content from an application running inside Herdr, the “copied to clipboard” message still appears, but the content does not actually reach the system clipboard — pasting (Ctrl+V) still shows the old content. This bug only occurs when Herdr runs in default (local) mode; when running with herdr --remote, clipboard works normally.

Workaround: start Herdr with the --remote flag:

herdr --remote

The copyToClipboardCmd configuration in Lazygit (as described above) is still correct and necessary — the issue lies in Herdr not forwarding OSC 52 to the outer terminal when running locally, not in Lazygit or the YAML config.

Summary

Error / Symptom Root cause
write |1: broken pipe No clipboard backend (xclip/wl-copy) on a headless server — no display server
fork/exec /bin/bash: invalid argument Using \033 (octal) in a YAML double-quoted string → NUL byte in the command string, Go exec rejects it
Copy reports success but host clipboard doesn’t receive it Running inside Herdr in local mode — Herdr doesn’t forward OSC 52 to the outer terminal (needs herdr --remote)

General solution: configure copyToClipboardCmd to use OSC 52 (\x1b]52;c;...) to send clipboard data through the terminal, independent of GUI/display server on the remote machine.