Skip to content

Adds support for shortcut passthrough to browser - #4724

Open
jcrsilva wants to merge 5 commits into
manaflow-ai:mainfrom
jcrsilva:feature/keyboard_passthrough
Open

jcrsilva wants to merge 5 commits into
manaflow-ai:mainfrom
jcrsilva:feature/keyboard_passthrough

Conversation

@jcrsilva

@jcrsilva jcrsilva commented May 25, 2026 •

Copy link
Copy Markdown

Summary

New config option added under "browser" allowing for certain keyboard shortcuts which right now are intercepted by tmux to passthough to the embedded browser when in configured hosts.

This has potentially other applications but the intent is to tackle this class of issue, to more easily allow people to run web-based IDEs such as code-server in the integrated cmux browser.

Testing

  • Unit tests added verifying the passthrough behavior
  • Unit test ensuring original behavior is kept if host does not match list
  • Manual testing via dev built, running code-server

Demo Video

Need to add one later, can't record rn.

Checklist

  • I tested the change locally
  • I added or updated tests for behavior changes
  • I updated docs/changelog if needed
  • I requested bot reviews after my latest commit (copy/paste block above or equivalent)
  • All code review bot comments are resolved
  • All human review comments are resolved

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Summary by cubic

Adds per‑host Cmd‑shortcut passthrough to the embedded browser so pages can handle Cmd+P, Cmd+Shift+P, Cmd+F, etc. Default behavior is unchanged; if a page doesn’t consume a chord, normal menu handling resumes.

  • New Features

    • Added browser.shortcutPassthroughHosts allowlist (exact hosts and *.example.com, ports ignored). On match, cmux forwards Cmd‑modifier chords to the page first at the event monitor, window, and webview layers; omnibar and Web Inspector excluded.
    • Expanded editor‑like arrow routing: Shift+Arrow, Option+Arrow, Shift+Option+Arrow, and Cmd+Shift+Up/Down route via keyDown to WebKit. Cmd+Option+Arrow stays reserved for pane focus.
    • Integrated config into settings file parsing, web/data/cmux.schema.json, docs, and localized descriptions; added tests for passthrough policy, host matching, arrow routing, and WebView/menu fallthrough.
  • Refactors

    • Cached parsed shortcutPassthroughHosts to avoid reparsing on every Cmd keystroke.

Written for commit 2a5fd3c. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Per‑URL Cmd‑modifier passthrough: configure hosts that receive Cmd‑key shortcuts first (exact and *.wildcard support); app falls back if page doesn’t consume.
    • Added persisted host allowlist and caching for performance.
  • Behavior Changes

    • Broader arrow‑key routing: Shift/Option combos and Cmd+Shift at document boundaries now forward to pages when appropriate.
  • Bug Fixes

    • Prevents Cmd+Option+Arrow (and related combos) from being forwarded, preserving app shortcuts.
  • Documentation

    • Updated schema, examples, and localized docs.
  • Tests

    • Added unit/UI tests for passthrough matching and arrow‑key routing.

Review Change Stack

@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown

@jcrsilva 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 May 25, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds per-URL Command-modifier passthrough so allowlisted embedded pages receive Cmd-key equivalents first; integrates the policy into AppDelegate and CmuxWebView, expands browser arrow-key routing, updates settings parsing/schema/example, adds tests, and localizes docs.

Changes

Per-URL Cmd Shortcut Passthrough with Arrow Routing

