Skip to content

feat: image paste (Ctrl+V) and drag-and-drop into terminal#84

Open
aakhter wants to merge 1 commit into
Ark0N:masterfrom
aakhter:feat/image-paste-and-drop
Open

feat: image paste (Ctrl+V) and drag-and-drop into terminal#84
aakhter wants to merge 1 commit into
Ark0N:masterfrom
aakhter:feat/image-paste-and-drop

Conversation

@aakhter
Copy link
Copy Markdown
Contributor

@aakhter aakhter commented May 15, 2026

Summary

Lets users paste or drop images into the terminal. The image is saved to ${workdir}/.claude-images/ and the absolute file path is inserted at the cursor — Claude (or any other CLI that reads file paths from stdin) can then process the image without the user having to manually save and @-mention it.

Two entry points:

  • Ctrl+V with an image on the clipboard
  • Drag-and-drop of one or more image files onto the terminal pane (with a visual overlay while dragging)

Mixed-content paste (image + text together) works — both the image is saved as a file and the text is forwarded to the terminal.

Implementation

  • POST /api/sessions/:id/paste-image — hand-parsed multipart endpoint (no @fastify/multipart dependency). Saves under ${session.workingDir}/.claude-images/img-${ts}.${ext} and returns the absolute path.
  • src/web/public/image-input.js — new mixin that wires both paste and drop into the existing terminal:
    • Paste trap technique: Ctrl+V is intercepted at the xterm keyboard layer, focus is briefly redirected to a hidden contenteditable div which receives the paste event (this is the only reliable way to capture clipboard image data over plain HTTP, where the async Clipboard API requires a secure context). Both image bytes and text data from the same paste are extracted, then focus returns to xterm.
    • Drag-and-drop: handlers on the terminal container show a dashed-border overlay during drag and accept any image/* file on drop.
  • src/web/routes/session-routes.ts — multipart parser (~100 lines) and the route handler. Body length is bounded to 10 MB and the image MIME type is validated against an allowlist (PNG/JPEG/WebP/GIF).
  • src/web/server.ts — wires image-input.js into the static asset list and adds session-cleanup so .claude-images/ is removed on session destroy (no orphan disk usage).
  • src/web/public/{index.html,styles.css} — script tag + drop-overlay styling.

The .claude-images/ directory is created lazily on first paste and is the only file the feature writes — no DB rows, no global state.

Test plan

  • Copy an image from a screenshot tool / browser, focus the terminal, press Ctrl+V → an image file appears in ${workdir}/.claude-images/ and its absolute path is typed into the terminal.
  • Drag an image from your file manager onto the terminal → drop overlay appears, file lands in the same directory, path is inserted.
  • Mixed paste (image + text together, e.g. some clipboard managers): the image file is created AND the text is forwarded to the terminal.
  • Multiple images dropped together: each saved with a distinct timestamp and each path inserted.
  • Bogus mime type (text/plain masquerading as image): rejected with 415.
  • >10 MB image: rejected with 413.
  • Delete the session → .claude-images/ directory removed.
  • Plain HTTP (not HTTPS): paste still works (this was a primary motivator — the secure-context-only Clipboard API doesn't help on local LAN setups).

🤖 Generated with Claude Code

Clipboard paste (Ctrl+V) and drag-and-drop of image files into the
terminal. Images are saved to {workdir}/.claude-images/ and the
absolute path is inserted into the terminal input for Claude to read.

- POST /api/sessions/:id/paste-image endpoint (hand-parsed multipart)
- image-input.js mixin with paste trap technique (works on HTTP)
- Ctrl+V intercepted at xterm keyboard level, routes through hidden
  contenteditable div to capture both image and text clipboard data
- Drag-and-drop on terminal container with visual overlay
- Session cleanup deletes .claude-images/ on destroy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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