Skip to content

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

Closed
jemutorres wants to merge 6 commits into
manaflow-ai:mainfrom
jemutorres:feat/quick-terminal-327
Closed

jemutorres wants to merge 6 commits into
manaflow-ai:mainfrom
jemutorres:feat/quick-terminal-327

Conversation

@jemutorres

@jemutorres jemutorres commented Mar 23, 2026 •

Copy link
Copy Markdown

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 availability, visibility, position, auto-hide, and size ratios).
    • 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 7a9b528. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Quick Terminal panel with default shortcut Option+Command+`
    • Configurable position, primary/secondary size ratios, and auto-hide in Preferences
    • Toggle via menu/command palette and CLI commands (toggle | show | hide | status)
  • Documentation
    • Added README and changelog entries describing Quick Terminal, shortcut, and CLI usage
  • Localization
    • Added English and Japanese strings for Quick Terminal UI and settings
  • Tests
    • Added unit test validating Quick Terminal shortcut defaults and metadata

@vercel

vercel Bot commented Mar 23, 2026

Copy link
Copy Markdown

@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

coderabbitai Bot commented Mar 23, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a Quick Terminal feature: a toggleable NSPanel terminal with configurable position/size and auto-hide; exposes a 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 QuickTerminalSettings/ResolvedSettings/Position, QuickTerminalPanel, QuickTerminalController with show/hide/toggle, animations, auto-hide, activation/restore, teardown, and public/scriptable APIs (toggle/show/hide/status and selector).
CLI Integration
CLI/cmux.swift
Adds cmux quick-terminal subcommand parsing (`toggle
Socket / Server Handlers
Sources/TerminalController.swift
Registers v2 methods `quick_terminal.toggle
UI: Command Palette & Shortcuts
Sources/ContentView.swift, Sources/KeyboardShortcutSettings.swift
Registers palette.toggleQuickTerminal, adds KeyboardShortcutSettings.Action.toggleQuickTerminal, provides default ⌥⌘` binding and accessor, and maps command to AppDelegate toggle.
App Menu, Settings & Persistence
Sources/cmuxApp.swift
Adds View menu item for Toggle Quick Terminal, introduces @AppStorage settings for position/primary/secondary ratios and auto-hide, Settings UI rows, and reset-to-default handling.
Localization & Documentation
Resources/Localizable.xcstrings, README.md, CHANGELOG.md
Adds English/Japanese localization strings for UI, settings, and shortcuts; documents Quick Terminal CLI usage and keyboard shortcut in README and CHANGELOG.
Tests
cmuxTests/WorkspaceUnitTests.swift
Adds test testToggleQuickTerminalShortcutDefaultsAndMetadata validating shortcut metadata, default key/modifiers, and menu-equivalent fields.
Minor docs / changelog updates
README.md, CHANGELOG.md
Changelog/README entries announcing Quick Terminal, default shortcut, CLI commands, and JSON status behavior.

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
    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 5.66% 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 clearly summarizes the main change: introducing a Quick Terminal feature with CLI/socket controls and automation-safe focus behavior.
Description check ✅ Passed The description is comprehensive, covering all required template sections: Summary details all changes, Testing documents local verification and CLI tests, and includes bot review trigger block.
Linked Issues check ✅ Passed All coding requirements from issue #327 are met: Quick Terminal feature with keyboard shortcut, menu/palette integration, socket v2 methods (toggle/show/hide/status), CLI commands with JSON output, and automation-safe focus preservation.
Out of Scope Changes check ✅ Passed All changes are scope-aligned: Quick Terminal implementation files, documentation updates, localization strings, tests, and CLI/socket integrations directly support issue #327 requirements.

✏️ 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

greptile-apps Bot commented Mar 23, 2026 •

Copy link
Copy Markdown
Contributor

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

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

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.

Comment thread Sources/AppDelegate.swift Outdated
Comment thread Sources/AppDelegate.swift Outdated
Comment thread CLI/cmux.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: 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

Comment thread CHANGELOG.md Outdated
Comment thread CLI/cmux.swift Outdated
Comment thread README.md Outdated
Comment thread Sources/AppDelegate.swift
Comment thread Sources/TerminalController.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.

♻️ 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! :)

@mrueg

mrueg commented Apr 15, 2026

Copy link
Copy Markdown

Would be great to see this feature in.

@jemutorres could you rebase this change so it applies cleanly?

jemutorres and others added 6 commits April 21, 2026 09:27
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
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>
@jemutorres
jemutorres force-pushed the feat/quick-terminal-327 branch from cd779b1 to 7a9b528 Compare April 21, 2026 07:50

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

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