Layer / File(s) Summary
Passthrough host allowlist configuration
Sources/Panels/BrowserPanel.swift, Sources/Panels/CmuxWebView.swift
BrowserLinkOpenSettings adds shortcutPassthroughHostsKey, a default, shortcutPassthroughHosts(...) accessor, and hostMatchesShortcutPassthrough(_:) / urlMatchesShortcutPassthrough(_:) to normalize and match hosts (supports *. wildcards; empty list returns false).
Settings parser, JSON path, schema, and example
Sources/KeyboardShortcutSettingsFileStore.swift, Sources/CmuxSettingsJSONPathSupport.swift, web/data/cmux.schema.json, web/app/[locale]/docs/configuration/page.tsx
Parser recognizes browser.shortcutPassthroughHosts array (trims, filters empty entries) and persists it; supported settings JSON paths and schema updated; example config template documents the new key.
Passthrough policy helper
Sources/App/BrowserShortcutPassthroughPolicy.swift
Adds shouldPassthroughCommandEquivalentToWebContent(_ event: NSEvent, responder: NSResponder? = nil, url: URL?, defaults: UserDefaults = .standard) -> Bool that checks for Command modifier, excludes inspector-like responders, and delegates URL allowlist matching to BrowserLinkOpenSettings.urlMatchesShortcutPassthrough.
AppDelegate passthrough integration
Sources/AppDelegate.swift
handleCustomShortcut and cmux_performKeyEquivalent add early per-URL allowlist checks to defer to WebKit when the focused CmuxWebView is allowlisted (omitting omnibar); cmuxOwningWebView visibility changed to fileprivate.
CmuxWebView passthrough guard
Sources/Panels/CmuxWebView.swift
performKeyEquivalent(with:) now early-calls super.performKeyEquivalent(with:) for allowlisted URLs so WebKit receives Cmd-modifier equivalents first, with a DEBUG log; later cmux routing is skipped if passthrough matched.
Browser arrow-key dispatch expansion
Sources/App/ShortcutRoutingSupport.swift
shouldDispatchBrowserArrowViaFirstResponderKeyDown implements an explicit modifier matrix: allows Shift/Option/Shift+Option arrow navigation, allows Cmd+Up/Down and Cmd+Shift+Up/Down at document boundaries, and explicitly blocks Cmd+Option+Arrow.
Test coverage
cmuxTests/BrowserShortcutPassthroughTests.swift, cmuxTests/BrowserArrowKeyForwardingTests.swift, cmuxTests/BrowserConfigTests.swift
New tests for passthrough host matching (isolated UserDefaults), AppDelegate/WebView passthrough behavior, and arrow-key routing (selection/word-jump modifiers and regression guards for Cmd+Option+Arrow).
Project file integration
cmux.xcodeproj/project.pbxproj
Adds PBX entries so the new policy source and UITests file are referenced and compiled into the proper targets.
Docs / i18n
web/messages/*, web/app/[locale]/docs/configuration/page.tsx
Adds schemaDescriptions.browser.shortcutPassthroughHosts localized strings and updates the settings example to show shortcutPassthroughHosts.

Sequence Diagram

sequenceDiagram
  participant AppDelegate
  participant CmuxWebView
  participant BrowserPolicy
  participant WebKit
  AppDelegate->>CmuxWebView: key-equivalent event / focused webView check
  CmuxWebView->>BrowserPolicy: shouldPassthroughCommandEquivalentToWebContent(event,responder,url)
  BrowserPolicy-->>CmuxWebView: allowlist result (true/false)
  alt allowlisted && Cmd-modifier
    CmuxWebView->>WebKit: super.performKeyEquivalent(with:)
    WebKit-->>CmuxWebView: consumed? (true/false)
    alt consumed
      CmuxWebView-->>AppDelegate: consume (suppress menu)
    else not consumed
      AppDelegate-->>WebKit: fallback menu/AppKit handling
    end
  else not allowlisted
    AppDelegate-->>WebKit: normal cmux shortcut handling / menu dispatch
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#1846: Touches Cmd/Option+arrow routing semantics similar to this change.
  • manaflow-ai/cmux-dev-artifacts#1817: Affects arrow-key routing used by find/up-down behaviors that this PR modifies.

Possibly related PRs

Poem

🐰 I nudged a key, it passed the gate,

Cmd hopped through, on a whitelist straight.
Arrows learned lanes with modest art,
Hosts and shortcuts play their part,
A little rabbit cheers with heart.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error PR introduces NSLock in keyboard event hot path (ShortcutPassthroughHostsCache in performKeyEquivalent call chain), violating blocking runtime rule that input/focus paths are latency-sensitive. Replace NSLock with MainActor-isolated cache or use UserDefaults-backed lazy property; keyboard events shouldn't need manual synchronization on main thread.
Cmux Architecture Rethink ❌ Error PR introduces NSLock-based mutable cache in hot keystroke path (fires 3x/Cmd event), violating architectural rule against "blocking repair paths (locks...)" for performance. Replace NSLock cache with UserDefaults observer-based invalidation or consolidate three passthrough entry points to single call site, eliminating locks in keystroke dispatch path.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (15 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Adds support for shortcut passthrough to browser' clearly summarizes the main feature introduced: enabling keyboard shortcut passthrough to the embedded browser for configured hosts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed shouldPassthroughCommandEquivalentToWebContent marked @MainActor; ShortcutPassthroughHostsCache marked @unchecked Sendable with documented NSLock protection; all calls from MainActor contexts.
Cmux No Hacky Sleeps ✅ Passed No hacky sleeps/delays in non-Swift code. Changes are Swift source/test files (out of scope), TypeScript docs (no timing patterns), JSON schema/translations, and submodule update.
Cmux Algorithmic Complexity ✅ Passed User-configured host allowlist (1-10 entries) with caching implemented; no scalable-collection violations. Fits "small fixed-size collections" pass criterion like modifier keys.
Cmux Swift Concurrency ✅ Passed PR introduces no legacy async patterns: synchronous design with @MainActor function, NSLock cache, no DispatchQueue.global/Task/Combine additions, proper test isolation.
Cmux Swift @Concurrent ✅ Passed New @MainActor function is synchronous; helper functions are synchronous static methods; cache properly uses @unchecked Sendable with locks; no invalid @concurrent usage.
Cmux Swift File And Package Boundaries ✅ Passed New 36-line file is focused policy logic; +62 and +73 line additions are under 250-line threshold for oversized files; touching existing oversized files incidentally is allowed.
Cmux Swift Logging ✅ Passed All logging in the PR complies with swift-logging.md: new DEBUG logs are properly guarded by #if DEBUG, no print/NSLog/debugPrint/dump in app code, and no ad hoc logging violations.
Cmux User-Facing Error Privacy ✅ Passed No user-facing error privacy violations. Error messages use privacy masking; documentation is safe; debug logs are guarded with #if DEBUG; no credentials or sensitive info exposed.
Cmux Full Internationalization ✅ Passed All 20 locales have complete translations for shortcutPassthroughHosts in web/messages; no new hardcoded user-facing Swift strings; test files exempt from i18n.
Cmux Swiftui State Layout ✅ Passed PR adds only utility functions and AppKit event handlers. No new @Published, @Observable state, GeometryReader layout changes, or render-time mutations detected.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR adds no user-visible NSWindow/NSPanel/NSWindowController/SwiftUI windows. Two NSWindow test fixtures (allowed case per rule) in test-only functions. All changes are keyboard routing logic.
Description check ✅ Passed PR description covers the feature (browser shortcut passthrough), testing (unit tests + manual), and uses most checklist items, though a demo video is deferred.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@jcrsilva

Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@cubic-dev-ai

cubic-dev-ai Bot commented May 25, 2026

Copy link
Copy Markdown

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@jcrsilva I have started the AI code review. It will take a few minutes to complete.

@socket-security

socket-security Bot commented May 25, 2026 •

Copy link
Copy Markdown

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@jcrsilva — reviewed the PR. The overall design is solid (opt-in allowlist, correct empty-list default, good unit test coverage for the matching logic, and the arrow-key routing improvements are well guarded). A few things worth addressing:


🔴 Critical: Cmd+Q / Cmd+W / app-level shortcuts can be silently swallowed

In NSWindow.performKeyEquivalent, when a host matches you unconditionally return true even when WebKit itself returns false:

let result = firstResponderWebView.performKeyEquivalent(with: event)
// …
// Always return true so AppKit does not fall through to the main menu …
return true

This means if WebKit doesn't handle the event (e.g. Cmd+Q, Cmd+W, Cmd+M, Cmd+`, Cmd+Tab), the event is swallowed entirely — the app cannot be quit while a passthrough-host URL is focused. A minimal safeguard:

// Only suppress the fall-through when WebKit actually consumed the event.
// For events WebKit ignores, let AppKit continue (main-menu, system, etc.).
if result { return true }
// Critical app-level shortcuts should always reach AppKit regardless.
let criticalKeyCodes: Set<UInt16> = [12 /*Q*/, 13 /*W*/, 46 /*M*/]
if criticalKeyCodes.contains(event.keyCode) { return false }
return result

