cmux NEXT composer: Cmd-V anywhere in an agent chat pastes into the composer; a copied image is one chip, never markdown
Leo-ask: ask-68647e03c0
Leo-ask: ask-1eb1fd1100
Leo said:
- "pastes need to be able to paste even when the composer isn't literally focused"
- "ME PASTING IT DOESNT JUST PASTE RIGHT IN THE COMPOSER IMMEDIATELY"
- "copying and pasting images straight puts weird things in composer"
He copied the images from Edge and Chrome. The composer got text like  next to the image chip.
Now:
- In an agent pane, Cmd-V goes into the composer when focus is on the transcript, on a clicked message, on a button or on nothing. The composer takes focus, and the text goes in after what is already there.
- A copied image becomes one image chip, and the
<img>orthe browser copies with it stays out of the prompt. - A text field elsewhere in the pane keeps its own paste: a prompt being edited, a search, a question's answer, or anything in a modal dialog.
Root cause
- Paste outside the prompt went nowhere. The composer's only paste listener,
useAttachmentIntake(webviews/src/agent-session/acpmux/composer/attachmentIntake.tsx:121-136), ignores any paste whose target is not the prompt or shell field.pasteTarget(Composer.tsx:441-446) returnsundefinedfor those. So a paste with focus on the transcript was dropped.- On WebKit the paste event never fires there at all. WebKit enables Paste outside editable content only when a
beforepastehandler cancels the event (Editor::canDHTMLPaste), and nothing inwebviews/orPackages/listens forbeforepaste. - The native side does not swallow Cmd-V:
- The KeyRouter has no plain Cmd-V binding outside terminals (
TerminalActionCatalog.swift:118), andBrowserChordTable.swift:53keeps the key for the page. PageWKWebView.pasteandAgentPaneWKWebView.pasteforward to WebKit's ownpaste:.- CEF's pre-key hook passes the key on.
- The KeyRouter has no plain Cmd-V binding outside terminals (
- So no Swift change is needed.
- On WebKit the paste event never fires there at all. WebKit enables Paste outside editable content only when a
- Markdown came in with the image. When the clipboard carries the image file, the field's DOM paste handler (
MarkdownField.tsx:436-449, added in #23100 / 84494d5c904) still puts the clipboard's plain text in the prompt (lifted.text). That text is themarkup for the same picture.
Fix
- New
composer/pasteAnywhere.ts, installed by the Composer:- Cmd-V outside a text field focuses the prompt (or the shell field) with the caret at the end, so the app's Paste lands in it.
- A
beforepastelistener turns Paste on in WebKit. - A
pasteevent that still lands outside a field (Edit > Paste, Chromium) is handed to the focused prompt as its own paste. Everything a paste does in the field still applies: image chips, Pasted text chips, the caret.
MarkdownFieldpaste: when the clipboard carries an image (a file or adata:<img>), the text it inserts no longer includes markdown images (withoutMarkdownImages,inlineImages.ts).
Changelog
- Fixed: In an agent chat, Cmd-V pastes into the composer even when the composer is not focused, and a pasted image becomes an image chip instead of markdown text.
Regression test
cd webviews && CMUX_BROWSER_TESTS=1 bun test test/agent-pane-paste-anywhere.test.ts (Chromium and WebKit, real agent pane):
- Base (ca294a90123 plus the test commit 78dbe89d296): 8 fail, 2 pass. Both passes are "a paste into another text field stays in that field", the guard.
- "text pasted with the keyboard on the transcript goes into the composer":
pastewas not cancelled, and the prompt stayed empty. - "goes at the end of the draft": got
"first part". - "Cmd-V outside a field moves the keyboard into the composer": focus stayed out.
- "an image copied from a browser is one image chip": the paste was not taken.
- The sixth case ("…pasted in the focused composer puts no markdown in it") was added after that run. A later base re-run also fails it on WebKit. Chromium's runs in that re-run were broken by a full disk on huge-blue, so they don't count.
- "text pasted with the keyboard on the transcript goes into the composer":
- Head 637945e913a: 12 pass, 0 fail.
Observed / Not run
- Ran on huge-blue:
- The new test, red on base and green on head.
bun run checkpasses.- The existing paste suites all pass (27 pass, 0 fail):
composer-paste-images,composer-paste-text,paste-chip-round-trip,composer-html-paste-edit,composer-line-breaks,composer-paste-endandnew-tab-paste-attachments. - The browser files
agent-pane-focus-content,composer-click-near-focusesandgallery-composer-pastepass when each runs on its own.
- Not run: a real Cmd-V in the Mac app; headless browsers don't run the system Paste. The native path was read, not exercised.
No capture: webview-only change (behavior, no new look).
Agent session: cosmic-gray
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Pasting with Cmd-V in an agent chat now goes into the composer even when the composer isn't focused, and a copied image lands as one image chip instead of markdown text.
Previously, a paste with focus on the transcript, a message, or nothing was dropped, and copying an image from a browser put  markup in the prompt next to the image chip.
- Cmd-V outside a text field focuses the prompt with the caret at the end; WebKit gets a
beforepastehandler so Paste works outside editable content. - A paste that carries the image (a file or a data:
<img>) drops the markdown image text viawithoutMarkdownImages. - Text fields elsewhere in the pane (editing a prompt, search, modal dialogs) keep their own paste.