Skip to content

Fix arrow keys not working in browser surfaces and IME candidate selection - #1423

Closed
jtdoth wants to merge 1 commit into
manaflow-ai:mainfrom
jtdoth:fix-1146-browser-arrow-keys
Closed

jtdoth wants to merge 1 commit into
manaflow-ai:mainfrom
jtdoth:fix-1146-browser-arrow-keys

Conversation

@jtdoth

@jtdoth jtdoth commented Mar 14, 2026 •

Copy link
Copy Markdown

Summary

  • Fix arrow keys (and Cmd+arrow) not working in browser surface textareas
  • Fix IME candidate selection (up/down) not working in terminal
  • Root cause: SwiftUI's internal focus system enters a broken state after a
    WKWebView has been in the responder chain — its hosting view intercepts
    key events via performKeyEquivalent, returns true, but never fires the action

Testing

  • Opened browser panel, navigated to a page with <textarea>
  • Verified up/down arrow keys move cursor inside textarea
  • Verified Cmd+Up/Down jumps to beginning/end of text
  • Verified Cmd+Left/Right jumps to beginning/end of line
  • Verified Cmd+T, Cmd+W, Cmd+N still work as app shortcuts
  • Verified Chinese IME candidate selection with up/down keys in terminal
  • Ran xcodebuild -scheme cmux-unit test — no new failures
  • Existing BrowserOmnibarCommandNavigationTests and
    CJKIMEPerformKeyEquivalentTests pass

No new unit tests added — the bug depends on SwiftUI's hosting view
entering a broken focus state after a WKWebView has been in the responder
chain, which cannot be reproduced in a unit test environment. The fix is
verified through manual testing and covered indirectly by existing tests
for the pure routing logic.

Demo Video

CleanShot.2026-03-14.at.14.26.05-trimmed-converted.3.mp4

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

Fixes #1146


Summary by cubic

Fixes arrow keys (including Cmd+arrow) in browser textareas and restores IME candidate selection in the terminal by bypassing SwiftUI’s broken focus path after a WKWebView is focused. App shortcuts still work as expected. Fixes #1146.

  • Bug Fixes
    • Route non-Command keys directly to the terminal view; handles normal typing and IME composition.
    • After app-level shortcuts, route remaining keys directly to the WKWebView to keep arrows/Cmd+arrows working in textareas.
    • Clear stale address bar focus when the first responder is a WKWebView (not just a terminal), preventing swallowed keys.

Written for commit f4c2e20. Summary will update on new commits.

Summary by CodeRabbit

Bug Fixes

  • Improved keyboard routing and focus detection when interacting with embedded web content, ensuring correct key dispatch regardless of focus context.
  • Enhanced focus handling between web views and terminal input to reduce conflicts and provide more reliable keyboard interaction when switching between components.

…ction

SwiftUI's internal focus system enters a broken state after a browser
panel (WKWebView) has been in the responder chain, where its hosting
view intercepts key events via performKeyEquivalent, returns true, but
never fires the action — silently swallowing arrow keys.

- Route non-Command keys directly to CmuxWebView.performKeyEquivalent
  after app-level shortcuts have been checked, bypassing the broken
  SwiftUI content view hierarchy walk.
- Clear stale browserAddressBarFocusedPanelId when the first responder
  is inside a WKWebView, not only when it is a terminal surface.
- Remove the separate hasMarkedText() branch in the terminal path;
  GhosttyNSView.performKeyEquivalent already returns false during IME
  composition, so the unified direct-routing path handles both normal
  typing and IME candidate navigation correctly.

Fixes manaflow-ai#1146
@vercel

vercel Bot commented Mar 14, 2026

Copy link
Copy Markdown

@jt-hsiao 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 14, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Modified AppDelegate.swift to improve key-event routing and focus detection for web views. Added a helper function to detect when the first responder is inside a WKWebView, and updated key-handling logic to route non-Command keys directly to the appropriate component (terminal or web view) based on responder location.

Changes

Cohort / File(s) Summary
First-responder and key-routing improvements
Sources/AppDelegate.swift
Introduced cmuxResponderIsInsideWebView() helper to traverse responder hierarchy and detect web view focus. Updated multiple code paths to use this helper for distinguishing terminal vs. web view focus contexts. Enhanced key handling in cmux_performKeyEquivalent to route non-Command keys directly to terminal or web view based on current responder, and expanded logging with descriptive reason strings (terminal_first_responder, webview_first_responder, etc.).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • Up/down arrow keys not working in browser surface #1146 — Up/down arrow keys not working in browser surface; this PR directly addresses the issue by implementing proper first-responder detection and routing non-Command keys to the appropriate target (terminal or web view) rather than letting them be consumed by SwiftUI's focus hierarchy.

Possibly related PRs

  • Fix side-docked dev tools resize #712 — Modifies AppDelegate's event/hit-testing and WebView ownership routing logic (cmuxOwningWebView), sharing overlapping code paths for focus/responder management.
  • tmux stuff #717 — Modifies cmux_performKeyEquivalent in AppDelegate to selectively passthrough events to the Ghostty terminal; this PR extends similar routing logic with webview-aware responder handling.
  • Fix cmd+` window cycling bouncing back #1243 — Changes key-event routing around terminals and web views to decide when to route Command-key events to the app menu vs. terminal/webview, intersecting with the routing decisions made here.

Poem

🐰 Hop along, keys find their way,
Web views and terminals at play,
No more focus fray,
Responders lead the sway,
Arrow keys dance through the day! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: fixing arrow keys and IME candidate selection in browser surfaces, which aligns with the primary objective in the changeset.
Linked Issues check ✅ Passed The PR addresses issue #1146 by fixing up/down arrow keys in browser surfaces through direct routing logic and WKWebView responder handling, meeting the stated objective.
Out of Scope Changes check ✅ Passed All code changes focus on fixing arrow key routing in browser surfaces and IME handling, staying within the scope of issue #1146 and the stated objectives.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering all required template sections including Summary, Testing, Demo Video, and a completed Checklist.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can customize the tone of the review comments and chat replies.

Configure the tone_instructions setting to customize the tone of the review comments and chat replies. For example, you can set the tone to Act like a strict teacher, Act like a pirate and more.

@jtdoth
jtdoth marked this pull request as ready for review March 14, 2026 06:42

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@jtdoth

jtdoth commented Mar 14, 2026

Copy link
Copy Markdown
Author

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

@cubic-dev-ai

cubic-dev-ai Bot commented Mar 14, 2026

Copy link
Copy Markdown

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

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

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

@jt-hsiao Sure, I'll review the changes in this PR!


🧠 Learnings used
Learnt from: SuperManfred
Repo: manaflow-ai/cmux PR: 1150
File: Sources/AppDelegate.swift:7394-7401
Timestamp: 2026-03-10T10:24:14.017Z
Learning: Repo: manaflow-ai/cmux — For Cmd+W behavior with browser popups: BrowserPopupPanel.performKeyEquivalent is the primary handler to close popups. AppDelegate.handleCustomShortcut(_:), in its Cmd+W fallback, must check both NSApp.keyWindow and event.window for identifier "cmux.browser-popup" and close it if found, before routing to workspace/settings close logic.

Learnt from: homanp
Repo: manaflow-ai/cmux PR: 883
File: CLI/cmux.swift:1569-1586
Timestamp: 2026-03-04T22:05:07.913Z
Learning: In manaflow-ai/cmux CLI (CLI/cmux.swift), for parity with existing browser commands, markdown.open intentionally normalizes --surface before resolving --workspace/--window, relying on server-side resolution to disambiguate final routing. Avoid one-off reordering in markdown; consider any change only as a coordinated, cross-command refactor.

Learnt from: moyashin63
Repo: manaflow-ai/cmux PR: 1074
File: Sources/AppDelegate.swift:7523-7545
Timestamp: 2026-03-09T01:38:35.335Z
Learning: In manaflow-ai/cmux (Sources/AppDelegate.swift), shouldConsumeShortcutWhileCommandPaletteVisible(...) intentionally consumes most Command shortcuts while the command palette is visible to protect its text input. As a result, UI zoom shortcuts (Cmd+Shift+= / Cmd+Shift+− / Cmd+Shift+0) must not fire while the palette is open. Do not reorder handlers (e.g., uiZoomShortcutAction(...)) to bypass this guard; users close the palette before zooming.
✅ 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.

@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 11220-11226: firstResponderWebView's handling should only
short-circuit when it actually handled the key event; change the logic around
firstResponderWebView and webView.performKeyEquivalent(with:) so you only return
the result when it's true, otherwise allow the method to fall through and let
NSWindow.performKeyEquivalent (and BrowserPopupPanel.performKeyEquivalent) run;
locate the block referencing firstResponderWebView and
WKWebView.performKeyEquivalent(with:) and adjust the conditional to return only
on true so menu/window handlers still get a chance on false.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e668b397-a9f3-4edd-8a5f-378aa7b65b80

📥 Commits

Reviewing files that changed from the base of the PR and between 6c644d9 and f4c2e20.

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

Comment thread Sources/AppDelegate.swift
Comment on lines +11220 to +11226
if let webView = firstResponderWebView {
let result = webView.performKeyEquivalent(with: event)
#if DEBUG
dlog(" → webview direct: \(result)")
#endif
return result
}

@coderabbitai coderabbitai Bot Mar 14, 2026 •

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

Fall through when WebKit declines a Command equivalent.

Line 11225 returns result unconditionally. If WKWebView.performKeyEquivalent(with:) returns false for a Cmd shortcut it does not own, the original NSWindow.performKeyEquivalent(with:) never runs, so window/menu handlers lose their chance. That can bypass repo-specific handlers like browser-popup Cmd+W, and native fallbacks such as window cycling.

💡 Suggested fix
         if let webView = firstResponderWebView {
             let result = webView.performKeyEquivalent(with: event)
 `#if` DEBUG
             dlog("  → webview direct: \(result)")
 `#endif`
-            return result
+            if result || !event.modifierFlags
+                .intersection(.deviceIndependentFlagsMask)
+                .contains(.command) {
+                return result
+            }
         }

Based on learnings: BrowserPopupPanel.performKeyEquivalent is the primary handler to close popups.

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

In `@Sources/AppDelegate.swift` around lines 11220 - 11226,
firstResponderWebView's handling should only short-circuit when it actually
handled the key event; change the logic around firstResponderWebView and
webView.performKeyEquivalent(with:) so you only return the result when it's
true, otherwise allow the method to fall through and let
NSWindow.performKeyEquivalent (and BrowserPopupPanel.performKeyEquivalent) run;
locate the block referencing firstResponderWebView and
WKWebView.performKeyEquivalent(with:) and adjust the conditional to return only
on true so menu/window handlers still get a chance on false.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is a false positive — CmuxWebView.performKeyEquivalent already handles Command key routing internally:

  1. shouldRouteCommandEquivalentDirectlyToMainMenu → tries NSApp.mainMenu.performKeyEquivalent (line 155)
  2. Falls back to handleBrowserSurfaceKeyEquivalent (line 164)
  3. Falls through to super.performKeyEquivalent (WKWebView, line 171)

All menu items and app shortcuts are resolved inside the CmuxWebView override before it returns. If it still returns false, it means no handler claimed the event — the same outcome the original NSWindow.performKeyEquivalent walk would produce, except the original walk also risks hitting the broken SwiftUI hosting view path (which is exactly the bug this PR fixes).

The only Command key where shouldRouteCommandEquivalentDirectlyToMainMenu returns false is Cmd+` (keyCode 50), which is intentionally excluded (confirmed by existing test testCmdBacktickDoesNotRouteDirectlyToMainMenuWhenWebViewIsFirstResponder). In that case, super.performKeyEquivalent returns false, and our code correctly propagates that — same as the old path.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

@coderabbit-user Thanks for the added context. I’ll verify your claim against the repo and get back with a short confirmation or tweak if anything looks off.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find CmuxWebView and performKeyEquivalent overrides =="
rg -nP --no-ignore-vcs -C3 '(class|extension)\s+CmuxWebView\b' --glob '**/*.swift' || true
rg -n --no-ignore-vcs -C5 'performKeyEquivalent\s*\(\s*with:' --glob '**/*.swift' || true

echo
echo "== Search for handleBrowserSurfaceKeyEquivalent =="
rg -n --no-ignore-vcs -C3 '\bhandleBrowserSurfaceKeyEquivalent\b' --glob '**/*.swift' || true

echo
echo "== Search BrowserPopupPanel and its performKeyEquivalent =="
rg -nP --no-ignore-vcs -C4 '(class|extension)\s+BrowserPopupPanel\b' --glob '**/*.swift' || true
rg -n --no-ignore-vcs -C5 'BrowserPopupPanel.*performKeyEquivalent|extension\s+BrowserPopupPanel|performKeyEquivalent\s*\(\s*with:' Sources/Panels/**/*.swift || true

echo
echo "== Find string identifier used for browser popups to cross-check learning =="
rg -n --no-ignore-vcs -C2 'cmux\.browser-popup' --glob '**/*.swift' || true

Length of output: 26926


@coderabbit-user Agreed — this was a false positive. I verified the routing:

  • In NSWindow.cmux_performKeyEquivalent, we first give the app-level handler a chance: handleBrowserSurfaceKeyEquivalent (Sources/AppDelegate.swift:11208–11213). Only then do we call firstResponderWebView.performKeyEquivalent and return its result (Lines 11220–11226).

  • CmuxWebView.performKeyEquivalent itself handles Command routing:

    • If shouldRouteCommandEquivalentDirectlyToMainMenu(event) is true, it tries NSApp.mainMenu.performKeyEquivalent first (Sources/Panels/CmuxWebView.swift:155–160).
    • Then falls back to AppDelegate.shared?.handleBrowserSurfaceKeyEquivalent (Lines 164–168).
    • Then to super.performKeyEquivalent (Lines 171–175).
    • For non-Command, it directly calls super (Lines 139–144).
  • Tests cover this: Cmd+N/W/R are consumed via the menu when WebView is first responder, while Return / Cmd+Return are not, and Cmd+` is explicitly excluded from direct-menu routing (cmuxTests/CmuxWebViewKeyEquivalentTests.swift:184–209, 220–246, 814–820).

Given this, allowing fall-through to the original NSWindow.performKeyEquivalent when the WebView returns false would just re-enter the SwiftUI hierarchy we’re intentionally bypassing for this bug, without adding any valid handler opportunity. Also, there’s no BrowserPopupPanel or “cmux.browser-popup” identifier in this repo, so that prior guideline doesn’t apply here.

I’m retracting the concern; no change needed.


✏️ Learnings added
Learnt from: jt-hsiao
Repo: manaflow-ai/cmux PR: 1423
File: Sources/AppDelegate.swift:11220-11226
Timestamp: 2026-03-14T07:05:52.379Z
Learning: Repo: manaflow-ai/cmux — In Sources/Panels/CmuxWebView.swift, performKeyEquivalent(with:) handles Command-key routing end-to-end: (1) if allowed, route to NSApp.mainMenu.performKeyEquivalent; (2) fall back to AppDelegate.shared?.handleBrowserSurfaceKeyEquivalent(event) for non–menu-backed app shortcuts; (3) fall back to super.performKeyEquivalent. For non-Command keys it calls super directly. Therefore, in NSWindow.cmux_performKeyEquivalent (Sources/AppDelegate.swift), it is correct to call firstResponderWebView.performKeyEquivalent and return its Bool unconditionally to avoid re-entering SwiftUI’s performKeyEquivalent path that can swallow keys after WKWebView focus.

Learnt from: jt-hsiao
Repo: manaflow-ai/cmux PR: 1423
File: Sources/AppDelegate.swift:11220-11226
Timestamp: 2026-03-14T07:05:52.379Z
Learning: Repo: manaflow-ai/cmux — Command-backtick (Cmd+`, 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+`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: SuperManfred
Repo: manaflow-ai/cmux PR: 1150
File: Sources/AppDelegate.swift:7394-7401
Timestamp: 2026-03-10T10:24:14.017Z
Learning: Repo: manaflow-ai/cmux — For Cmd+W behavior with browser popups: BrowserPopupPanel.performKeyEquivalent is the primary handler to close popups. AppDelegate.handleCustomShortcut(_:), in its Cmd+W fallback, must check both NSApp.keyWindow and event.window for identifier "cmux.browser-popup" and close it if found, before routing to workspace/settings close logic.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-12T21:54:38.291Z
Learning: Applies to Sources/**/*TerminalWindowPortal.swift : In `WindowTerminalHostView.hitTest()` in `TerminalWindowPortal.swift`: all divider/sidebar/drag routing must be gated to pointer events only. Do not add work outside the `isPointerEvent` guard to avoid typing latency.

Learnt from: SuperManfred
Repo: manaflow-ai/cmux PR: 803
File: Sources/Panels/BrowserPopupWindowController.swift:36-38
Timestamp: 2026-03-04T05:11:56.373Z
Learning: In Sources/Panels/BrowserPopupWindowController.swift and Sources/Panels/BrowserPanel.swift, `webView.isInspectable = true` (guarded by `#available(macOS 13.3, *)`) is intentionally enabled in all builds — not just DEBUG — because cmux is a developer tool and full Web Inspector access is desired in production builds as well. Do not flag this as a security concern.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-12T21:54:38.291Z
Learning: Applies to Sources/**/*.swift : `SurfaceSearchOverlay` must be mounted from `GhosttySurfaceScrollView` in `Sources/GhosttyTerminalView.swift` (AppKit portal layer), not from SwiftUI panel containers such as `Sources/Panels/TerminalPanelView.swift`. Portal-hosted terminal views can sit above SwiftUI during split/workspace churn.

Learnt from: moyashin63
Repo: manaflow-ai/cmux PR: 1074
File: Sources/AppDelegate.swift:7523-7545
Timestamp: 2026-03-09T01:38:24.337Z
Learning: When the command palette is visible (as in manaflow-ai/cmux Sources/AppDelegate.swift), ensure the shortcut handling consumes most Command shortcuts to protect the palette's text input. Specifically, do not allow UI zoom shortcuts (Cmd+Shift+= / Cmd+Shift+− / Cmd+Shift+0) to trigger while the palette is open. Do not reorder shortcut handlers (e.g., uiZoomShortcutAction(...)) to bypass this guard; users must close the palette before performing zoom actions. This guideline should apply to Swift source files handling global shortcuts within the app.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-05T03:20:48.079Z
Learning: Applies to **/*TerminalView.swift : Terminal find layering contract: SurfaceSearchOverlay must be mounted from GhosttySurfaceScrollView in Sources/GhosttyTerminalView.swift (AppKit portal layer), not from SwiftUI panel containers

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-05T03:20:48.079Z
Learning: Applies to **/*.swift : Socket/CLI commands must not steal macOS app focus; only explicit focus-intent commands may mutate in-app focus/selection

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 762
File: Sources/ContentView.swift:5784-5788
Timestamp: 2026-03-06T02:00:30.333Z
Learning: In manaflow-ai/cmux (Sources/ContentView.swift), ShortcutHintModifierPolicy.shouldShowHints is Command-only: it returns true only when modifierFlags normalized to [.command]. Control-hold must not show sidebar/titlebar shortcut hints, and close-button suppression in TabItemView must remain tied to showsModifierShortcutHints (Command hold) or the always-show debug flag.

Learnt from: homanp
Repo: manaflow-ai/cmux PR: 883
File: CLI/cmux.swift:1569-1586
Timestamp: 2026-03-04T22:05:07.913Z
Learning: In manaflow-ai/cmux CLI (CLI/cmux.swift), for parity with existing browser commands, markdown.open intentionally normalizes --surface before resolving --workspace/--window, relying on server-side resolution to disambiguate final routing. Avoid one-off reordering in markdown; consider any change only as a coordinated, cross-command refactor.

Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/ContentView.swift:3194-3196
Timestamp: 2026-03-04T14:05:48.668Z
Learning: In manaflow-ai/cmux (PR `#819`), Sources/ContentView.swift: The command palette’s external window labels intentionally use the global window index from the full orderedSummaries (index + 1), matching the Window menu in AppDelegate. Do not reindex after filtering out the current window to avoid mismatches (“Window 2” for an external window is expected).

Learnt from: debgotwired
Repo: manaflow-ai/cmux PR: 1149
File: Sources/ContentView.swift:3977-3978
Timestamp: 2026-03-10T09:33:37.952Z
Learning: In manaflow-ai/cmux (Sources/ContentView.swift), scheduleCommandPaletteResultsRefresh(forceSearchCorpusRefresh:) is shared command‑palette infrastructure across all submenus. Do not change its sync‑seeding behavior within feature‑scoped PRs; treat brief initial flashes as consistent with existing submenus. Any UX improvement (e.g., synchronous seeding on forced corpus refresh) should be implemented and tested globally in a dedicated follow‑up PR.

Learnt from: apollow
Repo: manaflow-ai/cmux PR: 1089
File: Sources/TerminalController.swift:3180-3193
Timestamp: 2026-03-09T02:08:14.574Z
Learning: Repo: manaflow-ai/cmux — In Sources/TerminalController.swift, v2WorkspaceClearTags(params:) must only clear all tags when the "source" key is absent. If "source" is present but blank or non-string (v2String(...) returns nil), the API should return invalid_params. Current implementation uses hasSourceKey = params.keys.contains("source") and guards with if hasSourceKey && source == nil { return .err(...)}.

Learnt from: 0xble
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-03-09T21:53:05.451Z
Learning: Repo: manaflow-ai/cmux — For browser portals, visibility resync is centralized in BrowserWindowPortalRegistry.updateEntryVisibleInUI(for: WKWebView, visibleInUI: Bool), which immediately synchronizes the WKWebView on visibility changes. Call sites (e.g., Workspace.reconcilePanelPortalVisibilityForCurrentLayout()) should use this helper instead of ad‑hoc resync logic.

Learnt from: mdsakalu
Repo: manaflow-ai/cmux PR: 510
File: Sources/GhosttyTerminalView.swift:2276-2336
Timestamp: 2026-03-11T04:48:32.420Z
Learning: In cmux Sources/GhosttyTerminalView.swift, when implementing initial-present recovery for Ghostty terminals, avoid ghostty_surface_draw loops. Re-read self.surface after view.forceRefreshSurface() (since the surface may be torn down/reparented), then use occlusion toggle (ghostty_surface_set_occlusion false/true) plus ghostty_surface_refresh to wake the renderer. Cancel retries once the layer has contents or the retry budget is exhausted.

Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/AppDelegate.swift:3491-3493
Timestamp: 2026-03-04T14:06:12.296Z
Learning: In PRs affecting this repository, limit the scope of localization (i18n) changes to Japanese translations for the file Sources/AppDelegate.swift. Do not include UX enhancements (e.g., preferring workspace.customTitle in workspaceDisplayName() or altering move-target labels) in this PR. Open a separate follow-up issue to address any UX-related changes to avoid scope creep and keep localization review focused.

Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/AppDelegate.swift:0-0
Timestamp: 2026-03-04T14:05:42.574Z
Learning: Guideline: In Swift files (cmux project), when handling pluralized strings, prefer using localization keys with the ICU-style plural forms .one and .other. For example, use keys like statusMenu.unreadCount.one for the singular case (1) and statusMenu.unreadCount.other for all other counts, and similarly for statusMenu.tooltip.unread.one/other. Rationale: ensures correct pluralization across locales and makes localization keys explicit. Review code to ensure any unread count strings and related tooltips follow this .one/.other key pattern and verify the correct value is chosen based on the count.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 954
File: Sources/TerminalController.swift:0-0
Timestamp: 2026-03-05T22:04:34.712Z
Learning: Adopt the convention: for health/telemetry tri-state values in Swift, prefer Optionals (Bool?) over sentinel booleans. In TerminalController.swift, socketConnectable is Bool? and only set when socketProbePerformed is true; downstream logic must treat nil as 'not probed'. Ensure downstream code checks for nil before using a value and uses explicit non-nil checks to determine state, improving clarity and avoiding misinterpretation of default false.

Learnt from: zlatkoc
Repo: manaflow-ai/cmux PR: 1368
File: Sources/Panels/BrowserPanel.swift:69-69
Timestamp: 2026-03-13T13:46:01.733Z
Learning: Do not wrap engine/brand name literals (e.g., displayName values such as Google, DuckDuckGo, Bing, Kagi, Startpage) in String(localized: ...). These are brand/product names that are not translatable UI text. Localization should apply to generic UI strings (labels, buttons, error messages, etc.). Apply this guideline across Swift source files under Sources/ (notably in BrowserPanel.swift and similar UI/engine-related strings) and flag only brand-name strings that are part of user-facing UI text appropriately for translation scope.

@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


Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@deftdawg

deftdawg commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

Does this fix #2653 ?

EDIT: is this fixed by #2780 (unreleased)?
I just tried Nightly and browser arrow behaviour seems to work better: https://github.com/manaflow-ai/cmux/releases/download/nightly/cmux-nightly-macos.dmg

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Thank you for this! Browser arrow and IME input handling are on main in 296537c :)

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.

Up/down arrow keys not working in browser surface

3 participants