At minimum, please re-examine whether always returning true is intentional and document why, or add the result-conditional return.


🟡 MainActor.assumeIsolated without @MainActor annotation

shouldPassthroughCommandEquivalentToWebContent uses MainActor.assumeIsolated { webView.url } but is not itself annotated @MainActor. If it's ever called off the main thread the runtime precondition fires. Since all three call sites are on the main thread today, marking the function @MainActor is the safer contract:

`@MainActor`
func shouldPassthroughCommandEquivalentToWebContent(
    _ event: NSEvent,
    responder: NSResponder? = nil,
    owningWebView: CmuxWebView? = nil,
    defaults: UserDefaults = .standard
) -> Bool {
    // …
    let url: URL? = webView.url   // no longer needs assumeIsolated
    // …
}

🟡 Performance: shortcutPassthroughHosts() parses UserDefaults on every Cmd key event

shortcutPassthroughHosts() splits a newline-delimited string and filters it on every invocation. With three call sites per event (AppDelegate → NSWindow → CmuxWebView) this runs on every Cmd keystroke. Consider caching the parsed array on a UserDefaults.didChangeNotification observer, or at least consolidating to a single call site.


🟡 Triple passthrough check — CmuxWebView path may be redundant

The passthrough guard appears in:

  1. AppDelegate (returns false early to bail the configured-shortcut path)
  2. NSWindow.performKeyEquivalent (calls WebKit and returns true)
  3. CmuxWebView.performKeyEquivalent (calls super and returns)

The comment in AppDelegate says the intent is for the event to flow into CmuxWebView.performKeyEquivalent through the normal chain, but NSWindow's guard intercepts it first and already forwards to WebKit. If NSWindow always fires before CmuxWebView is reached directly, the check in CmuxWebView is dead code. Please clarify or document the scenario where #3 is needed.


🟡 cmuxOwningWebView visibility escalation

cmuxOwningWebView was widened from private to fileprivate static solely to let the new AppDelegate code reach it. If AppDelegate is in the same file as the NSWindow extension, fileprivate is equivalent to the extension's scope — that may be fine, but it's worth a comment explaining the intentional visibility change.


🟢 Minor: wildcard-matches-apex behavior should be in schema description

The test correctly documents that *.example.com also matches the apex example.com (consistent with hostsToOpenInEmbeddedBrowser). This could surprise users, so it's worth a brief note in the JSON schema description field alongside the existing wildcard mention.


✅ What looks good

  • Empty-list default preserves existing behavior — the key safety property is correctly enforced.
  • cmuxIsLikelyWebInspectorResponder guard prevents the Web Inspector from being hijacked.
  • Omnibar exclusion (browserOmnibarPanelId == nil) is in both call sites.
  • Test isolation with per-suite UserDefaults and teardown blocks is clean.
  • Arrow-key regression guards (Cmd+Option+Arrow stays with cmux) are explicit and well-tested.
  • Schema + docs updated in the same PR.

@greptile-apps

greptile-apps Bot commented May 25, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a browser.shortcutPassthroughHosts config option that lets users route Cmd-modifier chords to web content first when the focused browser URL matches an allowlist, enabling web IDEs like code-server to receive Cmd+P, Cmd+F, etc. Default behavior is unchanged; if the page does not consume a chord, cmux's normal menu dispatch continues.

  • Passthrough is enforced at three layers (local event monitor, NSWindow swizzle, CmuxWebView) with clear reasoning for each; @MainActor annotation on shouldPassthroughCommandEquivalentToWebContent replaces the prior MainActor.assumeIsolated runtime trap with a compile-time guarantee.
  • Arrow-routing is broadened to include Shift+Arrow, Option+Arrow, Shift+Option+Arrow, and Cmd+Shift+Up/Down for text-selection chords; Cmd+Option+Arrow is explicitly guarded for cmux pane focus.
  • All 20 locale files receive translated descriptions for the new setting, and the JSON schema accurately describes the fall-through behavior for system shortcuts.

Confidence Score: 5/5

Safe to merge; default behavior is unchanged and the passthrough is fully opt-in via an empty-default allowlist.

The three-layer dispatch architecture is well-reasoned and correctly propagates WebKit's return value so system shortcuts fall through when pages don't consume them. The @mainactor annotation fixes the prior runtime-trap concern. One locking pattern in the host cache can produce a transient stale entry under concurrent off-main-actor access, but all current callers go through @mainactor code paths, making the practical impact nil.

The ShortcutPassthroughHostsCache in Sources/Panels/BrowserPanel.swift is worth a second look if BrowserLinkOpenSettings.shortcutPassthroughHosts is ever called from a non-main-actor context in the future.

Important Files Changed

Filename Overview
Sources/App/BrowserShortcutPassthroughPolicy.swift New 36-line focused file; @mainactor annotation gives compile-time isolation guarantee; takes URL? instead of WKWebView for testability. Clean.
Sources/App/ShortcutRoutingSupport.swift Extends arrow-routing to Shift+Arrow, Option+Arrow, Shift+Option+Arrow, and Cmd+Shift+Up/Down; correctly guards Cmd+Option+Arrow for cmux pane focus; horizontal Cmd+Shift arrows deliberately excluded.
Sources/AppDelegate.swift Adds passthrough checks at two points (local event monitor and NSWindow swizzle); NSWindow block correctly propagates WebKit's return value so fall-through to AppKit menu happens when page doesn't consume the chord; cmuxOwningWebView visibility widened to fileprivate with clear justification.
Sources/Panels/BrowserPanel.swift Adds ShortcutPassthroughHostsCache singleton with @unchecked Sendable + NSLock; stale-write window exists if cache is ever accessed from a non-main-actor context (locking pattern does not re-validate before writing).
Sources/Panels/CmuxWebView.swift Adds passthrough guard at the WKWebView layer with clear reasoning for why the check is not redundant; returns super.performKeyEquivalent and skips cmux main-menu forwarding only on a passthrough match.
Sources/KeyboardShortcutSettingsFileStore.swift Parses shortcutPassthroughHosts string array and joins with newlines for storage; logs invalid entries; consistent with other browser-section parsers.
web/data/cmux.schema.json New shortcutPassthroughHosts array field with descriptionKey pointing to locale messages; description accurately states Cmd+Q fall-through behavior and wildcard semantics.
web/messages/en.json Adds shortcutPassthroughHosts description; all 20 locale files were updated with per-language translations.