2396-2515: Add debug logs for Quick Terminal focus transitions.

show/hide changes panel visibility, key-window state, and terminal focus, but the new paths do not emit dlog() entries. Add concise request/result logs around queued transitions, activation mode, and completion state.

Example instrumentation
     func show(activateApp: Bool = true) {
+#if DEBUG
+        dlog("quickTerminal.show request activate=\(activateApp ? 1 : 0) visible=\(isVisible ? 1 : 0) transitioning=\(isTransitioning ? 1 : 0)")
+#endif
         if isTransitioning {
             pendingTransitionAction = .show(activateApp: activateApp)
             return
         }
@@
                 self.isTransitioning = false
                 panel.level = .floating
+#if DEBUG
+                dlog("quickTerminal.show complete activate=\(activateApp ? 1 : 0) visible=\(self.isVisible ? 1 : 0)")
+#endif
                 if activateApp {
@@
     func hide(restorePreviousApp: Bool) {
+#if DEBUG
+        dlog("quickTerminal.hide request restorePreviousApp=\(restorePreviousApp ? 1 : 0) visible=\(isVisible ? 1 : 0) transitioning=\(isTransitioning ? 1 : 0)")
+#endif
         if isTransitioning {
             pendingTransitionAction = .hide(restorePreviousApp: restorePreviousApp)
             return
         }
@@
                 self.isTransitioning = false
                 panel.orderOut(nil)
+#if DEBUG
+                dlog("quickTerminal.hide complete restorePreviousApp=\(restorePreviousApp ? 1 : 0) visible=\(self.isVisible ? 1 : 0)")
+#endif
                 self.terminalSurface?.hostedView.setActive(false)

As per coding guidelines, **/*.swift: “All debug events (keys, mouse, focus, splits, tabs) must be logged to the unified debug log using the dlog() function and wrapped in #if DEBUG / #endif preprocessor directives”.

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

In `@Sources/AppDelegate.swift` around lines 2396 - 2515, The show/toggle/hide
flows lack debug logging; add concise dlog() calls wrapped in `#if` DEBUG / `#endif`
in toggle(activateApp:), show(activateApp:), and hide(restorePreviousApp:) to
record transition requests (including pendingTransitionAction state), activation
mode (activateApp / restorePreviousApp and whether NSApp was active), queued
actions when isTransitioning is true, and completion results (visibility state,
panel.level, previousFrontmostApp activation result, and terminalSurface focus
changes). Place logs at the start of each method (log inputs and early returns),
when you set pendingTransitionAction, before/after calling
panel.orderFront/orderOut or makeKeyAndOrderFront, and inside both
completionHandler blocks to report final state and any activation of
previousFrontmostApp; reference symbols: toggle(activateApp:),
show(activateApp:), hide(restorePreviousApp:), pendingTransitionAction,
previousFrontmostApp, terminalSurface.hostedView, and panel. Ensure all added
dlog() calls are inside `#if` DEBUG guards.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CLI/cmux.swift`:
- Around line 2848-2853: The quick-terminal subcommand is being dispatched after
the global --window pre-focus block and thus can inadvertently trigger app
focusing; update the dispatch logic so quick-terminal does not run through that
pre-focus path by either moving the case "quick-terminal" branch (the call to
runQuickTerminal) to execute before the global --window pre-focus block or by
short-circuiting the pre-focus logic when the parsed subcommand equals
"quick-terminal"; change the condition around the pre-focus block (or add an
explicit guard) to skip focusing for this subcommand, referencing the case
"quick-terminal" and the runQuickTerminal(...) call to locate and adjust the
code.

In `@Sources/AppDelegate.swift`:
- Around line 11434-11439: The current quick-terminal shortcut check uses
matchShortcut(event: , shortcut:) which bypasses chord handling; replace that
check with the configured-chord-aware path by calling
activeConfiguredShortcutChordPrefixForCurrentEvent(event, shortcut:
KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal)) (or the app's
equivalent chord-aware matcher) so chorded .toggleQuickTerminal shortcuts can
arm and then execute properly, then call toggleQuickTerminalVisibility() and
return true when the chord-aware matcher indicates a full match.

In `@Sources/cmuxApp.swift`:
- Around line 4629-4631: Replace the hard-coded percent label in
quickTerminalRatioPercentLabel by using a localized formatted string key (e.g.
"settings.quickTerminal.ratioPercent") and feed the computed
Int((QuickTerminalSettings.clampRatio(ratio) * 100).rounded()) as the format
argument via String(localized:..., ...) so the percent symbol and number are
localizable; also add the "settings.quickTerminal.ratioPercent" entry to
Resources/Localizable.xcstrings for all supported languages with an appropriate
format placeholder (e.g. "%d%%") and translated variants.
- Around line 4650-4694: The sliders and toggle lack accessible labels/values;
update the controls in SettingsCardRow so each Slider (bound via
quickTerminalPrimarySizeBinding and quickTerminalSecondarySizeBinding) has an
accessibilityLabel using the same localized title (e.g.,
"settings.quickTerminal.primarySize" / "settings.quickTerminal.secondarySize")
and an accessibilityValue set to quickTerminalRatioPercentLabel(…) so screen
readers read the percent, and update the Toggle (bound to quickTerminalAutoHide)
to remove the empty-string label and instead set an accessibilityLabel using the
localized "settings.quickTerminal.autoHide" title and an accessibilityHint or
accessibilityValue reflecting the on/off subtitle strings so assistive tech gets
explicit labels and state.

---

Nitpick comments:
In `@Sources/AppDelegate.swift`:
- Around line 2396-2515: The show/toggle/hide flows lack debug logging; add
concise dlog() calls wrapped in `#if` DEBUG / `#endif` in toggle(activateApp:),
show(activateApp:), and hide(restorePreviousApp:) to record transition requests
(including pendingTransitionAction state), activation mode (activateApp /
restorePreviousApp and whether NSApp was active), queued actions when
isTransitioning is true, and completion results (visibility state, panel.level,
previousFrontmostApp activation result, and terminalSurface focus changes).
Place logs at the start of each method (log inputs and early returns), when you
set pendingTransitionAction, before/after calling panel.orderFront/orderOut or
makeKeyAndOrderFront, and inside both completionHandler blocks to report final
state and any activation of previousFrontmostApp; reference symbols:
toggle(activateApp:), show(activateApp:), hide(restorePreviousApp:),
pendingTransitionAction, previousFrontmostApp, terminalSurface.hostedView, and
panel. Ensure all added dlog() calls are inside `#if` DEBUG guards.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 577a641d-c1ce-4ffb-9063-7a175f5a5fde

📥 Commits

Reviewing files that changed from the base of the PR and between cd779b1 and 7a9b528.

📒 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
✅ Files skipped from review due to trivial changes (5)
  • README.md
  • cmuxTests/WorkspaceUnitTests.swift
  • CHANGELOG.md
  • Resources/Localizable.xcstrings
  • Sources/TerminalController.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/KeyboardShortcutSettings.swift

Comment thread CLI/cmux.swift
Comment on lines +2848 to +2853
case "quick-terminal":
try runQuickTerminal(
commandArgs: commandArgs,
client: client,
jsonOutput: jsonOutput
)

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

Bypass global --window focusing for Quick Terminal.

quick-terminal is dispatched after the global --window pre-focus block, so cmux --window ... quick-terminal status|show|hide|toggle can focus/raise cmux before running this non-focus automation command. Route it before that block, or explicitly skip pre-focus for this command.

Proposed fix
         try authenticateClientIfNeeded(
             client,
             explicitPassword: socketPasswordArg,
             socketPath: resolvedSocketPath
         )
 
+        if command == "quick-terminal" {
+            try runQuickTerminal(
+                commandArgs: commandArgs,
+                client: client,
+                jsonOutput: jsonOutput
+            )
+            return
+        }
+
         let idFormat = try resolvedIDFormat(jsonOutput: jsonOutput, raw: idFormatArg)
 
         // If the user explicitly targets a window, focus it first so commands route correctly.
         if let windowId {
             let normalizedWindow = try normalizeWindowHandle(windowId, client: client) ?? windowId
             _ = try client.sendV2(method: "window.focus", params: ["window_id": normalizedWindow])
         }
-        case "quick-terminal":
-            try runQuickTerminal(
-                commandArgs: commandArgs,
-                client: client,
-                jsonOutput: jsonOutput
-            )
-

As per coding guidelines, Socket/CLI commands must not steal macOS app focus; only explicit focus-intent commands may mutate in-app focus/selection.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "quick-terminal":
try runQuickTerminal(
commandArgs: commandArgs,
client: client,
jsonOutput: jsonOutput
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLI/cmux.swift` around lines 2848 - 2853, The quick-terminal subcommand is
being dispatched after the global --window pre-focus block and thus can
inadvertently trigger app focusing; update the dispatch logic so quick-terminal
does not run through that pre-focus path by either moving the case
"quick-terminal" branch (the call to runQuickTerminal) to execute before the
global --window pre-focus block or by short-circuiting the pre-focus logic when
the parsed subcommand equals "quick-terminal"; change the condition around the
pre-focus block (or add an explicit guard) to skip focusing for this subcommand,
referencing the case "quick-terminal" and the runQuickTerminal(...) call to
locate and adjust the code.

Comment thread Sources/AppDelegate.swift
Comment on lines +11434 to +11439
// 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)) {
_ = toggleQuickTerminalVisibility()
return true
}

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 | 🟡 Minor

Use configured-shortcut matching so Quick Terminal chords work.

This raw matchShortcut path bypasses activeConfiguredShortcutChordPrefixForCurrentEvent, so a chorded .toggleQuickTerminal shortcut can arm its first stroke later but never execute on the second stroke.

Proposed fix
-        if matchShortcut(event: event, shortcut: KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal)) {
+        if matchConfiguredShortcut(event: event, action: .toggleQuickTerminal) {
             _ = toggleQuickTerminalVisibility()
             return true
         }
+
+        if activeConfiguredShortcutChordPrefixForCurrentEvent == nil,
+           armConfiguredShortcutChordIfNeeded(event: event, actions: [.toggleQuickTerminal]) {
+            return true
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/AppDelegate.swift` around lines 11434 - 11439, The current
quick-terminal shortcut check uses matchShortcut(event: , shortcut:) which
bypasses chord handling; replace that check with the configured-chord-aware path
by calling activeConfiguredShortcutChordPrefixForCurrentEvent(event, shortcut:
KeyboardShortcutSettings.shortcut(for: .toggleQuickTerminal)) (or the app's
equivalent chord-aware matcher) so chorded .toggleQuickTerminal shortcuts can
arm and then execute properly, then call toggleQuickTerminalVisibility() and
return true when the chord-aware matcher indicates a full match.

Comment thread Sources/cmuxApp.swift
Comment on lines +4629 to +4631
private func quickTerminalRatioPercentLabel(_ ratio: Double) -> String {
"\(Int((QuickTerminalSettings.clampRatio(ratio) * 100).rounded()))%"
}

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 | 🟡 Minor

Localize the percentage label.

Line 4630 creates user-facing Settings text without a localization key, so translators cannot adapt the percent label.

🌐 Proposed fix
 private func quickTerminalRatioPercentLabel(_ ratio: Double) -> String {
-    "\(Int((QuickTerminalSettings.clampRatio(ratio) * 100).rounded()))%"
+    let percent = Int((QuickTerminalSettings.clampRatio(ratio) * 100).rounded())
+    return String(
+        localized: "settings.quickTerminal.ratioPercent",
+        defaultValue: "\(percent)%"
+    )
 }

Also add settings.quickTerminal.ratioPercent to Resources/Localizable.xcstrings for all supported languages.

As per coding guidelines, All user-facing strings must be localized using String(localized: "key.name", defaultValue: "English text") and added to Resources/Localizable.xcstrings with translations for all supported languages.

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

In `@Sources/cmuxApp.swift` around lines 4629 - 4631, Replace the hard-coded
percent label in quickTerminalRatioPercentLabel by using a localized formatted
string key (e.g. "settings.quickTerminal.ratioPercent") and feed the computed
Int((QuickTerminalSettings.clampRatio(ratio) * 100).rounded()) as the format
argument via String(localized:..., ...) so the percent symbol and number are
localizable; also add the "settings.quickTerminal.ratioPercent" entry to
Resources/Localizable.xcstrings for all supported languages with an appropriate
format placeholder (e.g. "%d%%") and translated variants.

Comment thread Sources/cmuxApp.swift
Comment on lines +4650 to +4694
SettingsCardRow(
configurationReview: .settingsOnly,
String(localized: "settings.quickTerminal.primarySize", defaultValue: "Quick Terminal Primary Size"),
subtitle: String(localized: "settings.quickTerminal.primarySize.subtitle", defaultValue: "Size along the deployment axis.")
) {
HStack(spacing: 8) {
Slider(value: quickTerminalPrimarySizeBinding, in: 0.2...1.0)
.frame(width: 132)
Text(quickTerminalRatioPercentLabel(quickTerminalPrimarySizeRatio))
.font(.system(size: 11, weight: .medium))
.foregroundStyle(.secondary)
.frame(width: 42, alignment: .trailing)
}
}

SettingsCardDivider()

SettingsCardRow(
configurationReview: .settingsOnly,
String(localized: "settings.quickTerminal.secondarySize", defaultValue: "Quick Terminal Secondary Size"),
subtitle: String(localized: "settings.quickTerminal.secondarySize.subtitle", defaultValue: "Size on the opposite axis.")
) {
HStack(spacing: 8) {
Slider(value: quickTerminalSecondarySizeBinding, in: 0.2...1.0)
.frame(width: 132)
Text(quickTerminalRatioPercentLabel(quickTerminalSecondarySizeRatio))
.font(.system(size: 11, weight: .medium))
.foregroundStyle(.secondary)
.frame(width: 42, alignment: .trailing)
}
}

SettingsCardDivider()

SettingsCardRow(
configurationReview: .settingsOnly,
String(localized: "settings.quickTerminal.autoHide", defaultValue: "Quick Terminal Auto-Hide"),
subtitle: quickTerminalAutoHide
? String(localized: "settings.quickTerminal.autoHide.subtitleOn", defaultValue: "Hide automatically when it loses focus.")
: String(localized: "settings.quickTerminal.autoHide.subtitleOff", defaultValue: "Keep visible when focus moves to another app/window.")
) {
Toggle("", isOn: $quickTerminalAutoHide)
.labelsHidden()
.controlSize(.small)
}

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

Add accessible labels to the hidden Quick Terminal controls.

The two sliders and the empty-label toggle rely on nearby visual text, but that is not reliably associated for assistive tech.

♿ Proposed fix
                 HStack(spacing: 8) {
                     Slider(value: quickTerminalPrimarySizeBinding, in: 0.2...1.0)
                         .frame(width: 132)
+                        .accessibilityLabel(
+                            String(localized: "settings.quickTerminal.primarySize", defaultValue: "Quick Terminal Primary Size")
+                        )
+                        .accessibilityValue(quickTerminalRatioPercentLabel(quickTerminalPrimarySizeRatio))
                     Text(quickTerminalRatioPercentLabel(quickTerminalPrimarySizeRatio))
                         .font(.system(size: 11, weight: .medium))
                         .foregroundStyle(.secondary)
@@
                 HStack(spacing: 8) {
                     Slider(value: quickTerminalSecondarySizeBinding, in: 0.2...1.0)
                         .frame(width: 132)
+                        .accessibilityLabel(
+                            String(localized: "settings.quickTerminal.secondarySize", defaultValue: "Quick Terminal Secondary Size")
+                        )
+                        .accessibilityValue(quickTerminalRatioPercentLabel(quickTerminalSecondarySizeRatio))
                     Text(quickTerminalRatioPercentLabel(quickTerminalSecondarySizeRatio))
                         .font(.system(size: 11, weight: .medium))
                         .foregroundStyle(.secondary)
@@
                 Toggle("", isOn: $quickTerminalAutoHide)
                     .labelsHidden()
                     .controlSize(.small)
+                    .accessibilityLabel(
+                        String(localized: "settings.quickTerminal.autoHide", defaultValue: "Quick Terminal Auto-Hide")
+                    )
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/cmuxApp.swift` around lines 4650 - 4694, The sliders and toggle lack
accessible labels/values; update the controls in SettingsCardRow so each Slider
(bound via quickTerminalPrimarySizeBinding and
quickTerminalSecondarySizeBinding) has an accessibilityLabel using the same
localized title (e.g., "settings.quickTerminal.primarySize" /
"settings.quickTerminal.secondarySize") and an accessibilityValue set to
quickTerminalRatioPercentLabel(…) so screen readers read the percent, and update
the Toggle (bound to quickTerminalAutoHide) to remove the empty-string label and
instead set an accessibilityLabel using the localized
"settings.quickTerminal.autoHide" title and an accessibilityHint or
accessibilityValue reflecting the on/off subtitle strings so assistive tech gets
explicit labels and state.

@teamleaderleo

Copy link
Copy Markdown
Collaborator

cmux-reconcile: partly-useful

Usefulness verdict: Treat as an alternative Quick Terminal implementation; carry unique behavior into #4830 before retiring this branch.

This diff integrates a quick terminal with shortcut/menu/settings, CLI/socket controls, and non-focus-stealing automation. #4830 addresses the same capability with broader package-based settings and tests. The requirement remains useful (#327), so closing both as stale would lose active feature work. Compare focus, auto-hide, position/sizing and state ownership; consolidate one implementation. No claim that either is merge-ready.

Reviewed patch head: 7a9b5282de8dc7ef40dfec870104c560a2a76bad. Source/diff triage on September 18, 2026; no new build or runtime validation. No issue state, label, or merge decision changed.

Older issue/PR tracking index — remaining scope and competing implementations are recorded there.

@teamleaderleo

Copy link
Copy Markdown
Collaborator

This branch is superseded by the consolidation work in #4830, as noted in the maintainer reconciliation. The Quick Terminal requirement remains tracked there.

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?

3 participants