Skip to content

fix(desktop): terminal selection copies from every entry point on macOS - #6483

Open
realDragonium wants to merge 2 commits into
pingdotgg:mainfrom
realDragonium:t3code/fix-macos-terminal-copying
Open

fix(desktop): terminal selection copies from every entry point on macOS#6483
realDragonium wants to merge 2 commits into
pingdotgg:mainfrom
realDragonium:t3code/fix-macos-terminal-copying

Conversation

@realDragonium

@realDragonium realDragonium commented Aug 13, 2026

Copy link
Copy Markdown

What Changed

Terminal copying on macOS failed because each copy entry point resolved against a different owner, and only one of them could see the Ghostty selection (which lives in canvas/WASM state, not the DOM):

  • Cmd+C only worked while the hidden terminal textarea was focused — and the selection menu that auto-opens after every drag steals the keyboard while it's up, so the natural "select, then Cmd+C" died in the native menu's tracking loop.
  • Right-click → Copy was Electron's generic DOM-role menu; editFlags.canCopy is always false for a canvas selection, so Copy stayed disabled.
  • The clipboard write itself used navigator.clipboard.writeText, which Chromium rejects while the document is unfocused — and macOS shows context menus on inactive windows without activating them, so menu-driven copies could fail with an error even when everything upstream worked.

All entry points now route through one Ghostty-aware copy:

  • The selection menu's Copy item carries the platform copy accelerator (Cmd+C / Ctrl+Shift+C), so pressing it while the open menu owns the keyboard activates Copy natively (ContextMenuItem gains an optional accelerator, forwarded by ElectronMenu).
  • Right-click on a highlighted selection opens the same Add to chat / Copy menu instead of the DOM-role menu. Mouse-reporting apps keep owning right-click, and right-click without a selection keeps the generic paste menu.
  • Dismissing the menu refocuses the terminal input (unless the dismissal legitimately focused something else), so the keyboard shortcut keeps working against the still-highlighted selection.
  • Desktop clipboard writes happen in the main process via a new desktop:write-clipboard-text IPC (LocalApi.clipboard.writeText), removing the document-focus dependency; browsers fall back to navigator.clipboard.
  • Two hardening fixes from review: macOS Ctrl+click no longer clobbers the selection in engines that report it as button 0 (Firefox), and a keyup whose keydown was consumed by the native menu no longer injects a release-only Kitty key sequence.

Ctrl+C without a selection stays SIGINT on every platform.

Why

Fixes #6173 — copying from the integrated terminal on macOS was broken enough to block work entirely (Cmd+C, the selection menu, and right-click Copy all failed in common flows).

UI Changes

Two visible deltas, both restoring expected behavior: the selection menu's Copy item now shows the ⌘C shortcut hint, and right-clicking a highlighted terminal selection shows the Add to chat / Copy menu instead of a generic menu with Copy disabled. Happy to attach screenshots on request.

Verification

  • New tests: real-WASM ABI test pinning selection formatting (single-line, multiline, and after subsequent PTY output), menu accelerator pass-through, main-process clipboard IPC at the schema boundary, drawer menu/right-click/refocus logic, macOS secondary-click predicate. ~310 of the 570 changed lines are tests.
  • Manually verified on macOS desktop: select → Cmd+C, blur/refocus → Cmd+C, and the unfocused-window right-click → Copy failure that the renderer-clipboard path produced.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Implemented by Claude Fable 5 via Claude Code.

🤖 Generated with Claude Code


Note

Medium Risk
Touches terminal input encoding, IPC clipboard, and native menu keyboard handling—user-visible on macOS but scoped to selection/copy flows with broad test coverage.

Overview
Fixes macOS integrated-terminal copy by routing every copy path (keyboard shortcut, auto-open selection menu, right-click) through one Ghostty-aware copySelectionText that writes via LocalApi.clipboard.writeText — on desktop, a new desktop:write-clipboard-text IPC to the main process so copies work when the renderer is unfocused (e.g. native context menus on inactive windows).

Selection menu & native menus: ContextMenuItem gains optional accelerator; ElectronMenu forwards non-empty accelerators so Cmd+C / Ctrl+Shift+C work while the menu tracks on macOS. The drawer shows Add to chat / Copy with platform chords, opens that menu on right-click when a Ghostty selection exists (not the generic DOM menu), reopens after dismiss-by-right-click, and refocuses the terminal after dismiss unless focus moved elsewhere.

Terminal input hardening: macOS Ctrl+click (button 0) no longer starts a new selection before context menu (isTerminalMacSecondaryClick). Key release to the PTY is only sent if that key’s press was encoded (encodedPressKeyCodes), avoiding release-only Kitty sequences when a native menu consumed the keydown.

Contracts expose accelerator on context menu items and clipboard.writeText / optional writeClipboardText on desktop bridge; web falls back to navigator.clipboard.

Reviewed by Cursor Bugbot for commit 6ab350a. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix terminal selection copy on macOS by routing clipboard writes through the main process

  • Adds a writeClipboardText IPC channel so the renderer can request clipboard writes via the Electron main process, working around renderer focus constraints that prevented navigator.clipboard.writeText from succeeding on macOS.
  • Adds a right-click context menu for terminal selections with platform-specific accelerators (Cmd+C on macOS, Ctrl+Shift+C elsewhere), auto-reopen after right-click dismissal, and focus restoration to the terminal after dismissal.
  • Fixes macOS Ctrl+click (reported as button 0 in some browsers) so it no longer clears an existing selection before opening the context menu.
  • Fixes stray Kitty key-release sequences by tracking which keypresses were encoded to the PTY and suppressing releases for keys whose press was consumed by an accelerator.
  • LocalApi.clipboard.writeText prefers desktopBridge.writeClipboardText on desktop and falls back to navigator.clipboard in the browser.

Macroscope summarized 6ab350a.

Copy entry points each resolved against a different owner — the renderer
shortcut handler, the native selection menu, and Electron's DOM-role
context menu — and only the first could see the Ghostty selection. Route
them all through one Ghostty-aware copy: the selection menu's Copy item
carries the platform copy accelerator so Cmd+C works while the open menu
owns the keyboard, right-click on a selection opens that same menu instead
of the DOM-role one, menu dismissal refocuses the terminal input, and the
clipboard write happens in the main process so it no longer depends on
renderer document focus.

Fixes pingdotgg#6173

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c922ce8c-5a01-479b-b982-dbd27c4604b4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 13, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 73c5815. Configure here.

Comment thread apps/web/src/components/ThreadTerminalDrawer.tsx
@macroscopeapp

macroscopeapp Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new IPC channel for main-process clipboard writes, new accelerator support for context menus, and substantial new runtime behavior for terminal selection handling on macOS. While well-tested, the scope goes beyond a simple bug fix—it introduces new capabilities and changes how clipboard operations route on desktop.

You can customize Macroscope's approvability policy. Learn more.

…sses it

A right-click that dismisses the open selection menu reaches the renderer
before the menu's IPC resolution does, so the gesture ended menu-less: the
contextmenu handler saw the menu still marked open and dropped the request.
Park that pointer instead, and when the menu settles as a dismissal reopen
at the parked position if the selection still exists. Any newer pointerdown
anywhere in the window, or a window blur, clears the parked pointer so a
long-delayed dismissal cannot reopen a menu the user has moved on from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: copying text from the integrated terminal is broken on mac

1 participant