Sequence Diagram

sequenceDiagram
    participant EM as Local Event Monitor
    participant WS as NSWindow Swizzle
    participant WV as CmuxWebView
    participant WK as WebKit
    participant MM as AppKit Main Menu

    Note over EM,MM: Cmd-modifier keystroke on a passthrough host

    EM->>EM: shouldPassthroughCommandEquivalentToWebContent?
    alt Host matches allowlist
        EM-->>WS: return false (let event flow)
    else No match
        EM-->>MM: event consumed by configured shortcut
    end

    WS->>WS: shouldPassthroughCommandEquivalentToWebContent?
    alt Host matches allowlist
        WS->>WV: performKeyEquivalent(event)
        WV->>WV: shouldPassthroughCommandEquivalentToWebContent?
        WV->>WK: super.performKeyEquivalent(event)
        WK-->>WV: consumed (true/false)
        WV-->>WS: result
        alt WebKit consumed chord
            WS-->>EM: return true
        else WebKit did not consume
            WS->>MM: fall through to standard dispatch
            MM-->>EM: Cmd+Q / Cmd+W / etc. handled normally
        end
    else No match
        WS->>MM: normal cmux shortcut ladder
    end
Loading

Reviews (14): Last reviewed commit: "Sync swift-file-length-budget.tsv to pos..." | Re-trigger Greptile

Comment thread Sources/App/ShortcutRoutingSupport.swift Outdated
Comment thread web/app/[locale]/docs/configuration/page.tsx Outdated
Comment thread Sources/AppDelegate.swift
@greptile-apps

greptile-apps Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a new browser.shortcutPassthroughHosts config option that routes all Cmd-modifier key equivalents directly to the embedded WKWebView (bypassing cmux menus and configured shortcuts) when the current page's hostname matches the allowlist. The default empty list preserves existing behaviour unchanged.

  • BrowserPanel.swift adds host-matching helpers reusing the existing normalizeWhitelistPattern/hostMatchesPattern machinery; KeyboardShortcutSettingsFileStore and CmuxSettingsJSONPathSupport wire the new key through the settings pipeline.
  • Two intercept points are added in AppDelegate: handleCustomShortcut returns false early (clearing chord state) so the event flows to AppKit, and NSWindow.performKeyEquivalent catches it and unconditionally returns true after handing it to WebKit — ensuring the main menu never fires on a matched host.
  • The arrow-key forwarding expansion (shouldDispatchBrowserArrowViaFirstResponderKeyDown) is independent and well-tested; it correctly guards Cmd+Option+Arrow for cmux pane focus.

Confidence Score: 3/5

Safe to merge once the @mainactor annotation is added; the unconditional true-return design is worth a second look before shipping.

The new shouldPassthroughCommandEquivalentToWebContent function accesses a @MainActor-isolated WKWebView property through a runtime-only assertion (MainActor.assumeIsolated) rather than a compile-time annotation. All current call sites are on the main thread, so it won't crash today, but the missing annotation leaves no compiler-enforced safety net for future refactors. The NSWindow intercept also unconditionally swallows every Cmd-equivalent on a passthrough host — including chords WebKit doesn't handle — which could silently kill shortcuts like Cmd+Q for users who list a broad host like localhost.

Sources/App/ShortcutRoutingSupport.swift (missing @mainactor), Sources/AppDelegate.swift (unconditional true return in NSWindow passthrough)

Important Files Changed

Filename Overview
Sources/App/ShortcutRoutingSupport.swift Adds shouldPassthroughCommandEquivalentToWebContent free function using MainActor.assumeIsolated without @mainactor annotation; also expands shouldDispatchBrowserArrowViaFirstResponderKeyDown with new arrow-key combos
Sources/AppDelegate.swift Two passthrough intercept points added: handleCustomShortcut early-exits (returns false) and NSWindow.performKeyEquivalent unconditionally returns true; cmuxOwningWebView visibility widened from private to fileprivate
Sources/Panels/BrowserPanel.swift Adds shortcutPassthroughHostsKey, shortcutPassthroughHosts(), hostMatchesShortcutPassthrough(), and urlMatchesShortcutPassthrough() — mirrors existing hostMatchesWhitelist pattern with the correct inverted empty-list default (false instead of true)
Sources/Panels/CmuxWebView.swift Adds passthrough fast-path before existing menu/replay machinery in performKeyEquivalent; logic is correct and consistent with the NSWindow intercept
cmuxTests/BrowserShortcutPassthroughTests.swift New test file covering empty-allowlist default, exact host match, wildcard subdomain, URL port stripping, nil/scheme-only URL, and whitespace-stripping — good coverage of the new BrowserLinkOpenSettings API

Sequence Diagram

sequenceDiagram
    participant EM as Local Event Monitor
    participant AD as AppDelegate.handleCustomShortcut
    participant NW as NSWindow.performKeyEquivalent
    participant CWV as CmuxWebView.performKeyEquivalent
    participant WK as WKWebView (super)
    participant Menu as NSApp Main Menu

    EM->>AD: NSEvent (Cmd+key)
    AD->>AD: shouldPassthroughCommandEquivalentToWebContent?
    alt host matches allowlist
        AD-->>EM: false (chord cleared, event flows to AppKit)
        EM->>NW: performKeyEquivalent
        NW->>NW: shouldPassthroughCommandEquivalentToWebContent?
        NW->>CWV: performKeyEquivalent
        CWV->>CWV: shouldPassthroughCommandEquivalentToWebContent?
        CWV->>WK: super.performKeyEquivalent
        WK-->>CWV: handled / not handled
        CWV-->>NW: result
        NW-->>EM: true (always — menu blocked)
    else host not in allowlist
        AD->>AD: normal shortcut dispatch
        AD-->>EM: true/false
        Note over NW,Menu: Standard cmux shortcut routing
    end
Loading

