README.md

August 15, 2026 · View on GitHub

English · 简体中文 · 日本語

cc-clip sends a local clipboard through a loopback-only SSH tunnel to remote AI coding agents

Latest release CI status MIT license

Paste images into remote Claude Code, Codex CLI, opencode, and Cursor sessions over SSH — and copy text back out, free of terminal soft-wrap.
Optional integrations bring completion and approval notifications back to your desktop.

Quick start · Choose a target · How it works · Documentation

Terminal demo showing cc-clip installation, setup, and remote image paste
Install → setup → open SSH → paste.

Upgrading from v0.8.x? In v0.9.0, --codex became Codex-only. Use --all when the same host also needs the Claude integration. See the upgrade guide.

Quick Start

This is the stable macOS-to-Linux path. You need:

  • macOS 13 or later;
  • a Linux remote (amd64 or arm64) with curl, bash, and xclip or wl-paste;
  • a named Host entry in ~/.ssh/config.

1. Install

curl -fsSL https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.sh | sh
cc-clip --version

If the installer asks, add ~/.local/bin to your PATH before continuing.

2. Set up one host

cc-clip setup myserver

The default target is Claude Code. Setup checks local dependencies, adds the loopback RemoteForward, starts the local daemon, and deploys the remote shim. Use a target flag from the next section for Codex, opencode, or notifications.

3. Open a new SSH session

ssh myserver

Start your coding agent and paste as usual. The new SSH connection is important: it is what holds the reverse tunnel open.

4. Verify the whole path

Copy an image to the Mac clipboard, then run locally:

cc-clip doctor --host myserver

Choose a Target

Choose one selector per setup. With no selector, cc-clip configures Claude Code.

Remote workflowSetup commandImage pasteDesktop notificationsExtra requirement
Claude Codecc-clip setup myserverYesYesxclip or wl-paste
Codex CLI onlycc-clip setup myserver --codexYesYesXvfb; setup may need remote sudo
All integrationscc-clip setup myserver --allYesYesXvfb for Codex
opencodecc-clip setup myserver --opencodeYesYesxclip or wl-paste
Antigravitycc-clip setup myserver --agyNoYesNotification integration only
Cursor CLIcc-clip setup myserver --cursorYesNoDISPLAY or WAYLAND_DISPLAY set in Cursor's shell

For Codex targets, cc-clip tries to install Xvfb with apt or dnf. If passwordless sudo is unavailable, it stops and prints the exact install command; run that command manually, then repeat setup.

The Claude, opencode, and Cursor paths use the remote xclip or wl-paste shim. Codex reads X11 directly, so its target adds Xvfb and cc-clip x11-bridge instead.

Cursor has one extra prerequisite the deploy cannot satisfy: its clipboard reader only runs when DISPLAY or WAYLAND_DISPLAY is set in the shell where Cursor runs (check with echo $DISPLAY). Connect with ssh -X myserver or export an existing display — cc-clip deliberately does not invent one, because a DISPLAY with no X server behind it would break clipboard fallback for every other tool in that shell. Cursor also stops waiting for clipboard helpers after about 4 seconds, so for large images over a slow link add export CC_CLIP_FETCH_TIMEOUT_MS=3000 to your remote shell rc. Cursor notifications are not wired up yet.

If a package manager already owns cc-clip on the remote, preserve that ownership with cc-clip setup myserver --use-remote-bin. Setup resolves cc-clip under your remote login shell's PATH (so ~/.nix-profile/bin, pipx and asdf installs are found), records its version and hash, and performs the normal integration setup without uploading a replacement binary.

The mode is remembered in the host's deploy state: later cc-clip connect runs — including the connect <host> --force line that cc-clip update suggests — keep using the package-managed binary without needing the flag again. Deploy with --local-bin to switch the host back to uploaded binaries. The flag cannot be combined with --local-bin in the same run.

opencode and Antigravity integration generation is covered by tests, but host event delivery has not yet been smoke-tested on a representative machine. Please report what you find.

Other local platforms

Local machineRemoteSupport levelRecommended path
macOS 13+LinuxStablecc-clip setup HOST
Windows 10/11LinuxExperimentalsend / hotkey quick start
LinuxLinuxManual daemonRun cc-clip serve, then cc-clip setup HOST in another shell

Windows support remains experimental. Start with the explicit upload-and-paste workflow in the Windows Quick Start. An opt-in direct RemoteForward transport also exists (since v0.9.1), but it is not the default.

How It Works

cc-clip keeps the transport narrow and local to your SSH connection:

