clipaste
hqhq1025/clipaste/docs/llms-full.txt
Homepage: https://hqhq1025.github.io/clipaste/ Source: https://github.com/hqhq1025/clipaste License: MIT Version: 2.6.0 Language: Rust Author: Haoqing Wang (https://github.com/hqhq1025) clipaste is a clipboard daemon that makes screenshot paste work in terminal-based AI coding tools — Claude Code, Codex CLI and Cursor CLI — on macOS and Windows, and bridges the clipboard to SSH remotes and WSL2 environments. Graphical Linux hosts also serve clipboard PNG images over SSH through a read-only backend. The existing macOS/Windows footprint is about 9 MB with no measurable idle CPU; this…
- Reads credentials
- Installs packages
# clipaste — full reference
Homepage: https://hqhq1025.github.io/clipaste/
Source: https://github.com/hqhq1025/clipaste
License: MIT
Version: 2.6.0
Language: Rust
Author: Haoqing Wang (https://github.com/hqhq1025)
---
## What clipaste is
clipaste is a clipboard daemon that makes screenshot paste work in terminal-based AI
coding tools — Claude Code, Codex CLI and Cursor CLI — on macOS and Windows, and bridges
the clipboard to SSH remotes and WSL2 environments. Graphical Linux hosts also serve
clipboard PNG images over SSH through a read-only backend. The existing macOS/Windows
footprint is about 9 MB with no measurable idle CPU; this is not a Linux measurement,
since Linux polls and invokes system clipboard tools.
---
## The problem, precisely
Three separate failures are usually reported as one:
1. **The clipboard carries the wrong shape of data.** A macOS screenshot places raw image
bytes on the pasteboard — TIFF or PNG data. There is no file on disk and no path.
2. **The terminal cannot pass image bytes through.** Ghostty, Alacritty, iTerm2 and
similar terminals can paste text and file paths into the program they host. They have
no mechanism for handing raw image bytes to that program. Pressing Ctrl+V sends
nothing, so the AI tool reports "no image detected".
3. **An SSH remote has no clipboard at all.** The remote machine cannot see your local
pasteboard. Tools fall back to inserting your local file path as literal text, and the
remote agent cannot open a path that does not exist on its filesystem.
---
## How clipaste solves it
Locally on macOS/Windows, a background daemon watches the clipboard. When a
screenshot appears, it writes the bytes to a PNG file and adds its path alongside
the original image data. On macOS, a file path is something the terminal can pass
through, so Cmd+V works; the retained image data plus a legacy PNGf pasteboard type
keeps Ctrl+V image paste working for tools that read the clipboard directly.
On Linux, the daemon reads clipboard `image/png` into a private stable PNG cache
without taking clipboard ownership or adding file URLs/text. The pipeline is
clipboard PNG -> cache -> existing loopback HTTP -> SSH shims / `clipaste-paste`.
It does not promise local terminal text-path paste. Copying an image file that
offers only a URI is not supported yet; copy image pixels or a screenshot.
Existing macOS/Windows clipboard behavior and paste workflows are unchanged.
**Over SSH.** The daemon also runs an HTTP server bound to `127.0.0.1:18340` serving three
endpoints: `/health`, `/clipboard/type` and `/clipboard/image`. `clipaste ssh-setup`
installs an `xclip`/`wl-paste` shim on the Linux remote and adds
`RemoteForward 18340 127.0.0.1:18340` to the local `~/.ssh/config`. When Claude Code on
the remote shells out to `xclip`, the shim answers from the tunnel instead. The image
never leaves loopback except through the user's own SSH connection.
**In WSL2.** No tunnel is needed; WSL reaches the Windows host directly. `clipaste
wsl-setup` installs the same shims inside the distro, pointed at clipaste.exe on Windows.
**Server-only mode.** With `CLIPASTE_SERVER_ONLY=1` in the daemon's environment,
macOS and Windows stage and serve images exactly as above but never rewrite the
local clipboard, so GUI apps keep pasting the original image. On Windows the
default rewrite removes `CF_DIB`, which is why apps such as Slack or Word paste a
path there. Local terminals get no path in this mode. `brew services` cannot pass
the variable, so macOS needs a user LaunchAgent with `EnvironmentVariables`; on
Windows, `setx CLIPASTE_SERVER_ONLY 1` survives reinstalls. Only `1` enables it;
`0` or unset keeps the default, and other values stop the daemon at startup.
Linux never modifies the clipboard, so the variable changes nothing there.
---
## Commands
```
clipaste Run the daemon (macOS / Windows / graphical Linux)
clipaste doctor [--json] Diagnose this machine and print the fix command
clipaste ssh-setup user@host Configure an SSH remote (add -p PORT for a custom SSH port)
clipaste wsl-setup Configure WSL2 (add --host IP to skip host auto-detection)
clipaste --version
clipaste --help
```
`ssh-setup` and `wsl-setup` also install a `clipaste-paste` command on the target: it
fetches the current clipboard image into a real file on that host and prints the path.
---
## Installing
### Supported hosts and consumers
The clipboard-host daemon runs on macOS, Windows, and graphical Linux with usable
clipboard access. Linux support depends on the compositor and source application;
universal desktop compatibility has not been tested.
| OS / context | Local clipboard-host daemon | Consumer of another host's clipboard |
|---|---|---|
| macOS | Supported | SSH remote via `clipaste-paste` |
| Windows | Supported | Via WSL2 |
| Native Linux desktop | Read-only PNG via Wayland data-control or X11/XWayland | Supported over SSH via shims / `clipaste-paste` |
| Headless Linux | No display; host startup fails with guidance | Supported with configured helpers / SSH |
| WSL2 | No; the Windows daemon is required | Supported via `wsl-setup` |
Linux consumer shims fetch images from a macOS, Windows, or graphical Linux
host daemon. The Linux host resolves real system clipboard tools, not the
generated HTTP shims. On macOS remotes, use `clipaste-paste`.
macOS (Homebrew):
```bash
brew install hqhq1025/clipaste/clipaste
brew services start clipaste
```
Windows (PowerShell, no administrator rights required):
```powershell
irm https://raw.githubusercontent.com/hqhq1025/clipaste/main/install.ps1 | iex
```
The Windows installer downloads the latest release into `%LOCALAPPDATA%\clipaste`, adds it
to the user PATH, registers an `HKCU\...\Run` auto-start entry, and launches the daemon.
Linux desktop (releases since v2.5.0 include static x86_64 and ARM64 binaries):
```bash
sudo apt install wl-clipboard xclip curl
```
Download `clipaste-v2.6.0-x86_64-unknown-linux-musl.tar.gz` for x86_64 or
`clipaste-v2.6.0-aarch64-unknown-linux-musl.tar.gz` for ARM64 from
https://github.com/hqhq1025/clipaste/releases/tag/v2.6.0. Verify the archive
against the release's `SHA256SUMS`, extract it, then install the binary:
```bash
install -Dm755 clipaste "$HOME/.local/bin/clipaste"
export PATH="$HOME/.local/bin:$PATH"
clipaste
```
Keep `~/.local/bin` on your shell's `PATH`. Run
`clipaste` as the desktop user in a graphical-session terminal and leave it
running. No Linux service or automatic startup is installed. Stop with Ctrl+C;
restart from the same graphical session. In a separate desktop terminal:
```bash
clipaste doctor --json
clipaste ssh-setup user@your-server
```
Copy a screenshot as image data and re-run `doctor`; an empty clipboard warning
before copying is normal. Open a new SSH session and verify the fetched image
with `clipaste-paste` or a supported shim-based paste gesture.
To install from source with Rust/Cargo, use
`cargo install --git https://github.com/hqhq1025/clipaste --tag v2.6.0 --locked`
and put Cargo's binary directory (normally `~/.cargo/bin`) on `PATH`.
Linux still requires the distro tools and graphical-session access above.
For development, run `cargo build --release` in the checkout. Linux builds
retain diagnostics and consumer setup commands, including `wsl-setup`; WSL2
remains a Windows consumer.
### Linux backend selection
| `CLIPASTE_BACKEND` | Behavior |
|---|---|
| `auto` (default) | Prefer native Wayland data-control; otherwise use system `xclip` through `DISPLAY`, explicitly warning when falling back from Wayland to XWayland |
| `wayland` | Require system `wl-paste` with usable data-control access as described below; fail instead of falling back |
| `x11` | Require system `xclip` and an accessible `DISPLAY`, using X11 or the compositor's XWayland clipboard bridge |
Native Wayland requires `wl-clipboard >=2.2` for empty-selection watch events.
All Wayland clipboard accesses use `wl-paste --watch` in bounded one-shot mode,
which refuses popup fallback and verifies actual compiled-in data-control
support. Ext-only compositors need `wl-clipboard >=2.3` built with
`ext-data-control` support; `wlr-data-control` works with compatible 2.2+ builds.
With 2.1.x or unavailable data-control, `auto` warns and falls back to XWayland
through system `xclip` and an accessible `DISPLAY`; without that, it fails with
guidance to upgrade or use an X11 session. No forced-focus polling is used.
No display fails with guidance to start from a graphical desktop or configure
a consumer instead.
For an explicit backend, start `CLIPASTE_BACKEND=x11 clipaste`, then run
`CLIPASTE_BACKEND=x11 clipaste doctor --json` in a separate terminal. Keep the
override and desktop environment consistent across both processes.
GNOME Wayland may need the XWayland clipboard bridge. Reporters must test a
screenshot copied from a native Wayland app, inspect `doctor`, and verify the
actual image fetched on the remote. An X11-only clipboard test does not establish
native Wayland compatibility, and backend detection alone is not an end-to-end
test. Record the compositor/session, source app, backend, and diagnostic result
when reporting compatibility.
Linux polls every 300 ms and only reads `image/png`. Clipboard clears, non-image
content, and recognized private markers clear the staged image served over HTTP.
Historical cached paths are retained; clearing the clipboard does not erase the cache.
### Opt-in Linux desktop verification
Run `bash tests/linux/run.sh` from the repository root on Linux. It runs unit
tests, strict Clippy, and real clipboard/HTTP smoke tests in isolated Xvfb and
headless Sway sessions. Temporary HOME/cache/runtime directories keep test state
separate; the tests do not use the real user's clipboard. See `AGENTS.md` for
distro prerequisites and the existing `tests/linux/Dockerfile` container recipe.
Direct runs require loopback port `18340` to be free. Passing isolated tests does
not establish GNOME/ext-only compatibility or replace native-app screenshot tests.
---
## SSH remote setup, in detail
Run on the local macOS, Windows, or graphical Linux clipboard host with its daemon
running, not on the remote consumer:
```bash
clipaste ssh-setup user@your-server
clipaste ssh-setup user@your-server -p 22222 # custom SSH port
```
The command:
- verifies the local daemon is answering on `127.0.0.1:18340`
- detects the remote OS with `uname -s` in a single SSH round trip
- on a Linux remote, installs `~/.local/bin/xclip` and `~/.local/bin/wl-paste` shims
- on every remote, installs `~/.local/bin/clipaste-paste`
- ensures `~/.local/bin` is on PATH, creating the login shell's rc file if none exists
- adds `RemoteForward 18340 127.0.0.1:18340` (and `Port` when `-p` was given) to the
matching host block in `~/.ssh/config`, without duplicating or overriding existing
directives
The `RemoteForward` only exists in SSH sessions opened *after* the config change, so the
user must reconnect before pasting.
On a **macOS remote**, the xclip shims are deliberately not installed: nothing on macOS
shells out to xclip, so the shims would be dead code. `clipaste-paste` is the supported
path there.
---
## WSL2 setup, in detail
Run inside the WSL2 distro with clipaste.exe already running on Windows:
```bash
clipaste wsl-setup
clipaste wsl-setup --host 127.0.0.1 # skip auto-detection
```
Host detection probes candidate addresses and keeps the first that actually serves
`/health`:
| WSL networking mode | Windows host reachable at | Why |
|---|---|---|
| `mirrored` | `127.0.0.1` | WSL shares the host's network interfaces, including loopback |
| `nat` (default) | the vEthernet gateway | usually the `/etc/resolv.conf` nameserver; read from the routing table when DNS tunnelling replaces it |
Detection order is decided by `wslinfo --networking-mode` when that tool is available, but
every candidate is probed regardless, so an older WSL without `wslinfo` still lands on the
right address. Under `networkingMode=mirrored` with `dnsTunneling=true`, the resolv.conf
nameserver is a virtual DNS endpoint (typically `10.255.255.254`) and is *not* the host —
which is why probing beats reading DNS configuration.
clipaste binds to `127.0.0.1` on Windows. NAT-mode WSL cannot reach a loopback-bound
service on the host. The supported fix is `networkingMode=mirrored` in
`%USERPROFILE%\.wslconfig` (Windows 11 22H2 and later). Where mirrored mode is
unavailable, forward the port on the Windows side with `netsh interface portproxy`.
---
## Paste gestures
| Tool | Local (macOS / Windows) | SSH → Linux | SSH → macOS | WSL2 |
|---|---|---|---|---|
| Claude Code | Ctrl+V | Ctrl+V | `clipaste-paste` | Ctrl+V |
| Cursor CLI | Ctrl+V | Ctrl+V | `clipaste-paste` | Ctrl+V |
| Codex CLI | Ctrl+V | `clipaste-paste` | `clipaste-paste` | `clipaste-paste` |
On macOS locally, Cmd+V also works — that is the case the file-path trick was built for.
It needs the default mode; with `CLIPASTE_SERVER_ONLY=1` no path is added.
The local column does not apply to Linux hosts. Linux adds no clipboard text or
file URLs; its supported host workflow supplies PNG images to remote consumers.
**Codex CLI is the standing exception.** It reads the clipboard in-process through the
`arboard` crate, which talks to X11 or Wayland directly and never executes the `xclip`
binary. There is no environment variable or external-command hook to redirect it, so a
shim cannot intercept it. `clipaste-paste` writes the image to a real file on the current
host and prints the path; hand that path to Codex and it attaches the image.
**Never press Cmd+V in an SSH session.** It transmits your local file path as text. The
remote agent will read it as a string and fail to open it.
---
## Diagnostics for coding agents
```bash
clipaste doctor --json
```
```json
{
"version": "2.4.1",
"os": "linux",
"role": "ssh-remote",
"status": "fail",
"checks": [
{ "name": "helper", "status": "ok", "detail": "~/.local/bin/clipaste-paste", "fix": null },
{ "name": "bridge", "status": "fail",
"detail": "http://127.0.0.1:18340 is not answering",
"fix": "reconnect: the SSH RemoteForward is only active inside a session opened after ssh-setup" }
]
}
```
Contract:
- `role` is `clipboard-host`, `ssh-remote`, `wsl2`, or `unsupported-host`, and
decides which checks run. `unsupported-host` is an extension of the role
contract; callers must accept the additional value.
- Detection order is WSL context, then SSH session, then a local macOS/Windows
host or graphical Linux session. WSL stays a Windows consumer even with SSH
or display variables. Actual SSH sessions remain `ssh-remote`, including SSH
into macOS or graphical Linux. Graphical local Linux is `clipboard-host`;
headless Linux with a configured consumer helper remains `ssh-remote` even
without SSH variables, so helper and bridge checks still run.
- `status` is the worst of all checks: `ok`, `warn` or `fail`.
- `checks[].fix` is a remediation command or guidance, or `null` when no single
command applies.
- Exit code is `0` when usable (including warnings), `1` when broken, `2` on bad arguments.
- A `warn` is not a failure. "No screenshot staged yet" is the normal state of a fresh
install; treating it as a fault causes an agent to loop.
- On a clipboard host, the `daemon` check detail contains `server-only` when the
running daemon has `CLIPASTE_SERVER_ONLY=1`. Local terminals then get no file
path by design. Daemons from v2.5.0 and earlier ignore the variable.
`unsupported-host` remains in the contract for platforms without a backend; it
is not a blanket Linux classification. Linux without a display or consumer
configuration gets `clipboard-host` diagnostics with a failing `backend` check
and actionable graphical-session guidance. Missing distro tools, inaccessible
displays, and absent Wayland data-control need distinct remedies; adding a
service or installing `curl` does not supply desktop access.
Run Linux host diagnostics as the same desktop user and in the same session as
the daemon. Wayland requires the session's `WAYLAND_DISPLAY` and `XDG_RUNTIME_DIR`;
X11/XWayland requires `DISPLAY` and display authorization. Use the same
`CLIPASTE_BACKEND` override. SSH shells, `sudo`, stale tmux sessions, and services
can lack the required environment. Setting a display variable alone does not
establish or authorize a connection.
To consume another host's clipboard on Linux, run `ssh-setup` on that macOS,
Windows, or graphical Linux host with its daemon running, then open a new SSH
session. WSL2 still requires the Windows daemon and `wsl-setup` in the distro.
Checks distinguish failure modes that look identical from outside: helper missing, helper
installed but not on PATH, shim shadowed by the real `xclip`, tunnel down, and a stale
daemon still owning the port after an upgrade.
The repository also ships an `AGENTS.md` with the full install recipe, a diagram of which
side installs what, the paste-gesture table, and the actions an agent should not take —
notably binding the daemon to `0.0.0.0` to "fix" connectivity, when the bytes served on
that port are the user's screen contents.
---
## Compatibility
Terminals on the clipboard host: Ghostty, Alacritty, iTerm2, Terminal.app, WezTerm and
Kitty on macOS; Windows Terminal, PowerShell and cmd.exe on Windows. WezTerm and Kitty
also cover Windows Ctrl+V.
Consumers: Linux servers reachable over SSH with `curl`, backed by a macOS or
Windows clipboard host or a graphical Linux host with usable clipboard access.
WSL2 distros including Ubuntu, Debian, Fedora, Arch and
Kali require the Windows daemon. macOS remotes are supported through
`clipaste-paste`. Linux hosting is read-only PNG capture, not local terminal
text-path paste. GNOME Wayland may require a working XWayland clipboard bridge;
test native-app screenshots rather than assuming universal compatibility.
Linux verification is not a substitute for macOS/Windows regression checks.
---
## Privacy and security
- The HTTP server binds to `127.0.0.1` and is never exposed on a network interface.
- Reaching it from an SSH remote requires an SSH RemoteForward tunnel the user sets up.
- Reaching it from WSL2 requires mirrored networking, where loopback is shared with the
Windows host.
- Screenshots are written to a local cache directory (`~/.cache/clipaste` on macOS and
Linux, `%LOCALAPPDATA%/clipaste` on Windows). Identical PNG bytes reuse stable
SHA-256 paths. Published files no longer expire automatically, so clipboard
history paths remain valid. Disk usage grows with unique images; explicitly
deleting cached files invalidates any saved paths that reference them.
- Linux cache directories use `0700` and PNG files use `0600`. Clipboard clears,
non-image content, and recognized private markers clear the currently staged
image without deleting historical cache files.
- No telemetry, no network calls other than serving the local endpoints.
---
## Implementation notes
- **macOS**: an `NSTimer` on the run loop watches `NSPasteboard.changeCount`. When the
clipboard holds image data with no file URL or string, the daemon rewrites it with the
temp-file URL plus `public.png`, `com.apple.pboard.type.PNGf` and a plain-text path.
When the clipboard instead holds a *file URL* pointing at an image (a screenshot saved
to disk and then copied in Finder), the file is captured for remote serving without
touching the local clipboard. In server-only mode, image data is captured the same
way: the pasteboard is never rewritten, and a capture is discarded if the change
count moved during conversion.
- **Windows**: fully event-driven. A hidden `HWND_MESSAGE` window registers via
`AddClipboardFormatListener` and handles `WM_CLIPBOARDUPDATE`, de-duplicated with
`GetClipboardSequenceNumber`. `CF_DIB` is converted to PNG and the path written back as
`CF_UNICODETEXT`. Server-only mode skips that write, leaving `CF_DIB` in place.
There is no polling loop.
- Linux: polls every 300 ms using bounded one-shot `wl-paste --watch` calls
for Wayland data-control, or system `xclip` for X11/XWayland. Reads `image/png`
into the private stable cache without rewriting clipboard formats. Auto
fallback from native Wayland is explicitly warned; no forced-focus polling.
- **HTTP**: a hand-rolled server on the standard library's `TcpListener`. No web framework.
- Runtime tools: Linux uses `wl-clipboard` and/or `xclip`
according to the selected backend. HTTP requests made by the CLI use `curl`.
macOS/Windows retain their native clipboard APIs.
---
## Frequently asked questions
**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. Terminals can paste text and
file paths but cannot hand raw image bytes to the program they host, so the keystroke
arrives empty. clipaste writes the screenshot to a temp PNG and puts that path on the
clipboard alongside the image data.
**Can I paste screenshots into Claude Code running on a remote server over SSH?**
Yes. Run `clipaste ssh-setup user@host` from the local macOS, Windows, or graphical
Linux clipboard host with its daemon running, then open a new SSH session.
On Linux remotes, press Ctrl+V in Claude Code; on macOS remotes, use `clipaste-paste`.
**Why can't Codex CLI paste images over SSH the way Claude Code can?**
Codex reads the clipboard in-process via `arboard` and never runs `xclip`, so it bypasses
the shim. Use `clipaste-paste` on the remote and hand the printed path to Codex.
**Does clipaste work in WSL2?**
Yes, with the Windows daemon already running. Run `clipaste wsl-setup` inside
the distro; see the networking requirements above.
**How much memory and CPU does clipaste use?**
The existing macOS/Windows footprint is about 9 MB resident with no measurable
idle CPU. Linux polls every 300 ms and invokes system tools; those measurements
do not establish its resource use.
**Does clipaste send my screenshots anywhere?**
No. Loopback only, with no telemetry.
**Which terminals and AI tools are supported?**
Ghostty, Alacritty, iTerm2, Terminal.app, WezTerm, Kitty, Windows Terminal; Claude Code,
Codex CLI and Cursor CLI.
**Is clipaste free and open source?**
Yes, MIT licensed, at github.com/hqhq1025/clipaste.
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
No one has posted yet. Be the first.