Reviews (2): Last reviewed commit: "Adds support for shortcut passthrough to..." | Re-trigger Greptile

Comment thread Sources/App/ShortcutRoutingSupport.swift Outdated
Comment thread Sources/AppDelegate.swift Outdated
@greptile-apps

greptile-apps Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a browser.shortcutPassthroughHosts config option that routes all Cmd-modifier keyboard events to the embedded browser's web content (bypassing cmux's own menus) when the focused page's host matches the allowlist. It also expands arrow-key routing in shouldDispatchBrowserArrowViaFirstResponderKeyDown to cover Shift+Arrow, Option+Arrow, Shift+Option+Arrow, and Cmd+Shift+Up/Down so text-selection and word-jump chords reach WebKit correctly.

  • Passthrough dispatch chain: handleCustomShortcut (local monitor) returns false early; NSWindow.cmux_performKeyEquivalent catches the event, calls CmuxWebView.performKeyEquivalent directly, and unconditionally returns true — intentionally preventing the main menu from seeing the event, but also silently swallowing Cmd+Q, Cmd+W, and Cmd+H when a passthrough host is focused.
  • Actor isolation gap: shouldPassthroughCommandEquivalentToWebContent reads WKWebView.url via MainActor.assumeIsolated but is not annotated @MainActor, leaving the isolation requirement unenforced at compile time.
  • Test coverage is solid: BrowserShortcutPassthroughTests covers the allowlist matching helpers, and BrowserArrowKeyForwardingTests is extended with all new routing cases and deliberate scope-exclusion guards.

Confidence Score: 3/5

The core passthrough logic correctly delivers events to WebKit for the web-IDE use case, but two issues on the changed path should be addressed before merge.

The NSWindow passthrough block silently drops Cmd+Q, Cmd+W, and Cmd+H when any passthrough host is focused, and the missing @MainActor annotation on the new helper leaves an isolation invariant unenforced at compile time — a future off-main caller will crash rather than fail to build.

Sources/AppDelegate.swift (unconditional return true in the passthrough block) and Sources/App/ShortcutRoutingSupport.swift (missing @MainActor on the new helper).

Important Files Changed

Filename Overview
Sources/App/ShortcutRoutingSupport.swift Adds shouldPassthroughCommandEquivalentToWebContent helper and expands arrow-key routing. The new helper uses MainActor.assumeIsolated without an @MainActor annotation — a runtime-only enforcement that should be a compile-time constraint.
Sources/AppDelegate.swift Adds two passthrough intercept points. The NSWindow path unconditionally swallows all Cmd-modifier events — including Cmd+Q and Cmd+W — when a passthrough host is focused.
Sources/Panels/BrowserPanel.swift Adds passthrough host matching helpers reusing existing normalizeWhitelistPattern / hostMatchesPattern logic. No new issues.
Sources/Panels/CmuxWebView.swift Adds passthrough block correctly placed after the Return/Enter special-case; same check is evaluated a second time when reached via the NSWindow path.
web/data/cmux.schema.json Adds shortcutPassthroughHosts to the browser schema; description omits that system shortcuts (Cmd+Q, Cmd+W, Cmd+H) are also bypassed.
cmuxTests/BrowserShortcutPassthroughTests.swift New test file with solid coverage of allowlist matching helpers across exact match, wildcard, URL extraction, nil URL, and whitespace normalization cases.
cmuxTests/BrowserArrowKeyForwardingTests.swift Extended with all new routing cases and deliberate scope-exclusion guards with clear rationale in comments.

Sequence Diagram

sequenceDiagram
    participant User as User (Cmd+key)
    participant LEM as LocalEventMonitor<br/>(handleCustomShortcut)
    participant WIN as NSWindow<br/>(cmux_performKeyEquivalent)
    participant WV as CmuxWebView<br/>(performKeyEquivalent)
    participant WK as WKWebView<br/>(super)
    participant MENU as NSApp.mainMenu

    User->>LEM: keyDown event
    LEM->>LEM: shouldPassthroughCommandEquivalentToWebContent?
    alt Host matches allowlist
        LEM-->>WIN: return false (event continues)
        WIN->>WIN: shouldPassthroughCommandEquivalentToWebContent?
        WIN->>WV: performKeyEquivalent(event)
        WV->>WV: shouldPassthroughCommandEquivalentToWebContent? (2nd eval)
        WV->>WK: super.performKeyEquivalent(event)
        WK-->>WV: handled (true/false)
        WV-->>WIN: finish(result)
        WIN-->>User: return true (always — swallows Cmd+Q etc.)
    else Host not in allowlist
        LEM->>LEM: process configured shortcuts
        LEM-->>WIN: return true/false
        WIN->>WIN: normal cmux shortcut chain
        WIN->>MENU: unhandled → main menu
        MENU-->>User: menu action fires
    end
Loading

Reviews (3): Last reviewed commit: "Adds support for shortcut passthrough to..." | Re-trigger Greptile

Comment thread Sources/App/ShortcutRoutingSupport.swift Outdated
Comment thread Sources/AppDelegate.swift Outdated
Comment thread web/data/cmux.schema.json Outdated
Comment thread Sources/App/ShortcutRoutingSupport.swift Outdated

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/data/cmux.schema.json`:
- Around line 875-882: Update the description for the shortcutPassthroughHosts
schema entry to state that host matching strips port numbers before comparison;
e.g., add a sentence such as "Port numbers are ignored during matching — hosts
are matched after stripping any :port suffix, so 'localhost' will match
'localhost:3000'." Keep the existing notes about exact and wildcard prefix
matching and ensure the wording clarifies that wildcards and exact names apply
to the host portion only (ports are not considered).
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 836b16a5-323c-460c-8b7a-a6ed7fb1c19c

📥 Commits

Reviewing files that changed from the base of the PR and between 28b0a78 and 2b48d1f.

📒 Files selected for processing (11)
  • Sources/App/ShortcutRoutingSupport.swift
  • Sources/AppDelegate.swift
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/Panels/BrowserPanel.swift
  • Sources/Panels/CmuxWebView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/BrowserArrowKeyForwardingTests.swift
  • cmuxTests/BrowserShortcutPassthroughTests.swift
  • web/app/[locale]/docs/configuration/page.tsx
  • web/data/cmux.schema.json

Comment thread web/data/cmux.schema.json

@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: 22

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/BrowserConfigTests.swift`:
- Around line 1486-1502: The helper withPassthroughHost mutates
UserDefaults.standard which can leak between concurrent tests; replace its usage
by creating an isolated UserDefaults suite (implement makeIsolatedDefaults as
shown in the comment) and update tests that call
shouldPassthroughCommandEquivalentToWebContent to accept or be provided with
that isolated defaults instance so the policy reads from the suite instead of
UserDefaults.standard; specifically, add makeIsolatedDefaults, ensure defaults
are cleared/teardowned, and modify the call sites or the
shouldPassthroughCommandEquivalentToWebContent helper so it uses the injected
UserDefaults rather than relying on global state (reference symbols:
withPassthroughHost, makeIsolatedDefaults,
shouldPassthroughCommandEquivalentToWebContent,
BrowserDevToolsButtonDebugSettingsTests, BrowserShortcutPassthroughTests).

In `@web/data/cmux.schema.json`:
- Line 882: Update the description string for the "Hosts whose pages receive
Cmd-modifier shortcuts directly." property to explicitly document apex behavior
for wildcards: state whether patterns like "*.example.com" match the apex
"example.com" (e.g., clarify that "*.example.com" does NOT match "example.com"
and that exact host matches are required), and mention that port numbers are
ignored and empty list keeps existing behavior; ensure the new text replaces the
current description so runtime behavior is unambiguous.

In `@web/messages/ar.json`:
- Line 504: Update the Arabic locale string for
schemaDescriptions.browser.shortcutPassthroughHosts to explicitly state that
wildcard patterns like *.subdomain do not match the apex domain (example.com)
while patterns without a wildcard match the apex, and mention that exact host
and port rules still apply (ports ignored); locate the key
"shortcutPassthroughHosts" in web/messages/ar.json and edit its value to mirror
the schema/wildcard semantics (apex vs wildcard matching) using concise Arabic
phrasing consistent with other locale entries.

In `@web/messages/bs.json`:
- Line 504: The current Bosnian translation for
schemaDescriptions.browser.shortcutPassthroughHosts is ambiguous about whether a
wildcard like "*.example.com" matches the apex domain; update that string to
explicitly state the implementation semantics (e.g., "*.example.com" matches
subdomains only and does NOT match "example.com"), and add a short note
explaining to include the apex domain explicitly (e.g., add "example.com") if
you want it matched; modify the message text for shortcutPassthroughHosts to
include this clarification while keeping the existing explanation about ports,
exact matches, and empty-list behavior.

In `@web/messages/da.json`:
- Line 504: The Danish translation for
schemaDescriptions.browser.shortcutPassthroughHosts is ambiguous about whether
the wildcard form (*.example.com) includes the apex domain; update the string in
web/messages/da.json (schemaDescriptions.browser.shortcutPassthroughHosts) to
explicitly state the schema's wildcard semantics—i.e., clarify whether
"*.example.com" matches subdomains only or also the apex "example.com"—so it
matches the original schema wording and remains consistent with other locales;
keep the rest of the description unchanged.

In `@web/messages/de.json`:
- Around line 503-505: Update the "browser.shortcutPassthroughHosts" translation
string to explicitly state wildcard apex behavior: clarify that patterns like
"*.example.com" also match the apex host "example.com" (i.e., the root/apex is
included), so users know "*.subdomain" and "*.example.com" both match the base
domain as well as subdomains; keep the rest of the sentence about exact host
matching, port numbers being ignored, and empty list behavior unchanged.

In `@web/messages/en.json`:
- Around line 604-606: Update the "browser"."shortcutPassthroughHosts"
description to explicitly state the wildcard-apex behavior: clarify that
patterns like "*.example.com" also match the apex host "example.com" (i.e.,
wildcard covers the base/apex), and keep the rest of the existing details about
subdomain wildcards, exact matches, and port-number/empty-list behavior intact;
modify the string for the "shortcutPassthroughHosts" key accordingly.

In `@web/messages/es.json`:
- Around line 503-505: Update the "browser.shortcutPassthroughHosts" Spanish
message to explicitly state that wildcard patterns like "*.example.com" also
match the apex domain "example.com"; modify the text for the key
shortcutPassthroughHosts so it clarifies that wildcards include the apex host
(not only subdomains), mention ports are ignored and an empty list keeps
existing behavior, and keep the rest of the explanatory examples (e.g., VS Code
via code-server) intact.

In `@web/messages/fr.json`:
- Line 504: Update the browser.shortcutPassthroughHosts description to
explicitly state wildcard apex matching: clarify that patterns like
"*.example.com" also match the apex "example.com" (i.e., the bare domain), along
with existing notes about exact host matches, ignored port numbers, and empty
list behavior; update the value for the key "shortcutPassthroughHosts" in
fr.json to add a short sentence stating this apex-domain matching behavior.

In `@web/messages/it.json`:
- Line 504: Update the Italian translation for the "shortcutPassthroughHosts"
message to explicitly state the wildcard semantics used by
browser.shortcutPassthroughHosts: clarify that patterns like "*.example.com"
match both subdomains and the apex host "example.com" (ports ignored), and keep
the rest of the explanation about exact/wildcard matching, passthrough behavior,
and empty-list default intact.

In `@web/messages/ja.json`:
- Line 564: Update the description for browser.shortcutPassthroughHosts to
explicitly state that wildcard entries like *.example.com also match the apex
domain (example.com) when supported, so readers understand that *.サブドメイン は apex
ドメイン(例: example.com)にも一致すること、ポートは無視されること、完全一致とワイルドカードの両方がサポートされることを明記してください;
edit the text around the existing "*.サブドメイン ワイルドカードをサポートします" phrase to add a
short clause clarifying apex-domain matching and an example (e.g.,
「*.example.com は example.com にも一致します」).

In `@web/messages/km.json`:
- Around line 503-505: Update the browser.shortcutPassthroughHosts message to
explicitly state the wildcard matching semantics: clarify that patterns like
*.example.com will also match the apex domain example.com (i.e., the wildcard
covers the root/apex), in addition to subdomains, so readers understand that
*.subdomain patterns include the bare host; keep the rest of the existing
description intact and preserve Khmer localization style.

In `@web/messages/ko.json`:
- Around line 503-505: Update the "browser.shortcutPassthroughHosts" value in
web/messages/ko.json to explicitly state the wildcard semantics for apex
domains: add a brief sentence clarifying whether patterns like "*.example.com"
do or do not match the apex host "example.com" (and keep notes that ports are
ignored and empty list preserves default behavior) so readers know the exact
behavior; ensure the change is applied to the string for the
"browser.shortcutPassthroughHosts" key.

In `@web/messages/no.json`:
- Around line 503-505: Update the "browser.shortcutPassthroughHosts" message to
explicitly state whether wildcard entries include the apex host (e.g., clarify
if "*.example.com" also matches "example.com" or not); edit the Norwegian
description to add a single clear sentence about the wildcard semantics (apex
match or no apex match), keep the existing notes about exact host match,
subdomain wildcards, and port numbers being ignored, and include a brief example
to illustrate the behavior so readers know how "*.underdomene" relates to
"underdomene".

In `@web/messages/pl.json`:
- Around line 503-504: Update the "browser.shortcutPassthroughHosts" Polish
message to explicitly state wildcard matching includes the apex host (e.g.,
clarify that patterns like "*.example.com" also match "example.com"); edit the
string in web/messages/pl.json under the "browser" -> "shortcutPassthroughHosts"
key to append a short sentence stating that "*.subdomena" (e.g.,
"*.example.com") will match the apex host "example.com".

In `@web/messages/pt-BR.json`:
- Around line 503-504: Update the "browser.shortcutPassthroughHosts" schema
description to explicitly state wildcard behavior in Portuguese: add a sentence
clarifying that patterns like "*.example.com" also match the apex domain
"example.com" (i.e., the wildcard includes the bare/apex host), and ensure this
note is written in pt-BR alongside the existing explanation about subdomains,
ports being ignored, and empty list behavior so readers clearly understand that
*.subdomínio covers both subdomínio.example.com and example.com.

In `@web/messages/ru.json`:
- Around line 503-504: Update the "browser.shortcutPassthroughHosts" Russian
description to explicitly state wildcard apex-domain behavior: clarify that a
pattern like "*.example.com" also matches the apex host "example.com" (not only
subdomains). Mention that port numbers are ignored and that exact host or
wildcard forms may be used, keeping the rest of the existing guidance about Cmd
passthrough and empty-list behavior intact; edit the string under the
browser.shortcutPassthroughHosts key accordingly.

In `@web/messages/th.json`:
- Line 504: Update the translation for the key "shortcutPassthroughHosts" to
explicitly document wildcard apex matching: state that patterns like
"*.example.com" also match the apex host "example.com" (i.e., wildcard subdomain
patterns include the base domain), while keeping the existing notes that ports
are ignored, both exact and wildcard matches are supported, and empty lists
preserve default cmux behavior; modify the string value for
"shortcutPassthroughHosts" accordingly so the Thai locale clearly communicates
the apex-domain matching semantics.

In `@web/messages/tr.json`:
- Line 504: Update the translation for the "shortcutPassthroughHosts"
description to explicitly state that wildcard patterns like "*.altetkialan" also
match the apex domain (e.g., "altetkialan" or "example.com") in addition to
subdomains; keep the existing notes that port numbers are ignored and an empty
list preserves current cmux behavior. Edit the string value for the
shortcutPassthroughHosts key so it clearly mentions "joker desenler apex (ana)
alanı da eşler — örn. *.example.com hem example.com hem alt.example.com ile
eşleşir" while retaining the rest of the original explanation about passthrough
ordering and empty-list behavior.

In `@web/messages/uk.json`:
- Line 504: Update the "shortcutPassthroughHosts" translation string so it
explicitly states the wildcard does not match the apex domain — e.g., clarify
that "*.example.com" applies to subdomains like "foo.example.com" but does not
match "example.com"; keep the existing sentence about ports being ignored and
preserve style/terminology for browser.shortcutPassthroughHosts across locales.

In `@web/messages/zh-CN.json`:
- Line 504: Update the "shortcutPassthroughHosts" description to explicitly
state the wildcard apex-matching behavior for patterns like "*.example.com":
indicate whether such a pattern will match both the apex domain (example.com)
and its subdomains (e.g., sub.example.com) or only subdomains; keep the existing
notes that ports are ignored and empty lists preserve cmux behavior. Reference
the "shortcutPassthroughHosts" key and use clear example wording (e.g., “例如
*.example.com 将匹配 example.com 与 sub.example.com” or “例如 *.example.com 只匹配子域,不匹配
example.com”) to remove ambiguity.

In `@web/messages/zh-TW.json`:
- Line 504: Update the "shortcutPassthroughHosts" description to explicitly
state the wildcard matching behavior for patterns like "*.example.com": indicate
whether such a pattern matches only subdomains (e.g., "sub.example.com") or also
the apex domain ("example.com"), and give a short example of each case so users
know how to craft entries; keep mention of port being ignored and empty list
behavior as-is.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 200fe3da-59a4-47b4-8df1-de11b6d55c8d

📥 Commits

Reviewing files that changed from the base of the PR and between 2b48d1f and b3b161d.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (27)
  • Sources/App/BrowserShortcutPassthroughPolicy.swift
  • Sources/App/ShortcutRoutingSupport.swift
  • Sources/AppDelegate.swift
  • Sources/Panels/CmuxWebView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/BrowserConfigTests.swift
  • web/data/cmux.schema.json
  • web/messages/ar.json
  • web/messages/bs.json
  • web/messages/da.json
  • web/messages/de.json
  • web/messages/en.json
  • web/messages/es.json
  • web/messages/fr.json
  • web/messages/it.json
  • web/messages/ja.json
  • web/messages/km.json
  • web/messages/ko.json
  • web/messages/no.json
  • web/messages/pl.json
  • web/messages/pt-BR.json
  • web/messages/ru.json
  • web/messages/th.json
  • web/messages/tr.json
  • web/messages/uk.json
  • web/messages/zh-CN.json
  • web/messages/zh-TW.json
