Skip to content

feat: add ImagePasteAddon for clipboard image handling#143

Open
brianegan wants to merge 2 commits into
coder:mainfrom
brianegan:onImagePaste
Open

feat: add ImagePasteAddon for clipboard image handling#143
brianegan wants to merge 2 commits into
coder:mainfrom
brianegan:onImagePaste

Conversation

@brianegan
Copy link
Copy Markdown

@brianegan brianegan commented Mar 23, 2026

Summary

  • Adds ImagePasteAddon, a new addon following the ITerminalAddon pattern (same as FitAddon), that detects image data in clipboard paste events and emits them as base64-encoded payloads via an onImagePaste event
  • Updates InputHandler.handlePaste to only claim paste events that contain text, allowing image-only pastes to bubble through to addons
  • Keeps the core Terminal API strictly xterm.js-conformant — no custom events on the Terminal class

Usage

import { Terminal, ImagePasteAddon } from 'ghostty-web';

const term = new Terminal();
const imagePasteAddon = new ImagePasteAddon();
term.loadAddon(imagePasteAddon);

imagePasteAddon.onImagePaste((data) => {
  console.log(data.name);       // e.g. "clipboard_1234567890.png"
  console.log(data.dataBase64); // base64-encoded image data
});

Design decisions

  • Addon, not core API: onImagePaste doesn't exist in xterm.js. Implementing it as an addon keeps the drop-in replacement promise intact — code written against the core API remains portable between xterm.js and ghostty-web.
  • Event bubbling: InputHandler no longer calls preventDefault()/stopPropagation() at the top of paste handling. It only claims the event when there is text to process, letting image-only pastes reach addon listeners.
  • Exported types: ImagePasteAddon and IImagePasteData are exported from the package entry point.

Test plan

  • All 341 existing tests pass
  • New image-paste.test.ts covers activation, disposal, lifecycle, event subscription, image paste firing, non-image paste ignoring, and post-dispose cleanup
  • Manual test: paste an image from clipboard with the addon loaded and verify onImagePaste fires
  • Manual test: paste text with the addon loaded and verify normal onData behavior is unaffected

🤖 Generated with Claude Code

brianegan and others added 2 commits March 23, 2026 13:48
Image paste handling was baked into Terminal and InputHandler as a
custom onImagePaste event, which doesn't exist in the xterm.js API.
Extract it into an opt-in addon following the ITerminalAddon pattern
(same as FitAddon) to keep the core Terminal API xterm.js-conformant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brianegan
Copy link
Copy Markdown
Author

Heya, really cool project! I was building a VSCode extension with ghostty-web and ran into the issue where I needed to paste images. I created this plugin with Claude Opus to handle such a case.

Not sure if you're accepting submissions coauthored by AI, but if so, I've found this helpful and wanted to contribute.

diegosouzapw added a commit to diegosouzapw/ghostty-web that referenced this pull request May 23, 2026
Adds ImagePasteAddon, a new addon following the ITerminalAddon pattern
(same as FitAddon), that detects image data in clipboard paste events
and emits them as base64-encoded payloads via an onImagePaste event.

Also updates InputHandler.handlePaste to only claim paste events that
contain text. Paste events without text (e.g. image-only) are no longer
consumed by the default handler, allowing them to bubble through to
addons like ImagePasteAddon.

The core Terminal API stays strictly xterm.js-conformant — no custom
events on the Terminal class.

Public API additions in lib/index.ts:
- ImagePasteAddon class
- IImagePasteData type

Usage:

  import { Terminal, ImagePasteAddon } from 'ghostty-web';
  const term = new Terminal();
  const addon = new ImagePasteAddon();
  term.loadAddon(addon);
  addon.onImagePaste((data) => { /* data.name, data.dataBase64 */ });

Adapts the import order to satisfy our Biome organizeImports rule
(value imports before type-only imports).

Co-authored-by: Brian Egan <brian.egan@verygood.ventures>
Inspired-by: coder#143
diegosouzapw added a commit to diegosouzapw/ghostty-web that referenced this pull request May 23, 2026
Adds ImagePasteAddon, a new addon following the ITerminalAddon pattern
(same as FitAddon), that detects image data in clipboard paste events
and emits them as base64-encoded payloads via an onImagePaste event.

Also updates InputHandler.handlePaste to only claim paste events that
contain text. Paste events without text (e.g. image-only) are no longer
consumed by the default handler, allowing them to bubble through to
addons like ImagePasteAddon.

The core Terminal API stays strictly xterm.js-conformant — no custom
events on the Terminal class.

Public API additions in lib/index.ts:
- ImagePasteAddon class
- IImagePasteData type

Usage:

  import { Terminal, ImagePasteAddon } from 'ghostty-web';
  const term = new Terminal();
  const addon = new ImagePasteAddon();
  term.loadAddon(addon);
  addon.onImagePaste((data) => { /* data.name, data.dataBase64 */ });

Adapts the import order to satisfy our Biome organizeImports rule
(value imports before type-only imports).


Inspired-by: coder#143

Co-authored-by: Brian Egan <brian.egan@verygood.ventures>
@diegosouzapw
Copy link
Copy Markdown

Hi @brianegan! 👋

Your work on this PR inspired a commit in my fork diegosouzapw/ghostty-web.
I ported the ImagePasteAddon for clipboard image handling and added you as co-author in the corresponding commit — thank you for the contribution!

I'm working on OmniRoute, a project that provides free access to LLM models, and I'm planning to use ghostty-web as the terminal component there. Your work is part of what makes that possible. 🙏

Feel free to check it out — contributions and feedback are very welcome!

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.

2 participants