Paste clipboard images as files with Hammerspoon

· Tech

I run AI coding agents inside sbx, a Docker sandbox. It works great for isolation, but it does not support pasting images from the clipboard. The agent can only see files mounted into the container.

I paste images to AI constantly (screenshots, diagrams, error messages). Not having clipboard image support was a real friction point.

The workaround: a Hammerspoon hotkey that saves the clipboard image as a file in the current tmux pane directory, then copies the filename to the clipboard. I press the hotkey, then tell the agent to look at the file.

The script

Add this to ~/.hammerspoon/init.lua:

-- ── Paste clipboard image to current tmux pane directory ─────
hs.hotkey.bind({"ctrl", "shift"}, "v", function()
local img = hs.pasteboard.readImage()
if img then
local filename = os.date("clipboard-%Y%m%d-%H%M%S") .. ".png"
local cwd = hs.execute("/opt/homebrew/bin/tmux display-message -p '#{pane_current_path}'"):gsub("%s+$", "")
if cwd == "" then cwd = os.getenv("HOME") end
local path = cwd .. "/" .. filename
img:saveToFile(path)
hs.pasteboard.setContents(filename)
hs.alert.show("Saved: " .. filename)
else
hs.alert.show("No image in clipboard")
end
end)

Reload Hammerspoon config after adding it (Cmd+R in the Hammerspoon console, or click Reload Config from the menu bar icon).

What it does

hs.pasteboard.readImage() reads the clipboard contents as an image. If there is no image data (just text, for example), it returns nil and shows an alert.

hs.execute calls tmux to get the current working directory of the active pane. This is the key part. #{pane_current_path} is a tmux format variable that returns the CWD of the shell running in the focused pane. This means the image always lands in whatever directory I am currently working in, which is the project directory mounted into sbx.

The image gets saved as clipboard-YYYYMMDD-HHMMSS.png. After saving, hs.pasteboard.setContents(filename) replaces the clipboard image with the filename as text. So I press the hotkey, then Cmd+V pastes the filename, not the image.

If tmux is not running or returns an empty string, it falls back to the home directory.

The workflow

  1. Copy an image (screenshot, browser, anything)
  2. Press Ctrl+Shift+V
  3. Hammerspoon saves the image to the current tmux pane directory
  4. The filename is now in the clipboard
  5. Tell the AI agent to check the file, paste the filename

The agent running inside sbx can read the file because it is in the mounted project directory. No clipboard integration needed.

Prerequisites

This requires Hammerspoon and tmux. The tmux binary path is hardcoded to /opt/homebrew/bin/tmux (Homebrew on Apple Silicon). If your tmux is elsewhere, update the path.