💤 Files with no reviewable changes (1)
  • Sources/App/ShortcutRoutingSupport.swift

Comment thread cmuxTests/BrowserConfigTests.swift
Comment thread web/data/cmux.schema.json Outdated
Comment thread web/messages/ar.json Outdated
Comment thread web/messages/bs.json Outdated
Comment thread web/messages/da.json Outdated
Comment thread web/messages/th.json Outdated
Comment thread web/messages/tr.json Outdated
Comment thread web/messages/uk.json Outdated
Comment thread web/messages/zh-CN.json Outdated
Comment thread web/messages/zh-TW.json Outdated
@jcrsilva
jcrsilva force-pushed the feature/keyboard_passthrough branch from 62fafa6 to 04c7505 Compare May 27, 2026 17:26
@jcrsilva

Copy link
Copy Markdown
Author

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

@jcrsilva: Sure, I'll re-review the latest changes on this PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cubic-dev-ai

cubic-dev-ai Bot commented May 27, 2026

Copy link
Copy Markdown

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@jcrsilva I have started the AI code review. It will take a few minutes to complete.

@jcrsilva

Copy link
Copy Markdown
Author

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

@jcrsilva Sure, I'll kick off a review of the latest changes on this PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cubic-dev-ai

cubic-dev-ai Bot commented May 27, 2026

Copy link
Copy Markdown

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@jcrsilva I have started the AI code review. It will take a few minutes to complete.

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/AppDelegate.swift`:
- Around line 11844-11852: Remove the suggested `@MainActor` change and instead
cache the parsed allowlist used during passthrough checks: modify the chain
starting at shouldPassthroughCommandEquivalentToWebContent →
BrowserLinkOpenSettings.urlMatchesShortcutPassthrough →
hostMatchesShortcutPassthrough so that shortcutPassthroughHosts does not reparse
UserDefaults on every call; implement a cached parsedPatterns property (or
similar) that is refreshed when UserDefaults.didChangeNotification fires (or
when the relevant key changes), and have hostMatchesShortcutPassthrough consult
the cached parsedPatterns for matching to avoid per-event parsing overhead.

In `@Sources/Panels/BrowserPanel.swift`:
- Around line 894-900: shortcutPassthroughHosts currently reparses the
newline-delimited string on every call (hot path during per-keystroke
command-key routing); add a static cached parsed array (e.g., a private static
var cachedShortcutPassthroughHosts: [String]?) and change
shortcutPassthroughHosts(defaults:) to return the cached value if present,
otherwise parse once, store in the cache, and return it; invalidate or refresh
this cache on settings changes by observing UserDefaults.didChangeNotification
(or call the same invalidation from any explicit setter path) and consider
synchronizing access with a serial DispatchQueue or lock to be thread-safe;
update the host-match call sites that currently call shortcutPassthroughHosts
repeatedly to rely on the cached result.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7d51f0fe-9d21-4e65-8c93-f13fe42ff482

📥 Commits

Reviewing files that changed from the base of the PR and between 62fafa6 and 04c7505.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (33)
  • Sources/App/BrowserShortcutPassthroughPolicy.swift
  • Sources/App/ShortcutRoutingSupport.swift
  • Sources/AppDelegate.swift
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/Panels/BrowserPanel.swift
  • Sources/Panels/CmuxWebView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/BrowserArrowKeyForwardingTests.swift
  • cmuxTests/BrowserConfigTests.swift
  • cmuxTests/BrowserShortcutPassthroughTests.swift
  • web/app/[locale]/docs/configuration/page.tsx
  • web/data/cmux.schema.json
  • web/messages/ar.json
  • web/messages/bs.json
  • web/messages/da.json
  • web/messages/de.json
  • web/messages/en.json
  • web/messages/es.json
  • web/messages/fr.json
  • web/messages/it.json
  • web/messages/ja.json
  • web/messages/km.json
  • web/messages/ko.json
  • web/messages/no.json
  • web/messages/pl.json
  • web/messages/pt-BR.json
  • web/messages/ru.json
  • web/messages/th.json
  • web/messages/tr.json
  • web/messages/uk.json
  • web/messages/zh-CN.json
  • web/messages/zh-TW.json
💤 Files with no reviewable changes (26)
  • web/app/[locale]/docs/configuration/page.tsx
  • web/messages/pt-BR.json
  • web/messages/pl.json
  • web/data/cmux.schema.json
  • web/messages/fr.json
  • web/messages/zh-TW.json
  • web/messages/zh-CN.json
  • web/messages/es.json
  • web/messages/ru.json
  • web/messages/th.json
  • web/messages/de.json
  • web/messages/ja.json
  • web/messages/uk.json
  • web/messages/ar.json
  • web/messages/da.json
  • web/messages/it.json
  • web/messages/km.json
  • web/messages/no.json
  • web/messages/en.json
  • cmuxTests/BrowserArrowKeyForwardingTests.swift
  • web/messages/ko.json
  • web/messages/tr.json
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/BrowserShortcutPassthroughTests.swift
  • web/messages/bs.json
  • cmuxTests/BrowserConfigTests.swift

Comment thread Sources/AppDelegate.swift
Comment thread Sources/Panels/BrowserPanel.swift
@jcrsilva

Copy link
Copy Markdown
Author

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented May 28, 2026

Copy link
Copy Markdown

@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@jcrsilva I have started the AI code review. It will take a few minutes to complete.

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

@jcrsilva Sure, I'll kick off a review of the latest changes on this PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@greptile-apps

greptile-apps Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

New config option added under "browser" allowing for certain keyboard shortcuts
which right now are intercepted by tmux to passthough to the embedded browser when
in configured hosts.

This has potentially other applications but the intent is to tackle
[this class](manaflow-ai#2342) of issue, to more
easily allow people to run web-based IDEs such as code-server in the integrated
cmux browser.
@jcrsilva
jcrsilva force-pushed the feature/keyboard_passthrough branch from 1d05e84 to feb67a9 Compare May 28, 2026 12:35
@teamleaderleo

Copy link
Copy Markdown
Collaborator

This remains a live browser shortcut passthrough proposal; leaving the configuration and routing choice to the team.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: browser The embedded browser, web surfaces, inline VS Code S3: minor Wrong behavior with a workaround

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants