Skip to content

Add image paste support via yank-media#135

Open
stevemolitor wants to merge 3 commits intomainfrom
image-paste-support
Open

Add image paste support via yank-media#135
stevemolitor wants to merge 3 commits intomainfrom
image-paste-support

Conversation

@stevemolitor
Copy link
Copy Markdown
Owner

Summary

  • Lets users paste images from the system clipboard into Claude buffers using M-x yank-media. The handler writes the image to a temp file and injects @<path> at the prompt; Claude's CLI reads @path references natively and attaches the image to the next message.
  • Works across all three terminal backends (eat, vterm, ghostel) by dispatching through the existing claude-code--term-send-string abstraction.
  • Two new defcustoms: claude-code-enable-image-paste (default t) and claude-code-image-paste-cleanup-on-kill (default t). Requires Emacs 29+ (yank-media-handler); no-op on older versions.
  • README gets a Features bullet and a short "Pasting Images" subsection.

Motivation

This is a long-standing request (issue #127). Terminal emulators don't forward OS-level clipboard image data or drag events to the CLI on their own, but the Claude CLI does accept file path references via @path. Bridging those two via yank-media-handler is a small, uncomplicated glue.

Implementation notes

  • Handler writes with coding-system-for-write 'binary so PNG/JPEG bytes are preserved verbatim.
  • Temp files live under the variable temporary-file-directory with a claude-image- prefix and a type-appropriate extension (.png, .jpg, .gif, .webp, .bmp; falls back to .png for unrecognized image/* types).
  • Per-buffer cleanup hook removes the temp files on kill-buffer when claude-code-image-paste-cleanup-on-kill is non-nil.
  • Registration is gated behind (fboundp 'yank-media-handler) so it's a no-op on Emacs < 29.

Test plan

  • On Emacs 29+, copy a PNG to the clipboard, M-x claude-code, M-x yank-media — verify the prompt shows @/tmp/claude-image-XXXX.png and sending the message works.
  • Repeat with a JPEG, verify .jpg extension.
  • Kill the Claude buffer, verify the temp file is deleted (with claude-code-image-paste-cleanup-on-kill at its default t).
  • Set claude-code-image-paste-cleanup-on-kill to nil, kill buffer, verify the file stays.
  • Set claude-code-enable-image-paste to nil, open a fresh Claude buffer, verify yank-media does nothing.
  • Cycle through all three terminal backends (eat, vterm, ghostel); feature should work identically in each.
  • On Emacs 28 (if accessible), confirm the feature is silently skipped with no errors.

On Emacs 29 and later, register a `yank-media-handler' for `image/.*'
in every Claude buffer.  When the user pastes an image from the system
clipboard the handler writes the bytes to a temp file and injects
`@<path> ' into the terminal via `claude-code--term-send-string' — Claude's
CLI reads `@path' references natively and attaches the image to the next
message.  Temp files are tracked per-buffer and cleaned up on
kill-buffer when `claude-code-image-paste-cleanup-on-kill' is non-nil.

Works transparently across all three terminal backends (eat, vterm,
ghostel) because the abstraction already dispatches send-string per
backend.  Two new defcustoms control the feature and cleanup behavior.

Documents the feature in README and adds a Features bullet.
Wrap yank-media in an interactive command that targets the Claude
buffer via claude-code--with-buffer, so the user can invoke it from
anywhere — command map prefix on p, or the Send group of the
transient menu.  README updated to mention the binding.
The default temp dir on macOS is nested deep under /var/folders/...
which makes the @<path> reference inserted at the prompt unreadable.
New defcustom claude-code-image-paste-directory defaults to /tmp on
systems that have it and falls back to temporary-file-directory on
others.  Users can override to e.g. ~/.claude/pastes/ for a project
directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant