Skip to content

feat: add quick Terminal panel, CLI/socket controls, and automation-safe focus behavior#1996

Open
jemutorres wants to merge 5 commits intomanaflow-ai:mainfrom
jemutorres:feat/quick-terminal-327
Open

feat: add quick Terminal panel, CLI/socket controls, and automation-safe focus behavior#1996
jemutorres wants to merge 5 commits intomanaflow-ai:mainfrom
jemutorres:feat/quick-terminal-327

Conversation

@jemutorres
Copy link
Copy Markdown

@jemutorres jemutorres commented Mar 23, 2026

Implements Quick Terminal across app shortcut/menu/settings, command palette, socket v2, and CLI (cmux quick-terminal).

Also ensures socket/CLI quick terminal commands do not steal macOS focus and wraps animation completion state updates on MainActor.

Adds README and CHANGELOG notes.

Closes #327

Summary

  • Added Quick Terminal end-to-end integration:
    • Keyboard shortcut (default: Option+Command+`)
    • View menu action
    • Command Palette action
    • Settings controls (position, primary/secondary size, auto-hide)
    • Socket v2 methods:
      • quick_terminal.toggle
      • quick_terminal.show
      • quick_terminal.hide
      • quick_terminal.status
    • CLI commands:
      • cmux quick-terminal [toggle|show|hide|status]
      • cmux --json quick-terminal status
  • Added localization strings for new Quick Terminal labels and settings.
  • Added/updated test coverage for shortcut metadata defaults.
  • Updated docs:
    • CHANGELOG (Unreleased)
    • README shortcut table and Quick Terminal CLI section.

Why

  • Provide a fast “drop-down style” terminal surface for quick interactions.
  • Make Quick Terminal scriptable for automation workflows.
  • Preserve user context by preventing socket/CLI calls from stealing macOS app focus.
  • Improve concurrency safety in Quick Terminal animation completion paths.

Testing

  • Local build/run:
    • ./scripts/reload.sh --tag quick-terminal
  • CLI smoke tests:
    • cmux-dev quick-terminal status
    • cmux-dev quick-terminal show
    • cmux-dev quick-terminal status
    • cmux-dev quick-terminal hide
    • cmux-dev --json quick-terminal status
  • Manual verification:
    • Shortcut Option+Command+` toggles Quick Terminal.
    • View menu action toggles Quick Terminal.
    • Command Palette action toggles Quick Terminal.
    • Settings values apply (position, primary size, secondary size, auto-hide).
    • Socket/CLI automation path does not steal frontmost app focus.
  • Notes:
    • No full local test suite run (repo policy favors CI for heavier suites).

Review Trigger (Copy/Paste as PR comment)

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

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

Summary by cubic

Adds a drop-down Quick Terminal panel with keyboard/menu/palette controls and scriptable CLI/socket APIs. Automation-safe: CLI/socket calls don’t steal macOS focus; supports configurable position, size, auto-hide, and restores the previous app when hiding.

  • New Features

    • Toggle via Option+Command+`, View menu, and Command Palette.
    • Settings: position (top/bottom/left/right/center), primary/secondary size, auto-hide on blur.
    • CLI: cmux quick-terminal [toggle|show|hide|status] and cmux --json quick-terminal status (prints visibility and settings).
    • Socket v2: quick_terminal.toggle, quick_terminal.show, quick_terminal.hide, quick_terminal.status.
  • Bug Fixes

    • Queue show/hide actions during animations to avoid missed toggles and flicker.
    • Preserve native Cmd+` window cycling; allow toggle from within the Quick Terminal.

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

Summary by CodeRabbit

  • New Features

    • Quick Terminal panel: toggleable with default shortcut Option+Command+`
    • Configurable position, primary/secondary size ratios, and auto-hide in Preferences
    • Accessible via command palette and CLI commands (toggle | show | hide | status)
  • Documentation

    • Added README and changelog entries covering Quick Terminal, shortcut, and CLI usage
  • Tests

    • Added unit test validating the Quick Terminal shortcut defaults and metadata

Implements Quick Terminal across app shortcut/menu/settings, command palette, socket v2, and CLI (cmux quick-terminal).

Also ensures socket/CLI quick terminal commands do not steal macOS focus and wraps animation completion state updates on MainActor.

Adds README and CHANGELOG notes.

Closes manaflow-ai#327
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 23, 2026

@jemutorres is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector
Copy link
Copy Markdown

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dee46540-249f-47d5-a3ac-b66e9c7da9a4

📥 Commits

Reviewing files that changed from the base of the PR and between 603276c and cd779b1.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • CLI/cmux.swift
  • README.md
  • Sources/AppDelegate.swift
  • Sources/TerminalController.swift
  • cmuxTests/WorkspaceUnitTests.swift
✅ Files skipped from review due to trivial changes (3)
  • CHANGELOG.md
  • README.md
  • Sources/AppDelegate.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • CLI/cmux.swift

📝 Walkthrough

Walkthrough

Adds a Quick Terminal feature: a toggleable NSPanel terminal with configurable position/size and auto-hide; exposes keyboard shortcut (⌥⌘), command-palette action, Settings UI, CLI subcommands (cmux quick-terminal [toggle|show|hide|status]`), and v2 socket methods for external control and status.

Changes

Cohort / File(s) Summary
Core Quick Terminal Implementation
Sources/AppDelegate.swift
Implements QuickTerminalController/NSPanel, frame math for visible/hidden placements, animations, auto-hide, lifecycle/teardown, and public/scriptable APIs (toggle/show/hide/status and selector).
CLI & Socket Integration
CLI/cmux.swift, Sources/TerminalController.swift
Adds cmux quick-terminal CLI with subcommands and JSON/status output; registers v2 socket methods `quick_terminal.toggle
UI: Command Palette & Shortcuts
Sources/ContentView.swift, Sources/KeyboardShortcutSettings.swift
Registers palette.toggleQuickTerminal, maps to new KeyboardShortcutSettings.Action.toggleQuickTerminal, provides default ⌥⌘` binding and accessor for stored shortcut.
App Menu, Settings & Persistence
Sources/cmuxApp.swift
Persists shortcut, adds View menu item, adds Settings UI for Quick Terminal (position picker, primary/secondary ratio sliders, auto-hide toggle), and resets to defaults on “Reset All Settings”.
Localization & Documentation
Resources/Localizable.xcstrings, README.md, CHANGELOG.md
Adds English/Japanese localization entries for Quick Terminal UI and settings; documents CLI usage and keyboard shortcut in README and changelog.
Tests
cmuxTests/WorkspaceUnitTests.swift
Adds test validating toggleQuickTerminal shortcut metadata and defaults.
Small helpers / formatting
README.md, CHANGELOG.md
Updated documentation and changelog entries describing the feature and CLI/socket interfaces.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as App UI (Menu / Palette / Shortcut)
    participant CLI as CLI / External
    participant App as AppDelegate
    participant QT as QuickTerminalController (NSPanel)
    participant Term as TerminalSurface

    User->>UI: trigger toggle/show/hide
    CLI->>App: cmux quick-terminal [toggle|show|hide|status]
    UI->>App: toggleQuickTerminalVisibility(activateApp?)
    App->>QT: toggle/show/hide
    alt Show flow
        QT->>QT: compute finalFrame / hiddenFrame
        QT->>QT: create/configure NSPanel
        QT->>Term: instantiate/attach TerminalSurface
        QT->>QT: animate frame & alpha in
        QT-->>App: visible = true
    else Hide flow
        QT->>QT: animate frame & alpha out
        QT->>QT: hide/detach NSPanel
        QT-->>App: visible = false
    end
    App-->>UI: status / completion
    App-->>CLI: JSON status (if requested)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Poem

🐰 I dug a tiny terminal den,
press ⌥⌘` and pop—it opens then.
Panels slide with a gentle hum,
settings snug, your sessions come.
Hop in quick, the shell awaits—yum.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.52% 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 and concisely describes the main changes: adding a Quick Terminal panel with CLI/socket controls and automation-safe focus behavior.
Description check ✅ Passed The description comprehensively covers all required sections: summary of changes, rationale, testing approach with specific test cases, and a detailed checklist with most items completed.
Linked Issues check ✅ Passed The PR fully addresses issue #327 by implementing a complete Quick Terminal feature with UI controls (keyboard shortcut, menu, palette), configuration options (position, size, auto-hide), and automation interfaces (socket v2 methods and CLI commands).
Out of Scope Changes check ✅ Passed All changes directly support the Quick Terminal feature scope: UI integration, automation APIs, safety behavior, tests, localization, and documentation updates are all within the stated objectives.

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

✨ 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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 23, 2026

Greptile Summary

This PR implements end-to-end Quick Terminal integration — a drop-down style floating terminal panel — wired up across keyboard shortcut, View menu, command palette, settings UI, socket v2 API, and CLI. The implementation follows established app patterns well: QuickTerminalController is correctly @MainActor-isolated, animation completion handlers are safely wrapped in Task { @MainActor }, and socket/CLI paths correctly pass activateApp: false to prevent macOS focus stealing while still registering as focusIntentV2Methods to allow in-app focus mutations per the socket focus policy.

Key additions:

  • QuickTerminalController in AppDelegate.swift manages panel lifecycle, slide animations, previous-app restoration, and auto-hide via windowDidResignKey
  • Socket v2 handlers (quick_terminal.toggle/show/hide/status) in TerminalController.swift
  • CLI subcommand cmux quick-terminal [toggle|show|hide|status] with plain-text and --json output
  • Full settings UI for position, primary/secondary size ratios, and auto-hide toggle
  • English + Japanese localization strings for all new surfaces
  • One P1 concern: the available fallback in formatQuickTerminalStatusPayload defaults to true when the key is absent — it should default to false to avoid falsely reporting availability
  • Minor indentation inconsistency in QuickTerminalController.show() around the previousFrontmostApp capture block
  • The new test's defaultsKey assertion verifies a string constant rather than observable behavior, which is borderline per the CLAUDE.md test quality policy

Confidence Score: 4/5

  • This PR is safe to merge after fixing the available fallback default in the CLI status formatter.
  • The feature is well-structured and follows existing app patterns throughout. The activateApp: false approach correctly prevents macOS focus stealing, MainActor isolation is consistent, and all user-facing strings are localized. The one concrete issue — ?? true for available in formatQuickTerminalStatusPayload — is a P1 logic concern but affects only the plain-text CLI output path when the key is unexpectedly absent, not core functionality. Everything else is P2 style/quality feedback.
  • CLI/cmux.swift (available fallback default) and Sources/AppDelegate.swift (indentation in show())

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Adds QuickTerminalSettings, QuickTerminalPosition, QuickTerminalController, and AppDelegate integration. Core logic is solid (MainActor isolation, Task-wrapped completionHandler, activateApp/restorePreviousApp flow). Minor indentation inconsistency at lines 2140–2145.
CLI/cmux.swift Adds runQuickTerminal and formatQuickTerminalStatusPayload. Subcommand routing and error handling are clean. The available fallback defaulting to true (line 2630) is a minor safety concern that should default to false.
Sources/TerminalController.swift Adds quick_terminal.* V2 socket handlers and registers them in both focusIntentV2Methods and the command allowlist. Handlers correctly pass activateApp: false to prevent macOS focus stealing while still allowing in-app focus mutations per the focus policy.
Sources/cmuxApp.swift Adds View menu item, AppStorage bindings, and Settings UI for Quick Terminal position, size, and auto-hide. All strings are localized; settings reset path updated correctly.
cmuxTests/WorkspaceUnitTests.swift Adds testToggleQuickTerminalShortcutDefaultsAndMetadata covering label, defaultsKey, and shortcut modifier defaults. The defaultsKey assertion tests a static string constant rather than observable behavior (borderline per CLAUDE.md test policy).

Sequence Diagram

sequenceDiagram
    participant User
    participant Shortcut/Menu/Palette
    participant AppDelegate
    participant QuickTerminalController
    participant NSPanel
    participant SocketCLI as Socket/CLI
    participant TerminalController

    User->>Shortcut/Menu/Palette: Toggle Quick Terminal
    Shortcut/Menu/Palette->>AppDelegate: toggleQuickTerminal(_:)
    AppDelegate->>QuickTerminalController: toggle(activateApp: true)
    QuickTerminalController->>NSPanel: orderFront + makeKeyAndOrderFront
    QuickTerminalController->>NSPanel: animate (hidden→final frame, α 0→1)
    NSPanel-->>QuickTerminalController: completionHandler (Task @MainActor)
    QuickTerminalController->>NSPanel: level .floating, makeFirstResponder

    SocketCLI->>TerminalController: quick_terminal.toggle/show/hide
    TerminalController->>AppDelegate: toggleQuickTerminalVisibility(activateApp: false)
    AppDelegate->>QuickTerminalController: toggle(activateApp: false)
    QuickTerminalController->>NSPanel: orderFront (no makeKeyAndOrderFront)
    Note over QuickTerminalController,NSPanel: macOS app focus NOT stolen
    TerminalController->>SocketCLI: status payload (visible, position, sizes, auto_hide)

    NSPanel->>QuickTerminalController: windowDidResignKey (autoHide=true)
    QuickTerminalController->>NSPanel: animate (final→hidden frame, α 1→0)
    NSPanel-->>QuickTerminalController: completionHandler (Task @MainActor)
    QuickTerminalController->>NSPanel: orderOut
    QuickTerminalController->>AppDelegate: previousFrontmostApp.activate (if set)
Loading

Comments Outside Diff (1)

  1. cmuxTests/WorkspaceUnitTests.swift, line 1329-1342 (link)

    P2 Test partially verifies implementation shape rather than observable behavior

    Per the CLAUDE.md test quality policy, tests should verify observable runtime behavior through executable paths, not implementation shape. The defaultsKey assertion (== "shortcut.toggleQuickTerminal") checks that a constant in source code equals a specific string — if the key changed, the test would catch it, but so would the runtime (UserDefaults would simply not restore the saved shortcut). This assertion effectively tests a string constant against itself.

    The label and defaultShortcut property assertions are more defensible since they exercise the localization and shortcut-resolution paths at runtime. Consider dropping the defaultsKey check, or if the key name matters for a migration story, add a comment explaining why.

    This same pattern exists in neighbouring tests (e.g., testWorkspaceRenameShortcutDefaultsAndMetadata), so this isn't unique to this PR, but it's worth noting for consistency with the policy going forward.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "feat: add quick terminal controls and au..." | Re-trigger Greptile

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

1 issue found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Sources/AppDelegate.swift">

<violation number="1" location="Sources/AppDelegate.swift:2128">
P2: Quick-terminal show/hide requests are dropped during animations: `show`/`hide` both `return` when `isTransitioning == true` and there’s no pending action replay in the completion handlers. A rapid `show` then `hide` (or toggle) will ignore the hide and leave the panel visible, causing automation-visible state mismatches.</violation>
</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

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

jemutorres and others added 2 commits March 23, 2026 13:13
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
cmuxTests/WorkspaceUnitTests.swift (1)

188-194: Add key-equivalent conversion assertions for the backtick shortcut.

Since ` is a special key in menu routing paths, consider asserting keyEquivalent/menuItemKeyEquivalent and eventModifiers here too (similar to other shortcut tests) to catch regressions earlier.

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

In `@cmuxTests/WorkspaceUnitTests.swift` around lines 188 - 194, The test
currently checks only the raw
KeyboardShortcutSettings.Action.toggleQuickTerminal.defaultShortcut fields; add
assertions that its keyEquivalent (or menuItemKeyEquivalent) equals "`" and that
the computed eventModifiers/menu event modifiers match the expected set (command
+ option, no shift/control) so the shortcut's
keyEquivalent/menuItemKeyEquivalent and eventModifiers are validated like the
other shortcut tests; locate the shortcut via
KeyboardShortcutSettings.Action.toggleQuickTerminal.defaultShortcut and assert
both the menu key equivalent property and the event modifier representation to
catch routing regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Line 8: In CHANGELOG.md, escape the literal backtick in the shortcut text so
Markdown doesn't start an inline code span: replace the unescaped sequence
"Option+Command+`" with an escaped backtick form (e.g., "Option+Command+\`") or
wrap the whole shortcut safely as a code span that includes the escaped backtick
(e.g., `Option+Command+\``) so the "(default: ...)" text renders and lints
correctly.

In `@CLI/cmux.swift`:
- Around line 2596-2599: The parsing treats "--" as a subcommand when it's the
first token; update the logic that computes subcommand and remaining to
normalize commandArgs by removing a leading "--" (and any leading-only
separators) before selecting subcommand. Specifically, in the block that reads
commandArgs and assigns subcommand and remaining, first strip a leading "--"
from commandArgs (or skip all leading elements equal to "--"), then compute
subcommand = commandArgs.first?.lowercased() ?? "toggle" and remaining =
Array(commandArgs.dropFirst()).filter { $0 != "--" }; keep the existing
unknown-argument error throw but base it on the normalized args so "cmux
quick-terminal -- status" correctly interprets "status" as the subcommand.

In `@README.md`:
- Line 138: The markdown table row contains a raw backtick in the shortcut text
("⌥ ⌘ `") which can break rendering; update the README table row to escape the
backtick (e.g., use "⌥ ⌘ \`") or wrap the key(s) in <kbd> tags (e.g.,
<kbd>⌥</kbd> <kbd>⌘</kbd> <kbd>`</kbd>) so the shortcut displays correctly; edit
the cell that currently contains "⌥ ⌘ `".

In `@Sources/AppDelegate.swift`:
- Around line 9636-9641: The quick-terminal toggle currently consumes bare Cmd+`
(keyCode 50) or Cmd+Shift+` before AppKit can perform window cycling; before
calling matchShortcut/toggleQuickTerminalVisibility in AppDelegate.swift, add a
guard that rejects events where event.keyCode == 50 and the modifier flags
represent Command alone or Command+Shift (i.e., contains .command and optionally
.shift but no other modifiers), returning false so AppKit can handle native
window switching; alternatively, ensure KeyboardShortcutSettings.shortcut(for:
.toggleQuickTerminal) cannot be set to that key combo, but the immediate fix is
to check event.keyCode == 50 and modifierFlags and skip handling in this branch.

In `@Sources/TerminalController.swift`:
- Around line 141-143: The focus-intent allowlist erroneously includes
quick_terminal.toggle, quick_terminal.show, and quick_terminal.hide which grants
socket/CLI automation the ability to change in-app focus; remove these three
command entries from the allowlist (the list/array that currently contains
"quick_terminal.toggle", "quick_terminal.show", "quick_terminal.hide") so only
explicit focus-intent commands remain (e.g., window.focus, workspace.select/...,
surface.focus, pane.focus, browser focus commands and v1 focus equivalents);
after removal, run existing focus-related unit/integration checks to ensure no
other code depends on those quick_terminal entries and update any test mocks or
documentation referencing them.

---

Nitpick comments:
In `@cmuxTests/WorkspaceUnitTests.swift`:
- Around line 188-194: The test currently checks only the raw
KeyboardShortcutSettings.Action.toggleQuickTerminal.defaultShortcut fields; add
assertions that its keyEquivalent (or menuItemKeyEquivalent) equals "`" and that
the computed eventModifiers/menu event modifiers match the expected set (command
+ option, no shift/control) so the shortcut's
keyEquivalent/menuItemKeyEquivalent and eventModifiers are validated like the
other shortcut tests; locate the shortcut via
KeyboardShortcutSettings.Action.toggleQuickTerminal.defaultShortcut and assert
both the menu key equivalent property and the event modifier representation to
catch routing regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24332016-970b-4090-a95e-b058dbf0ad31

📥 Commits

Reviewing files that changed from the base of the PR and between 2aeb101 and bf7f13c.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • CLI/cmux.swift
  • README.md
  • Resources/Localizable.xcstrings
  • Sources/AppDelegate.swift
  • Sources/ContentView.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/TerminalController.swift
  • Sources/cmuxApp.swift
  • cmuxTests/WorkspaceUnitTests.swift

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
Sources/AppDelegate.swift (2)

9636-9641: ⚠️ Potential issue | 🟠 Major

Don't let this bypass palette protection or native `Cmd+`` window cycling.

Because this branch runs before the palette-consumption guard and doesn't reserve keyCode == 50, a user-assigned quick-terminal shortcut can still fire while the command palette is typing, and bare Cmd+\`` / Cmd+Shift+`` can preempt AppKit's native window switcher.

🛡️ Suggested guard
+        let isReservedWindowCycleShortcut =
+            event.keyCode == 50 &&
+            (normalizedFlags == [.command] || normalizedFlags == [.command, .shift])
+
         // Allow quick-terminal toggle even when the key event comes from the quick
         // panel itself (which is not a main terminal window context).
-        if matchShortcut(event: event, shortcut: KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal)) {
+        if !commandPaletteEffectiveInTargetWindow,
+           !isReservedWindowCycleShortcut,
+           matchShortcut(event: event, shortcut: KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal)) {
             _ = toggleQuickTerminalVisibility()
             return true
         }
Based on learnings, "Cmd+` (command-backtick) should not be routed directly" and "when the command palette is visible ... do not reorder shortcut handlers to bypass this guard."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/AppDelegate.swift` around lines 9636 - 9641, The current early-return
branch that matches matchShortcut(... shortcut: .toggleQuickTerminal) and calls
toggleQuickTerminalVisibility() must not bypass the command-palette guard or
allow native Cmd+` (keyCode == 50) to be handled here; update the condition to
first check the palette-consumption guard (the same guard used elsewhere to
prevent palette key handling) and explicitly ignore events with keyCode == 50
(and when necessary with shift modifier for Cmd+Shift+`) before calling
toggleQuickTerminalVisibility(); locate the matchShortcut call,
KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal) lookup, and
toggleQuickTerminalVisibility invocation and add the additional checks so the
quick-terminal shortcut is suppressed while the palette is visible and does not
preempt AppKit window cycling.

2119-2125: ⚠️ Potential issue | 🟠 Major

Return whether the quick-terminal request actually ran.

show/hide can legitimately no-op here (isTransitioning, already visible/hidden, or ensurePanel() failure). Returning Void makes those dropped requests indistinguishable from a real state change for automation callers.

Also applies to: 2127-2130, 2191-2198

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

In `@Sources/AppDelegate.swift` around lines 2119 - 2125, Change the
toggle/show/hide call paths to return a Bool indicating whether the requested
show/hide actually ran (instead of Void) so automation callers can distinguish
no-ops; update toggle(activateApp:) to return Bool and return the result of
calling show(activateApp:) or hide(restorePreviousApp:), and similarly change
the other related methods (the other toggle overloads and the show/hide
functions referenced in this diff) to return Bool and propagate true only when
the action proceeds (i.e. not isTransitioning, not already in the target state,
and ensurePanel() succeeded) and false when they legitimately no-op.
🧹 Nitpick comments (1)
Sources/AppDelegate.swift (1)

5764-5789: Default the scriptable quick-terminal APIs to non-activating behavior.

These wrappers are the automation-facing entry points, but their defaults still opt into activation/restoration. Making the safe behavior the default here reduces the chance of a future CLI/socket caller regressing the no-focus-steal contract.

♻️ Suggested change
-    func toggleQuickTerminalVisibility(activateApp: Bool = true) -> Bool {
+    func toggleQuickTerminalVisibility(activateApp: Bool = false) -> Bool {
         quickTerminalController.toggle(activateApp: activateApp)
         return true
     }

-    func showQuickTerminal(activateApp: Bool = true) -> Bool {
+    func showQuickTerminal(activateApp: Bool = false) -> Bool {
         quickTerminalController.show(activateApp: activateApp)
         return true
     }

-    func hideQuickTerminal(restorePreviousApp: Bool = true) -> Bool {
+    func hideQuickTerminal(restorePreviousApp: Bool = false) -> Bool {
         quickTerminalController.hide(restorePreviousApp: restorePreviousApp)
         return true
     }

     `@objc` func toggleQuickTerminal(_ sender: Any?) {
         _ = sender
-        _ = toggleQuickTerminalVisibility()
+        _ = toggleQuickTerminalVisibility(activateApp: true)
     }
As per coding guidelines, "Socket/CLI commands must not steal macOS app focus (no app activation/window raising side effects)."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/AppDelegate.swift` around lines 5764 - 5789, Change the scriptable
quick-terminal wrapper defaults to avoid activating or restoring the app: update
the default parameter values on toggleQuickTerminalVisibility(activateApp: Bool
= true), showQuickTerminal(activateApp: Bool = true), and
hideQuickTerminal(restorePreviousApp: Bool = true) to false, and ensure the ObjC
wrapper toggleQuickTerminal(_:) calls toggleQuickTerminalVisibility(activateApp:
false) (or otherwise forwards false) so automation/CLI/socket callers do not
cause app activation; locate these symbols: toggleQuickTerminalVisibility,
showQuickTerminal, hideQuickTerminal, and toggleQuickTerminal to make the edits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Sources/AppDelegate.swift`:
- Around line 9636-9641: The current early-return branch that matches
matchShortcut(... shortcut: .toggleQuickTerminal) and calls
toggleQuickTerminalVisibility() must not bypass the command-palette guard or
allow native Cmd+` (keyCode == 50) to be handled here; update the condition to
first check the palette-consumption guard (the same guard used elsewhere to
prevent palette key handling) and explicitly ignore events with keyCode == 50
(and when necessary with shift modifier for Cmd+Shift+`) before calling
toggleQuickTerminalVisibility(); locate the matchShortcut call,
KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal) lookup, and
toggleQuickTerminalVisibility invocation and add the additional checks so the
quick-terminal shortcut is suppressed while the palette is visible and does not
preempt AppKit window cycling.
- Around line 2119-2125: Change the toggle/show/hide call paths to return a Bool
indicating whether the requested show/hide actually ran (instead of Void) so
automation callers can distinguish no-ops; update toggle(activateApp:) to return
Bool and return the result of calling show(activateApp:) or
hide(restorePreviousApp:), and similarly change the other related methods (the
other toggle overloads and the show/hide functions referenced in this diff) to
return Bool and propagate true only when the action proceeds (i.e. not
isTransitioning, not already in the target state, and ensurePanel() succeeded)
and false when they legitimately no-op.

---

Nitpick comments:
In `@Sources/AppDelegate.swift`:
- Around line 5764-5789: Change the scriptable quick-terminal wrapper defaults
to avoid activating or restoring the app: update the default parameter values on
toggleQuickTerminalVisibility(activateApp: Bool = true),
showQuickTerminal(activateApp: Bool = true), and
hideQuickTerminal(restorePreviousApp: Bool = true) to false, and ensure the ObjC
wrapper toggleQuickTerminal(_:) calls toggleQuickTerminalVisibility(activateApp:
false) (or otherwise forwards false) so automation/CLI/socket callers do not
cause app activation; locate these symbols: toggleQuickTerminalVisibility,
showQuickTerminal, hideQuickTerminal, and toggleQuickTerminal to make the edits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 32da7582-8e06-454e-a983-b6f00dc0cbc9

📥 Commits

Reviewing files that changed from the base of the PR and between bf7f13c and 603276c.

📒 Files selected for processing (2)
  • CLI/cmux.swift
  • Sources/AppDelegate.swift
✅ Files skipped from review due to trivial changes (1)
  • CLI/cmux.swift

@jemutorres
Copy link
Copy Markdown
Author

Hi! The PR is ready for review. All checks pass except Vercel (likely permission-related).
Could a maintainer approve the workflows so checks can run?

Thank you! :)

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.

Does cmux support quick terminal?

1 participant