Support OSC 52/5522 clipboard for image paste over SSH
Summary
Claude Code cannot paste images via Ctrl+V when running over SSH in a headless Linux VM. This is because Claude Code shells out to xclip to read the clipboard, but the VM has no display server (X11/Wayland), so xclip fails.
The fix: Claude Code should speak OSC 52 (text) and OSC 5522/Kitty clipboard protocol (images) directly, instead of shelling out to xclip. These escape sequences travel transparently through SSH — the user's terminal reads the local clipboard and responds.
Proof that it works
We built an xclip shim that speaks OSC 52/5522 and tested it end-to-end:
- ✅ Text clipboard via OSC 52 — works through SSH in Ghostty, iTerm2, Kitty
- ✅ Image clipboard via OSC 5522 — works through SSH in Kitty (
xclip -t image/png -o > file.pngproduces valid PNG) - ✅ TARGETS query — Claude Code discovers
image/pngis available and attempts to read it - ❌ Race condition — Claude Code spawns
xclipas a subprocess that reads from/dev/tty. But Claude Code (a TUI app) also reads from the terminal. The response bytes get split between the two readers.
The race condition is unfixable from a subprocess. Both Claude Code and the xclip subprocess read from the same PTY. The terminal's response goes to whichever process reads first.
Proposed solution
Instead of:
Ctrl+V → spawn xclip subprocess → xclip opens /dev/tty → race condition
Do:
Ctrl+V → Claude Code sends OSC 5522 query directly → reads response from its own terminal fd → no race
Claude Code already owns the terminal. It should send the escape sequence and read the response itself, in-process. No subprocess needed.
Protocol details
Detection (from $TERM):
xterm-kitty/kitty*→ OSC 5522 supported (images + text)- Others with OSC 52 support → text only
OSC 52 text read:
Send: ESC ] 52 ; c ; ? BEL
Response: ESC ] 52 ; c ; <base64 text> BEL
OSC 5522 image read (Kitty clipboard protocol):
Send: ESC ] 5522 ; type=read ; <base64("image/png")> ST
Response: ESC ] 5522 ; type=read:status=OK ST
ESC ] 5522 ; type=read:status=DATA:mime=<b64 mime>;<b64 chunk> ST
...more DATA packets...
ESC ] 5522 ; type=read:status=DONE ST
Chunks are ≤4096 bytes pre-encoding. Full spec: https://sw.kovidgoyal.net/kitty/clipboard/
Terminal support
| Terminal | OSC 52 (text) | OSC 5522 (images) |
|----------|:---:|:---:|
| Kitty | ✅ | ✅ |
| Ghostty | ✅ | PR in progress |
| iTerm2 | ✅ | ❌ |
| WezTerm | ✅ | ❌ |
Impact
This is a growing use case — remote AI coding (Claude Code, Codex, Copilot) over SSH. As more terminals adopt OSC 5522 (Ghostty PR is active), this becomes the standard way to forward clipboard over SSH.
References
- Kitty clipboard protocol spec: https://sw.kovidgoyal.net/kitty/clipboard/
- Ghostty OSC 5522 discussion: https://github.com/ghostty-org/ghostty/discussions/8275
- Ghostty image paste request: https://github.com/ghostty-org/ghostty/discussions/10099
- Ghostty SSH image paste request: https://github.com/ghostty-org/ghostty/discussions/10517
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