Skip to content

Fix clipboard manager paste failing during focus transitions - #2435

Closed
alexander-pecheny wants to merge 2 commits into
manaflow-ai:mainfrom
alexander-pecheny:fix-clipboard-paste-synthetic-events
Closed

alexander-pecheny wants to merge 2 commits into
manaflow-ai:mainfrom
alexander-pecheny:fix-clipboard-paste-synthetic-events

Conversation

@alexander-pecheny

@alexander-pecheny alexander-pecheny commented Mar 31, 2026 •

Copy link
Copy Markdown

Human Summary

Text below the horizontal line is written by Claude. This is my human summary: I've had issues with raycast clipboard history not working ( #2415 ). This PR was made by Claude, but I've verified that it actually fixes the issue, AND that cmd-+ / − / 0 shortcuts to change zoom still work (commit making them work was the one that broke pasting). Feel free to reject / rewrite that, it is only as a proof of concept how this might be fixed.


Summary

  • Fix clipboard manager paste (Cmd+V) failing when overlays like Raycast or Tuna dismiss and send a synthetic key event during a focus transition
  • When the first responder is briefly the window itself (not the terminal), the main menu bypass doesn't fire — this detects that state and restores the terminal as first responder before dispatching

Problem

When a clipboard manager overlay dismisses and sends a synthetic Cmd+V, the window regains key status before the terminal view becomes first responder. The first responder is briefly the NSWindow itself, so:

  1. The main menu bypass doesn't fire (no terminal in the responder chain to validate paste:)
  2. The event falls through to the SwiftUI view hierarchy which swallows it

Fix

Detect when firstResponder is the window during a Command key equivalent, look up the focused terminal panel's GhosttyNSView, restore it as first responder, then dispatch to the main menu as usual.

Fixes #2415, related to #700

Test plan

  • Open cmux with a terminal focused
  • Use Raycast/Tuna clipboard manager to paste — verify Cmd+V works
  • Verify normal paste (without clipboard manager) still works
  • Verify other Command shortcuts (Cmd+C, Cmd+T, etc.) are unaffected

🤖 Posted by Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Restored reliable Command-key shortcut handling and menu navigation when a terminal is focused.
  • Behavior Changes

    • Copy-on-select no longer forces an inline startup override.
    • Split terminals now defer working-directory inheritance to configuration (no forced split cwd).
    • Non-release app variants skip the automatic updater.
    • App variants with certain bundle IDs use variant-specific socket paths.

When a clipboard manager overlay (Raycast, Tuna) dismisses and sends a
synthetic Cmd+V, the window regains key status before the terminal view
becomes first responder. The first responder is briefly the window itself
(AppKitWindow), so the main menu bypass doesn't fire (no terminal in the
responder chain to validate paste:), and the event falls through to the
SwiftUI view hierarchy which swallows it.

Fix: detect when the first responder is the window during a Command key
equivalent and restore the focused terminal's GhosttyNSView as first
responder before dispatching to the main menu.

Fixes manaflow-ai#2415, related to manaflow-ai#700

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Mar 31, 2026

Copy link
Copy Markdown

@alexander-pecheny is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Mar 31, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Window-level Command-key routing now recovers missing Ghostty first responders by searching subviews for a GhosttyNSView, restores focus, and then continues key-equivalent routing; the menu fast-path early return now only occurs when the menu actually consumes the event.

Changes

Cohort / File(s) Summary
Command-key focus recovery & routing
Sources/AppDelegate.swift
Added NSWindow.findGhosttyNSView(in:) recursive subview search; when firstResponderGhosttyView is nil but firstResponder is the NSWindow, locate and make the embedded GhosttyNSView first responder and adjust the menu-bypass conditional to return early only when consumedByMenu is true.
Ghostty config loading
Sources/GhosttyTerminalView.swift
Removed loadCopyOnSelectOverride(config) from default config loading so the TerminalCopyOnSelectSettings.overrideConfigLine() is no longer injected during initial/default config finalization.
Bundle-aware socket & updater gating
Sources/SocketControlSettings.swift, Sources/Update/UpdateController.swift
SocketControlSettings.defaultSocketPath(...) now returns a variant-specific /tmp/cmux-<suffix>.sock for non-release com.cmuxterm.app.* bundle IDs; UpdateController.startUpdaterIfNeeded() skips starting the updater when the bundle identifier is not exactly com.cmuxterm.app, logging the skip.
Working-directory / split behavior
Sources/TabManager.swift, Sources/Workspace.swift
TabManager.addWorkspace now computes a single workingDirectory from normalizedWorkingDirectory(...) (removing fallback snapshot logic) and uses it when scheduling git metadata refresh; split terminal creation in Workspace now passes workingDirectory: nil (removing custom split cwd resolution and its debug logging).

Sequence Diagram

sequenceDiagram
    actor User
    participant AppDelegate
    participant NSWindow
    participant ViewHierarchy as "Subview Tree"
    participant GhosttyNSView

    User->>AppDelegate: Press Cmd+<key>
    AppDelegate->>NSWindow: check firstResponder / ghostty owner
    alt firstResponderGhosttyView == nil && firstResponder is NSWindow
        AppDelegate->>ViewHierarchy: findGhosttyNSView(in: window.contentView)
        ViewHierarchy->>ViewHierarchy: recursively traverse subviews
        ViewHierarchy->>GhosttyNSView: locate GhosttyNSView
        AppDelegate->>NSWindow: makeFirstResponder(GhosttyNSView)
        NSWindow->>GhosttyNSView: focus restored
    end
    AppDelegate->>NSWindow: performKeyEquivalent -> menu check
    alt consumedByMenu == true
        NSWindow->>User: execute menu action
    else
        NSWindow->>GhosttyNSView: deliver key-equivalent to terminal
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I dug through views both wide and deep,
Found the Ghostty that had fallen asleep.
Gently I nudged, gave it back its light—
Now Cmd+keys hum through day and night. ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Most changes (AppDelegate, SocketControlSettings, UpdateController) appear tangential to the clipboard/paste fix. However, TabManager and Workspace changes removing fallback working-directory logic seem unrelated to the focus-transition paste issue. Clarify why working-directory changes and socket/updater changes are included in this PR if they address separate issues from clipboard paste failure during focus transitions.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: fixing clipboard manager paste during focus transitions, which is the core issue addressed by the PR.
Description check ✅ Passed The PR description includes a comprehensive summary of the problem, the fix approach, and a test plan covering the main use case.
Linked Issues check ✅ Passed The PR directly addresses #2415 by detecting focus transitions where the window is briefly first responder and restoring the terminal as first responder before dispatching paste events, preventing SwiftUI from swallowing the event.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix-clipboard-paste-synthetic-events

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 and usage tips.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 1 file

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/AppDelegate.swift`:
- Around line 12949-12953: Ensure the menu bypass is only set when we
successfully recovered a responder in the same window: when locating the
terminal panel via
AppDelegate.shared?.tabManager?.selectedWorkspace?.focusedTerminalPanel and its
Ghostty view found by Self.findGhosttyNSView(in:), first verify the
terminalPanel.hostedView.window === self (same NSWindow) and then call
self.makeFirstResponder(ghosttyNSView) and only assign menuBypassGhosttyView =
ghosttyNSView if makeFirstResponder returned true; apply the same checks before
enabling the menu bypass in the later block that sets the bypass (lines
~12960-12961).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76d9d23b-14ff-4e0d-81c7-0f217275805a

📥 Commits

Reviewing files that changed from the base of the PR and between 5835bff and e12f2a0.

📒 Files selected for processing (1)
  • Sources/AppDelegate.swift

Comment thread Sources/AppDelegate.swift
@greptile-apps

greptile-apps Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes Cmd+V paste failures that occur when a clipboard manager overlay (Raycast, Tuna, etc.) dismisses and sends a synthetic key event during an AppKit focus transition. When the overlay closes, the window regains key status before any view claims firstResponder, leaving NSWindow itself as the first responder momentarily. The existing main-menu bypass in cmux_performKeyEquivalent only fires when a GhosttyNSView is already in the responder chain, so it silently skipped and the event fell through to the broken SwiftUI focus path.

Changes:

  • Adds a focus-transition recovery block: when firstResponder is NSWindow and no GhosttyNSView is in the chain, the code looks up the focused terminal panel via AppDelegate.shared?.tabManager?.selectedWorkspace?.focusedTerminalPanel, walks its view tree with the new findGhosttyNSView(in:) helper to find the GhosttyNSView, and calls makeFirstResponder before proceeding with the existing main-menu bypass.
  • Adds findGhosttyNSView(in:) — a downward DFS through NSView.subviews to reach the GhosttyNSView nested inside GhosttySurfaceScrollView's private scroll+clip+document view layers.
  • Cleans up the empty if !consumedByMenu {} branch that preceded the else { return true } block.

Minor issue: The return value of self.makeFirstResponder(ghosttyNSView) is discarded. If the call fails (e.g., the hosted view is detached from the window hierarchy during a workspace transition), menuBypassGhosttyView is still set and the main-menu bypass fires unnecessarily — paste: validation fails against the window's responder chain, consumedByMenu is false, and the code falls through harmlessly, but checking the return value would make the guard explicit.

Confidence Score: 4/5

  • Safe to merge; the fix correctly handles the focus-transition case and the one remaining finding is a minor defensive coding improvement.
  • The logic is sound and consistent with the existing cmux_performKeyEquivalent patterns. The only issue is that makeFirstResponder's return value is discarded before setting menuBypassGhosttyView, which can cause a spurious but harmless redundant mainMenu.performKeyEquivalent call in the failure path. This is P2 and does not block merge, but warrants a follow-up fix for correctness clarity.
  • Sources/AppDelegate.swift — specifically the makeFirstResponder call at line 12952 where the return value should be guarded.

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Adds focus-transition recovery in cmux_performKeyEquivalent: when firstResponder is the window itself and a focused terminal panel exists, makeFirstResponder restores the terminal then the existing main-menu bypass fires. Also adds a downward DFS helper findGhosttyNSView(in:) and cleans up an empty if !consumedByMenu {} branch. Minor: the makeFirstResponder return value is discarded, so the bypass still fires even if first-responder restoration fails.

Sequence Diagram

sequenceDiagram
    participant CM as Clipboard Manager<br/>(Raycast/Tuna)
    participant OS as macOS
    participant Win as NSWindow
    participant PKE as cmux_performKeyEquivalent
    participant FR as firstResponder<br/>(NSWindow self)
    participant TP as focusedTerminalPanel
    participant GNV as GhosttyNSView
    participant Menu as NSApp.mainMenu

    CM->>OS: Dismiss overlay + send synthetic Cmd+V
    OS->>Win: Window becomes key (focus transition)
    Note over Win,FR: firstResponder = NSWindow itself<br/>(terminal not yet first responder)
    OS->>PKE: performKeyEquivalent(Cmd+V)
    PKE->>PKE: firstResponderGhosttyView = nil<br/>(window is FR, not a GhosttyNSView)
    PKE->>PKE: menuBypassGhosttyView = nil
    PKE->>PKE: self.firstResponder is NSWindow? ✓
    PKE->>TP: AppDelegate.shared?.tabManager?<br/>.selectedWorkspace?.focusedTerminalPanel
    TP-->>PKE: terminalPanel
    PKE->>GNV: findGhosttyNSView(in: terminalPanel.hostedView)
    GNV-->>PKE: ghosttyNSView
    PKE->>Win: makeFirstResponder(ghosttyNSView)
    Win->>GNV: becomeFirstResponder()
    GNV-->>Win: true
    PKE->>PKE: menuBypassGhosttyView = ghosttyNSView
    PKE->>Menu: mainMenu.performKeyEquivalent(Cmd+V)
    Menu->>GNV: paste: (via responder chain)
    GNV-->>Menu: handled ✓
    Menu-->>PKE: consumedByMenu = true
    PKE-->>OS: return true
Loading

Reviews (1): Last reviewed commit: "Fix clipboard manager paste failing duri..." | Re-trigger Greptile

Comment thread Sources/AppDelegate.swift Outdated
Comment on lines +12952 to +12953
self.makeFirstResponder(ghosttyNSView)
menuBypassGhosttyView = ghosttyNSView

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.

P2 makeFirstResponder return value unchecked

makeFirstResponder can return false when the view is not currently in the window's view hierarchy (e.g., the hosted view is detached during a workspace transition). In that case, menuBypassGhosttyView is still set to ghosttyNSView, so the code proceeds with mainMenu.performKeyEquivalent(with: event) even though the first responder was not actually restored. paste: validation then runs against the window's own responder chain (which has no terminal), consumedByMenu is false, and the code falls through to cmux_performKeyEquivalent — so the paste still fails, but the bypass fires unnecessarily.

Gating the assignment on the return value makes the intent explicit and avoids the spurious menu invocation:

Suggested change
self.makeFirstResponder(ghosttyNSView)
menuBypassGhosttyView = ghosttyNSView
if self.makeFirstResponder(ghosttyNSView) {
menuBypassGhosttyView = ghosttyNSView

You'd also need a closing } after the #if DEBUG block at line 12957.

… success

Check that the recovered GhosttyNSView belongs to the current window and
that makeFirstResponder actually succeeds before enabling the menu bypass.
Without these guards, the bypass could fire with no valid terminal responder
if the view is detached or belongs to a different window.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Sources/AppDelegate.swift (1)

12948-12958: Add a regression test for the recovered-responder path.

An AppDelegateShortcutRoutingTests case that forces firstResponder === window for synthetic Cmd+V—and a Cmd+` variant—would lock in this recovery path and guard the native window-cycling behavior while this responder swap is in place.

