clipaste

Rust · MIT · macOS & Windows · v2.4.1

Screenshot paste is broken in terminal AI tools.

You crop a screenshot, switch to Claude Code, press Ctrl+V, and nothing arrives. Over SSH it is worse: the remote has no idea your clipboard exists. clipaste is a 9 MB daemon that closes both gaps.

Then clipaste doctor tells you whether it worked, and what to run if it did not.

before → after, on loop

Why Ctrl+V does nothing

the clipboard

A macOS screenshot puts raw image bytes on the pasteboard — TIFF or PNG data, and nothing else. No file. No path. Just pixels sitting in memory.

the terminal

Ghostty, Alacritty and friends can paste text and file paths into the program they host. They have no mechanism for handing raw image bytes through. The keystroke arrives empty.

the ssh boundary

A remote shell has no access to your local clipboard whatsoever. There is nothing to paste, so tools fall back to inserting your local file path as literal text.

what clipaste does instead

It watches the clipboard. The moment a screenshot lands, it writes the bytes to a temporary PNG and puts that file's path on the clipboard next to the image data — something a terminal can pass through. The same PNG is served on 127.0.0.1:18340, so a remote that can reach that port through an SSH tunnel can fetch the picture instead of a path that means nothing to it.

Three places it works

On your own machine

Install, and paste. Nothing to configure.

« Cmd+Shift+4 to crop a screenshot »
$ claude
 what's wrong with this layout?  ^V
  ▸ [Image #1 attached]

On an SSH remote

Run setup once from the machine holding the clipboard, then reconnect.

« on your Mac »
$ clipaste ssh-setup dev@build-07
  [1/3] Checking local clipaste server... OK
  [2/3] Installing helper on dev@build-07... OK (Linux)
  [3/3] Configuring SSH RemoteForward... OK

« in a NEW session on build-07 »
$ claude
 why is this test flaky?  ^V
  ▸ [Image #1 attached]

Inside WSL2

No tunnel needed. Setup probes for the Windows host rather than trusting DNS config, so mirrored and NAT networking both work.

$ clipaste wsl-setup
  [1/2] Locating clipaste on the Windows host...
        127.0.0.1 (mirrored-mode loopback)
  [2/2] Installing xclip/wl-paste shims... OK

Codex CLI is the exception, and worth saying plainly: it reads the clipboard in-process through arboard, so it never runs the shim and cannot be intercepted. On a remote, run clipaste-paste — it writes the image to a real file there and prints the path for you to hand over.

Built to be installed by an agent

Which half of clipaste you need depends on which side of the bridge you are on — and the answer is not uname. An SSH session into a Mac is a remote, not a clipboard host. A human infers that from context; an agent guesses, installs the wrong half, and reports success. So clipaste answers the question directly.

$ clipaste doctor --json
{
  "role": "ssh-remote",
  "status": "fail",
  "checks": [
    { "name": "helper",
      "status": "ok",
      "fix": null },
    { "name": "bridge",
      "status": "fail",
      "fix": "reconnect: the SSH
        RemoteForward is only active
        inside a session opened
        after ssh-setup" }
  ]
}
  • Every check carries a fix. Not a hint — a literal command the agent can run.
  • Roles, not platforms. clipboard-host, ssh-remote, wsl2. Only the relevant checks run.
  • Warnings exit 0. "No screenshot staged yet" is a fresh install, not a fault. An agent that treats it as one loops forever.
  • Failure modes stay distinct. Helper missing, helper not on PATH, shim shadowed by the real xclip, tunnel down — four different reds, four different fixes.
  • Setup is non-interactive and idempotent. Safe to run unattended, safe to run twice.

The repository carries an AGENTS.md with the full recipe: which side installs what, the per-tool paste gesture table, and the things not to do — such as binding the daemon to 0.0.0.0 to "fix" connectivity, when the bytes on that port are the user's screen contents.

What works where

Paste gesture by tool and location. helper = run clipaste-paste, then hand over the printed path.
AI toolLocalSSH → LinuxSSH → macOSWSL2
Claude CodeCtrl+VCtrl+VhelperCtrl+V
Cursor CLICtrl+VCtrl+VhelperCtrl+V
Codex CLICtrl+Vhelperhelperhelper
Terminals verified on the clipboard host.
TerminalmacOS Cmd+VmacOS Ctrl+VWindows Ctrl+V
Ghosttyyesyes
Alacrittyyesyes
iTerm2yesyes
Terminal.appyesyes
WezTermyesyesyes
Kittyyesyesyes
Windows Terminalyes

Questions people actually ask

Why does Ctrl+V do nothing when I paste a screenshot into Claude Code?

A macOS screenshot puts only raw image data on the clipboard — TIFF or PNG bytes. Terminals such as Ghostty and Alacritty can paste text and file paths, but they have no way to hand raw image bytes to the program running inside them, so the keystroke reaches the AI tool carrying nothing. clipaste writes the screenshot to a temporary PNG and puts that file's path on the clipboard alongside the image data, which is something a terminal can pass through.

Can I paste screenshots into Claude Code running on a remote server over SSH?

Yes. Run clipaste ssh-setup user@host from the machine holding the clipboard. It installs an xclip shim on the remote and adds an SSH RemoteForward to your ~/.ssh/config, so the remote fetches the image back through the tunnel. Open a new SSH session afterwards, then press Ctrl+V. Never press Cmd+V in an SSH session: that sends your local file path as text, and the remote agent cannot open a path that does not exist there.

Why can't Codex CLI paste images over SSH the way Claude Code can?

Codex CLI reads the clipboard in-process through the arboard crate, which talks to X11 or Wayland directly and never runs the xclip binary. It therefore bypasses the shim clipaste installs, and there is no environment variable to redirect it. clipaste ships clipaste-paste instead: run it on the remote, and it writes the current clipboard image to a real file there and prints the path. Hand that path to Codex and it attaches the image.

Does clipaste work in WSL2?

Yes. Run clipaste wsl-setup inside the distro while clipaste.exe runs on Windows. Setup probes several candidate addresses for the Windows host and keeps the first that answers, so networkingMode=mirrored (host reachable at 127.0.0.1) and the default NAT mode both work. Under mirrored networking with DNS tunnelling the /etc/resolv.conf nameserver is a virtual DNS endpoint rather than the host — which is exactly why probing beats reading DNS config.

How does a coding agent install and verify clipaste without guessing?

Run clipaste doctor --json. It classifies the machine as clipboard-host, ssh-remote or wsl2, runs only the checks meaningful for that role, and returns each check as name, status, detail and fix — where fix is a literal command. Exit code is 0 when usable, 1 when broken, 2 on bad arguments.

How much memory and CPU does clipaste use?

About 9 MB resident, and no measurable CPU when idle. It is Rust with no runtime dependencies beyond the OS clipboard APIs. On macOS it watches the pasteboard change counter on a timer; on Windows it is fully event-driven through AddClipboardFormatListener, so it does not poll at all.

Does clipaste send my screenshots anywhere?

No. The HTTP server binds to 127.0.0.1 only and is never exposed to the network. Reaching it from an SSH remote requires a tunnel you set up yourself; reaching it from WSL2 requires mirrored networking, where loopback is shared with the Windows host. Screenshots are written to a local cache directory and cleaned up after an hour.

Is clipaste free and open source?

Yes — MIT licensed, source at github.com/hqhq1025/clipaste. It is a single Rust binary of roughly 1,600 lines: the macOS pasteboard watcher, the Windows clipboard listener, the loopback HTTP server, and the SSH and WSL setup commands.

Take a screenshot. Press paste. It arrives.