Paste clipboard images into Claude Code over SSH

Published on Friday, March 27, 2026

The problem

Claude Code is multimodal. It can read and reason about images using the Read tool. But when you run Claude Code on a remote server over SSH, there's no way to paste an image from your local clipboard into the session. The clipboard lives on your local machine, while Claude Code runs on the server.

I ran into the same issue with Neovim and built sshimg.nvim to solve it. Now I've built the same thing for Claude Code: claude-ssh-image-skill.

How it works

The solution has three parts:

  1. ccimgd: a daemon running on your local machine that reads PNG images from the clipboard (wl-paste on Wayland, xclip on X11, pngpaste on macOS) and serves them as base64-encoded JSON over TCP on port 9998
  2. ccimg: a client binary on the remote server that connects to the daemon, receives the image, and saves it as a temporary PNG file
  3. /paste-image: a Claude Code skill that runs ccimg and then uses the Read tool to display the image to Claude

The connection between client and daemon runs through an SSH reverse tunnel:

Local Machine                            Remote Server (SSH)
┌──────────────────────┐                 ┌──────────────────────────┐
│  Clipboard (PNG)     │                 │  Claude Code             │
│        │             │                 │        │                 │
│        ▼             │                 │        ▼                 │
│  ccimgd (Port 9998)  │◄────────────────│  /paste-image Skill      │
│  - wl-paste          │  SSH Reverse    │  - TCP Request to ccimgd │
│  - Returns base64    │  Tunnel         │  - Receives base64 image │
│    image in response │  (Port 9998)    │  - Saves as temp file    │
│                      │                 │  - Read → Claude sees    │
└──────────────────────┘                 │    the image             │
                                         └──────────────────────────┘

Building

Both binaries are written in Go and compile as fully static binaries with no runtime dependencies:

git clone https://github.com/AlexZeitler/claude-ssh-image-skill.git
cd claude-ssh-image-skill
./build.sh

This builds statically linked binaries for all supported platforms:

  • daemon/ccimgd-linux-amd64, daemon/ccimgd-darwin-amd64, daemon/ccimgd-darwin-arm64
  • client/ccimg-linux-amd64, client/ccimg-darwin-amd64, client/ccimg-darwin-arm64

Setup

Local machine (Linux)

cp daemon/ccimgd-linux-amd64 ~/.local/bin/ccimgd
cp daemon/ccimgd.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now ccimgd

Local machine (macOS)

Requires pngpaste for clipboard access:

brew install pngpaste
cp daemon/ccimgd-darwin-arm64 /usr/local/bin/ccimgd # or ccimgd-darwin-amd64 for Intel
cp daemon/com.ccimgd.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.ccimgd.plist

Remote server

Copy the client binary and the Claude Code skill:

scp client/ccimg-linux-amd64 your-server:~/.local/bin/ccimg
scp skill/paste-image.md your-server:~/.claude/commands/paste-image.md

To skip permission prompts, add the Bash permission to ~/.claude/settings.json on the server:

{
"permissions": {
"allow": [
"Bash(ccimg)"
]
}
}

SSH connection

Connect with a reverse tunnel so the remote ccimg can reach the local ccimgd:

ssh -R 9998:localhost:9998 your-server

Or add it permanently to ~/.ssh/config:

Host your-server
    RemoteForward 9998 localhost:9998

Usage

Copy an image to the clipboard on your local machine, then run this in Claude Code on the remote server:

/paste-image

Claude receives the image and can reason about it: screenshots, diagrams, error messages, whatever you need.

The skill

The skill itself is minimal. It's a Markdown file that tells Claude what to do:

Paste an image from the local clipboard into this session.

Instructions:
1. Run `ccimg` using the Bash tool.
2. Use the Read tool to read the printed file path.
This will display the image to Claude.

Claude Code skills are just natural language instructions stored in ~/.claude/commands/. When you invoke /paste-image, Claude follows the instructions: run the client, get the file path, read the image.

The daemon

ccimgd listens on 127.0.0.1:9998 and waits for a TCP connection. When a client connects and sends a newline-terminated message, the daemon reads the clipboard image and responds with a JSON object:

type response struct {
OK bool `json:"ok"`
Image string `json:"image,omitempty"`
Error string `json:"error,omitempty"`
}

The Image field contains the base64-encoded PNG data. The daemon auto-detects the platform and uses wl-paste on Wayland, xclip on X11, or pngpaste on macOS.

The client

ccimg connects to 127.0.0.1:9998 (which the SSH reverse tunnel forwards to the local machine), sends {}\n, receives the JSON response, decodes the base64 image, writes it to a temp file, and prints the path to stdout. That's all Claude Code needs to pick it up with Read.

Coexistence with sshimg.nvim

If you also use sshimg.nvim, both tools can run simultaneously. imgd uses port 9999 while ccimgd uses port 9998.

Source

The full source is on GitHub: AlexZeitler/claude-ssh-image-skill

What are your thoughts about
"Paste clipboard images into Claude Code over SSH"?
Drop me a line - I'm looking forward to your feedback!