Image paste
  local clipboard
      → cc-clip daemon on 127.0.0.1:18339
      → SSH RemoteForward
      → remote xclip/wl-paste shim or Xvfb bridge
      → remote coding agent

Notifications
  remote hook / notify command / plugin
      → SSH tunnel
      → local cc-clip daemon
      → macOS Notification Center or cmux
  1. The local daemon reads clipboard data only when the remote side asks for it.
  2. SSH exposes that daemon on remote loopback; no public listener is created.
  3. Claude Code and opencode reach it through a transparent clipboard shim.
  4. Codex reaches it through an Xvfb clipboard owner because Codex reads X11 directly instead of invoking xclip.
  5. Unrecognized xclip / wl-paste calls fall through to the real remote tool.

Notifications

Clipboard data and agent events share the SSH tunnel but use separate authentication material. cc-clip connect can wire:

SourceIntegrationExample event
Claude CodeManaged hooksStop, approval request, image paste
Codex CLInotify commandTask completion
opencodeGenerated pluginSession idle
AntigravityGenerated pluginAgent stop

For adapter details, manual configuration, nonce registration, and diagnostics, see SSH Notifications.

Security Model

BoundaryProtection
NetworkDaemon and forwarded port bind to loopback only
ClipboardBearer token with 30-day sliding expiration
NotificationsSeparate per-connect nonce
Process listTokens and hook payloads are not placed in command-line arguments
FallbackUnrelated clipboard calls pass through to the real remote binary

Loopback is shared by users on the same remote host. The token file is mode 0600, but cc-clip does not defend against another process acting as your Unix account or reading your files. Read the explicit threat model before using cc-clip on a shared or untrusted host.

Essential Commands

CommandUse it for
cc-clip setup HOST [target]First-time dependencies, SSH config, daemon, and deploy
cc-clip setup HOST --use-remote-binConfigure a host whose remote binary is package-managed
cc-clip connect HOST --force [target]Repair or fully redeploy a host
cc-clip connect HOST --token-onlySync a rotated or expired token
cc-clip doctor --host HOSTEnd-to-end diagnosis
some-command | cc-clip copy (on the remote)Copy remote output to your local clipboard, bypassing terminal soft-wrap
cc-clip statusLocal component status
cc-clip hosts listKnown-host registry
cc-clip update --checkCheck the published release channel
cc-clip updateInstall the latest published release

Run cc-clip --help for the authoritative command list. The commands guide covers the common flags and environment variables.

Configuration

SettingDefaultEnvironment variable
Tunnel port18339CC_CLIP_PORT
Token lifetime30dCC_CLIP_TOKEN_TTL
Debug loggingoffCC_CLIP_DEBUG=1

Troubleshooting

Start with the built-in diagnosis:

cc-clip doctor --host myserver

The three most common fixes are:

  • Tunnel unavailable: keep a fresh ssh myserver session open. A RemoteForward exists only while an SSH connection owns it.
  • Token rejected after daemon restart: run cc-clip connect myserver --token-only.
  • Codex has no clipboard: open a new SSH session so the injected DISPLAY is loaded; if Xvfb or x11-bridge is missing, run cc-clip connect myserver --codex --force (or --all --force).

If a new SSH tab reports remote port forwarding failed for listen port 18339, another live or stale SSH session already owns the fixed remote port. Use the working session, close the old one, or follow the port cleanup steps in the Troubleshooting Guide.

When Not to Use cc-clip

Use a simpler option when it fits:

  • use an editor's built-in remote clipboard if your whole workflow is already inside that editor;
  • use OSC 52 for text-only clipboard synchronization;
  • use scp when image transfer is rare and preserving paste behavior is not worth a daemon and SSH forward;
  • use a general clipboard bridge when you need broad, bidirectional clipboard synchronization rather than a narrow agent workflow;
  • avoid cc-clip on an untrusted shared host where remote local users must not reach your user-scoped loopback tunnel.

Documentation

GuideWhat it covers
Windows Quick StartWindows upload, paste, and hotkey workflow
UpgradingBreaking changes and version-specific migration
CommandsCommon commands, flags, and environment variables
NotificationsHook and plugin integrations
TroubleshootingSymptom-by-symptom diagnosis
SecurityThreat model and trust boundaries

Contributing

Bug reports and focused pull requests are welcome. For larger features, open an issue first so the approach can be discussed.

Building from source requires the Go version declared in go.mod:

git clone https://github.com/ShunmeiCho/cc-clip.git
cd cc-clip
make build
make test

Use Conventional Commits for commit messages (feat:, fix:, docs:, and so on).

License

MIT