Based on learnings, "Cmd+ (command-backtick, keyCode 50) is intentionally excluded from direct menu routing by shouldRouteCommandEquivalentDirectlyToMainMenu; tests assert this behavior. Do not add a window/main-menu bypass for Cmd+."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/AppDelegate.swift` around lines 12948 - 12958, Add a regression test
in AppDelegateShortcutRoutingTests that simulates the recovered-responder path
by forcing AppDelegate.firstResponder to be the NSWindow (so
menuBypassGhosttyView starts nil) and then exercising the synthetic Cmd+V and
Cmd+` paths; verify that when the code path in AppDelegate that uses
findGhosttyNSView(in:), checks
selectedWorkspace?.focusedTerminalPanel.hostedView, and calls
makeFirstResponder(ghosttyNSView) it restores menuBypassGhosttyView and allows
Cmd+V menu routing, but do not change behavior for keyCode 50 (Cmd+`)—assert
shouldRouteCommandEquivalentDirectlyToMainMenu still excludes Cmd+` and that no
window/main-menu bypass is added for that key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/AppDelegate.swift`:
- Around line 12948-12958: Add a regression test in
AppDelegateShortcutRoutingTests that simulates the recovered-responder path by
forcing AppDelegate.firstResponder to be the NSWindow (so menuBypassGhosttyView
starts nil) and then exercising the synthetic Cmd+V and Cmd+` paths; verify that
when the code path in AppDelegate that uses findGhosttyNSView(in:), checks
selectedWorkspace?.focusedTerminalPanel.hostedView, and calls
makeFirstResponder(ghosttyNSView) it restores menuBypassGhosttyView and allows
Cmd+V menu routing, but do not change behavior for keyCode 50 (Cmd+`)—assert
shouldRouteCommandEquivalentDirectlyToMainMenu still excludes Cmd+` and that no
window/main-menu bypass is added for that key.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab5105a8-8ef2-46c1-8112-c917caae47cb

📥 Commits

Reviewing files that changed from the base of the PR and between e12f2a0 and 99eeec8.

📒 Files selected for processing (1)
  • Sources/AppDelegate.swift

@cubic-dev-ai

cubic-dev-ai Bot commented Apr 7, 2026

Copy link
Copy Markdown

This review could not be run because your cubic account has exceeded the monthly review limit. If you need help restoring access, please contact contact@cubic.dev.

@alexander-pecheny
alexander-pecheny force-pushed the fix-clipboard-paste-synthetic-events branch from da2e4ba to 99eeec8 Compare April 7, 2026 13:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/Update/UpdateController.swift`:
- Around line 104-107: The updater-disabled bundle check
(Bundle.main.bundleIdentifier != "com.cmuxterm.app") is currently used only at
startup but manual flows still enter readiness-retry and can produce the
misleading "Updater is still starting…" timeout; modify
UpdateController.checkForUpdates and UpdateController.checkForUpdatesWhenReady
to short-circuit when the bundle is updater-disabled by checking the same
Bundle.main.bundleIdentifier condition up-front and returning early (no-op) or
appending a clear disabled message via UpdateLogStore.shared.append (e.g.,
"updater disabled (non-release bundle)"), so the readiness-retry path is never
entered for disabled bundles.

In `@Sources/Workspace.swift`:
- Around line 7492-7500: The change sets workingDirectory: nil when constructing
TerminalPanel (in the TerminalPanel(...) call using workspaceId: id, context:
GHOSTTY_SURFACE_CONTEXT_SPLIT, configTemplate: inheritedConfig) which
unintentionally alters split-terminal CWD behavior; revert this by restoring the
prior cmux fallback resolution (i.e., pass through the previous workingDirectory
value or restore the logic that computed the fallback CWD instead of forcing
nil) or remove the workingDirectory change from this PR and move it to a
dedicated split-CWD PR with tests for split terminal cwd behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4ba707f-3825-4e63-831f-057a1fb4f511

📥 Commits

Reviewing files that changed from the base of the PR and between 99eeec8 and da2e4ba.

📒 Files selected for processing (5)
  • Sources/GhosttyTerminalView.swift
  • Sources/SocketControlSettings.swift
  • Sources/TabManager.swift
  • Sources/Update/UpdateController.swift
  • Sources/Workspace.swift
💤 Files with no reviewable changes (1)
  • Sources/GhosttyTerminalView.swift

Comment thread Sources/Update/UpdateController.swift Outdated
Comment on lines +104 to +107
if Bundle.main.bundleIdentifier != "com.cmuxterm.app" {
UpdateLogStore.shared.append("updater skipped (non-release bundle: \(Bundle.main.bundleIdentifier ?? "nil"))")
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle the updater-disabled path explicitly in update-check flows.

Line 104 intentionally skips updater startup for non-release bundles, but the manual check path can still run readiness retries and end in the misleading timeout error (“Updater is still starting…”). Please short-circuit checkForUpdates / checkForUpdatesWhenReady when this bundle is updater-disabled (no-op or dedicated disabled message), instead of entering startup-retry state.

Suggested fix sketch
 class UpdateController {
+    private var isUpdaterDisabledForCurrentBundle: Bool {
+        Bundle.main.bundleIdentifier != "com.cmuxterm.app"
+    }

     func startUpdaterIfNeeded() {
         guard !didStartUpdater else { return }
-        if Bundle.main.bundleIdentifier != "com.cmuxterm.app" {
+        if isUpdaterDisabledForCurrentBundle {
             UpdateLogStore.shared.append("updater skipped (non-release bundle: \(Bundle.main.bundleIdentifier ?? "nil"))")
             return
         }
         ...
     }

     func checkForUpdatesWhenReady(retries: Int = 10) {
+        guard !isUpdaterDisabledForCurrentBundle else {
+            UpdateLogStore.shared.append("checkForUpdates skipped (updater disabled for this bundle)")
+            return
+        }
         ...
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Update/UpdateController.swift` around lines 104 - 107, The
updater-disabled bundle check (Bundle.main.bundleIdentifier !=
"com.cmuxterm.app") is currently used only at startup but manual flows still
enter readiness-retry and can produce the misleading "Updater is still
starting…" timeout; modify UpdateController.checkForUpdates and
UpdateController.checkForUpdatesWhenReady to short-circuit when the bundle is
updater-disabled by checking the same Bundle.main.bundleIdentifier condition
up-front and returning early (no-op) or appending a clear disabled message via
UpdateLogStore.shared.append (e.g., "updater disabled (non-release bundle)"), so
the readiness-retry path is never entered for disabled bundles.

Comment thread Sources/Workspace.swift Outdated
Comment on lines +7492 to +7500
// Let Ghostty handle working directory via its own
// working-directory / split-inherit-working-directory config.

// Create the new terminal panel.
let newPanel = TerminalPanel(
workspaceId: id,
context: GHOSTTY_SURFACE_CONTEXT_SPLIT,
configTemplate: inheritedConfig,
workingDirectory: splitWorkingDirectory,
workingDirectory: nil,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This introduces an out-of-scope split-CWD behavior change in a paste-fix PR.

Line 7500 now forces workingDirectory: nil, which changes split terminal cwd behavior and is unrelated to the clipboard-routing objective. Please either move this to a dedicated PR with split-cwd regression coverage, or keep prior cmux fallback resolution in this PR.

Suggested revert (if this PR should stay scoped to clipboard paste)
-        // Let Ghostty handle working directory via its own
-        // working-directory / split-inherit-working-directory config.
+        let splitWorkingDirectory = panelDirectories[panelId]
+            ?? terminalPanel(for: panelId)?.requestedWorkingDirectory
+            ?? currentDirectory

         // Create the new terminal panel.
         let newPanel = TerminalPanel(
             workspaceId: id,
             context: GHOSTTY_SURFACE_CONTEXT_SPLIT,
             configTemplate: inheritedConfig,
-            workingDirectory: nil,
+            workingDirectory: splitWorkingDirectory,
             portOrdinal: portOrdinal,
             initialCommand: remoteTerminalStartupCommand
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Workspace.swift` around lines 7492 - 7500, The change sets
workingDirectory: nil when constructing TerminalPanel (in the TerminalPanel(...)
call using workspaceId: id, context: GHOSTTY_SURFACE_CONTEXT_SPLIT,
configTemplate: inheritedConfig) which unintentionally alters split-terminal CWD
behavior; revert this by restoring the prior cmux fallback resolution (i.e.,
pass through the previous workingDirectory value or restore the logic that
computed the fallback CWD instead of forcing nil) or remove the workingDirectory
change from this PR and move it to a dedicated split-CWD PR with tests for split
terminal cwd behavior.

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Thanks for this! The Raycast paste focus fix landed on main in #2768. You opened this first, so you got there first. Closing since main covers it now.

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.

Raycast Clipboard History text does not paste in cmux, while tmux works

2 participants