Skip to content

Warn or disable X-button tab close (#4622) - #4626

Closed
austinywang wants to merge 10 commits into
mainfrom
issue-4622-tab-x-button-warn
Closed

austinywang wants to merge 10 commits into
mainfrom
issue-4622-tab-x-button-warn

Conversation

@austinywang

@austinywang austinywang commented May 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Adds app.warnBeforeClosingTabXButton for tab-strip X-button close confirmations.
  • Routes X-button close attempts through the existing close confirmation dialog path by default, including idle terminals, workspace/sidebar tab X closes, and last-workspace/window close handling, while keeping app.warnBeforeClosingTab as the existing shortcut/close-command preference.
  • Makes the macOS red window close button use the Close Window confirmation dialog before the main terminal window is allowed to close.
  • Exposes the new preference in Settings, command-palette settings toggles, cmux.json parsing/template/schema, settings search, and JSON path support.

Preference keys

  • app.warnBeforeClosingTab: existing key, unchanged; still maps to warnBeforeClosingTabShortcut internally.
  • app.warnBeforeClosingTabXButton: new boolean key, maps to warnBeforeClosingTabXButton in UserDefaults. Defaults to true, so tab-strip X closes ask for confirmation by default. Users can set it to false to keep X-button closes immediate.

Localization keys

  • settings.app.warnBeforeClosingTabXButton
  • settings.app.warnBeforeClosingTabXButton.subtitleOn
  • settings.app.warnBeforeClosingTabXButton.subtitleOff
  • settings.search.alias.setting.app.warn-before-closing-tab-x-button

Migration

No explicit migration is required. Existing Cmd+W/close-command behavior is unchanged because app.warnBeforeClosingTab is unchanged. The new app.warnBeforeClosingTabXButton key defaults to true when unset, so existing users get confirmation from the tab-strip X button by default and can opt out in Settings or cmux.json.

Closes #4622.

Verification

  • CMUX_SKIP_ZIG_BUILD=1 ./scripts/reload.sh --tag issue-4622-tab-x-button-warn
  • git diff --check
  • jq empty web/data/cmux.schema.json

Unit tests were not run locally per repo policy; CI is the test verification path.

Summary by CodeRabbit

  • New Features
    • Added a new "Warn Before X-Button Tab Close" setting (separate from shortcut-based close warnings; defaults enabled).
    • Setting is searchable and available via the command palette toggle.
    • Updated localization and search tokens so the setting appears in Settings search in multiple locales.
    • Confirmation behavior refined so X-button and shortcut closes can prompt independently.

Review Change Stack

@vercel

vercel Bot commented May 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 23, 2026 5:54am
cmux-staging Building Building Preview, Comment May 23, 2026 5:54am

@coderabbitai

coderabbitai Bot commented May 23, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds app.warnBeforeClosingTabXButton: schema/localization, settings registration/parsing, command-palette toggle, Settings UI toggle, threads a CloseTabConfirmationTrigger through Workspace/TabManager close flows, and unit tests exercising X-button confirmation behavior.

Changes

X-Button Tab Close Warning

Layer / File(s) Summary
Settings definition & registration
web/data/cmux.schema.json, Resources/Localizable.xcstrings, Sources/CmuxSettingsJSONPathSupport.swift, Sources/KeyboardShortcutSettingsFileStore+Template.swift, Sources/KeyboardShortcutSettingsFileStore.swift, Sources/CommandPalette/CommandPaletteSettingsToggle.swift, Sources/SettingsNavigation.swift, Sources/SettingsSearchAliases.swift
Add app.warnBeforeClosingTabXButton to schema and localization; register the path in supported JSON paths, include template default, parse the field into managed defaults, add command-palette toggle descriptor, and register settings navigation/search alias entries.
Warning policy & trigger types
Sources/cmuxApp.swift
Introduce CloseTabConfirmationTrigger and X-button-specific CloseTabWarningSettings accessors. Update CloseTabConfirmationPolicy to accept a trigger and consult the appropriate stored preference.
Close-flow instrumentation
Sources/Workspace.swift, Sources/TabManager.swift, Sources/WorkspaceCloseTabsBatching.swift, Sources/ContentView.swift
Replace explicit-close Set with per-tab trigger mapping, mark closes with .tabCloseButton from UI, forward trigger through closeWorkspaceFromCloseTabGesture, and use trigger when evaluating CloseTabConfirmationPolicy.shouldConfirm.
Settings UI & persistence
Sources/cmuxApp.swift
Add SettingsView state/binding and a toggle row with localized on/off subtitles for the X-button warning; reset behavior and AppStorage binding updated.
Feature tests
cmuxTests/TabManagerUnitTests.swift, cmuxTests/AppDelegateShortcutRoutingTests.swift
Add tests and helpers to assert confirmation behavior for X-button closes under enabled, disabled, and unset/inherit states; refactor test harness to manage both warning keys in UserDefaults and temporary cmux.json. Also add AppDelegate close-button tests verifying modal routing.

Sequence Diagram

sequenceDiagram
  participant User
  participant TabUI as Tab UI
  participant Workspace
  participant TabManager
  participant Policy as CloseTabConfirmationPolicy

  User->>TabUI: Click X button
  TabUI->>Workspace: onTabCloseRequest(tabID)
  Workspace->>Workspace: markExplicitClose(tabID, trigger: .tabCloseButton)
  Workspace->>TabManager: closeWorkspaceFromCloseTabGesture(workspace, trigger: .tabCloseButton)
  TabManager->>Policy: shouldConfirm(..., trigger: .tabCloseButton)
  Policy-->>TabManager: (true/false)
  TabManager-->>User: show confirmation or close immediately
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • manaflow-ai/cmux#2808: Related prior changes to close-confirmation plumbing in TabManager/Workspace/cmuxApp that this PR extends to a separate X-button trigger/setting.

Poem

A rabbit taps the tab with care,
Adds a pause for the little X there,
One toggle for clicks, one for the key,
Safer closes for you and me,
Hooray — cautious tabs! 🐰✨


Caution

Pre-merge checks failed

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

  • Ignore

❌ Failed checks (2 errors, 1 warning, 3 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Actor Isolation ❌ Error CloseTabWarningSettings enum lacks nonisolated marking while parallel types CloseTabConfirmationPolicy and CloseTabConfirmationTrigger receive it, introducing implicit MainActor isolation debt. Mark CloseTabWarningSettings as nonisolated: nonisolated enum CloseTabWarningSettings { ... } to match CloseTabConfirmationPolicy and satisfy Swift 6 actor isolation rules.
Cmux Full Internationalization ❌ Error Four new iOS string-catalog keys have 20 locales with only 2 real translations (en, ja); 18 are English copies, violating the "copied English translations" prohibition. Keep 2 locales (en, ja) matching existing warnBeforeClosingTab, or provide real translations for all 20 locales like warnBeforeQuit.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive The PR fully implements the primary objective from #4622: adds app.warnBeforeClosingTabXButton preference routing X-button closes through the existing confirmation dialog. However, the secondary objective (hiding/disabling the X button via app.hideTabCloseButton) is not implemented. The PR delivers the first requested feature (#4622) but omits the optional app.hideTabCloseButton capability. Clarify whether partial implementation is acceptable or if both features are required.
Out of Scope Changes check ❓ Inconclusive The PR includes changes to the macOS red window close button behavior in AppDelegate.swift, which extends beyond the stated #4622 objectives of adding X-button warning/hiding. This appears to be a related but separate enhancement. Confirm whether the red window close button changes are intentional scope additions or should be separated into a distinct PR for clarity.
Cmux Architecture Rethink ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (11 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Warn or disable X-button tab close (#4622)' directly reflects the main change: adding a warning option for tab X-button closes, matching the primary objective from issue #4622.
Cmux Swift Blocking Runtime ✅ Passed No new blocking operations introduced. PR adds trigger parameter, enum types, and settings logic only. Test drainMainQueue() is pre-existing test scaffolding (allowed).
Cmux No Hacky Sleeps ✅ Passed No hacky sleeps in production non-Swift code. Web setTimeout calls are presentation animations (allowed). Shell/Python sleeps are test scaffolding (allowed). Swift excluded per rule.
Cmux Swift Concurrency ✅ Passed PR adds X-button close warning using only synchronous value types (enums, method signatures, dictionary storage) with no new Task, DispatchQueue, Combine, or fire-and-forget async patterns.
Cmux Swift @Concurrent ✅ Passed New enums are synchronous. No @concurrent added, no nonisolated async functions introduced, no concurrent annotation rule violations detected.
Cmux Swift File And Package Boundaries ✅ Passed PR adds max 49 lines to any file (under 250-line threshold). New types follow established pattern in cmuxApp.swift. All changes are incidental touches to pre-existing oversized files.
Cmux Swift Logging ✅ Passed No new logging statements (print, debugPrint, dump, NSLog) were added to production Swift code in this PR. All changes focus on X-button close warning feature logic.
Cmux User-Facing Error Privacy ✅ Passed All user-facing strings are generic product terms. No error dialogs or sensitive implementation details exposed. Complies with privacy rules.
Cmux Swiftui State Layout ✅ Passed New @AppStorage for X-button warning follows existing SettingsView pattern; no new @Published/@observable state; internal Workspace/TabManager changes are non-SwiftUI or private fields.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR adds X-button tab close warning without creating new NSWindow/NSPanel/NSWindowController/SwiftUI Window/WindowGroup code; changes are parameter updates to existing main terminal windows.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering summary, preference keys, localization, migration strategy, and verification steps.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-4622-tab-x-button-warn

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.

Comment thread Sources/cmuxApp.swift Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@Resources/Localizable.xcstrings`:
- Around line 60964-61014: The new localization keys
settings.app.warnBeforeClosingTabXButton,
settings.app.warnBeforeClosingTabXButton.subtitleOff, and
settings.app.warnBeforeClosingTabXButton.subtitleOn only include "en" and "ja";
update each key to include an entry for every locale supported by this
Resources/*.xcstrings catalog (add the missing locale slots and supply
translated text or fallback English values), ensuring each locale has a
stringUnit/state and extractionState left as in other entries; apply the same
fix to the other new keys reported in the review (the other set of added keys
mentioned) so every new Swift localization key has entries for all catalog
locales.

In `@Sources/Workspace.swift`:
- Around line 9891-9892: The function markExplicitClose(surfaceId: TabID,
trigger: CloseTabConfirmationTrigger = .tabCloseButton) still has a default
parameter allowing callers to omit the trigger; remove the default so the
signature becomes markExplicitClose(surfaceId: TabID, trigger:
CloseTabConfirmationTrigger) and update all callsites to pass an explicit
CloseTabConfirmationTrigger value (e.g. .tabCloseButton, .keyboardShortcut,
.programmatic, etc.) to avoid silently routing non-X-button closes through the
X-button preference; search for markExplicitClose(...) usages and adjust each to
provide the correct CloseTabConfirmationTrigger.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2c3fbb80-5be4-4a5f-8072-ca80045ef641

📥 Commits

Reviewing files that changed from the base of the PR and between cd6688e and 2e71dd1.

📒 Files selected for processing (12)
  • Resources/Localizable.xcstrings
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Sources/CommandPalette/CommandPaletteSettingsToggle.swift
  • Sources/KeyboardShortcutSettingsFileStore+Template.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/SettingsNavigation.swift
  • Sources/SettingsSearchAliases.swift
  • Sources/TabManager.swift
  • Sources/Workspace.swift
  • Sources/cmuxApp.swift
  • cmuxTests/TabManagerUnitTests.swift
  • web/data/cmux.schema.json

Comment thread Resources/Localizable.xcstrings
Comment thread Sources/Workspace.swift Outdated
@greptile-apps

greptile-apps Bot commented May 23, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces app.warnBeforeClosingTabXButton (default true) to independently control whether the tab-strip X button shows a close confirmation, separate from the existing app.warnBeforeClosingTab shortcut preference. It threads a CloseTabConfirmationTrigger through TabManager and Workspace close paths and wires the setting end-to-end through Settings UI, Command Palette, cmux.json parsing/schema, and settings search.

  • The CloseTabConfirmationPolicy.decision split correctly routes .shortcut through requiresConfirmation + warnBeforeClosingTab and .tabCloseButton through warnBeforeClosingTabXButton.
  • Two issues need attention: (1) the sidebar tab middle-click at ContentView.swift:13902 still calls closeWorkspaceWithConfirmation, so warnBeforeClosingTabXButton has no effect for that gesture; (2) when warnBeforeClosingTabXButton is on and a user X-button-closes the only workspace in a window, they see two sequential dialogs because closeWorkspaceIfRunningProcess calls window.performClose(nil), retriggering the newly unconditional confirmCloseMainWindow in handleMainTerminalWindowShouldClose.

Confidence Score: 3/5

Not safe to merge as-is: the default-on setting causes a double confirmation dialog for single-workspace windows, and middle-click ignores the new warning entirely.

Two concrete defects affect the changed close paths. When warnBeforeClosingTabXButton is on (the default) and the user X-button-closes the only workspace in a window, the app shows Close workspace? and then immediately shows Close window? — a double prompt the unit tests miss because they run TabManager without a real NSWindow. The sidebar middle-click gesture still routes through closeWorkspaceWithConfirmation so the new setting has no effect on middle-click. Both defects are on the primary changed paths and the first will affect nearly every user on first launch.

Sources/AppDelegate.swift (handleMainTerminalWindowShouldClose interaction with closeWorkspaceIfRunningProcess) and Sources/ContentView.swift (middle-click call site at line 13902).

Important Files Changed

Filename Overview
Sources/cmuxApp.swift Introduces CloseTabConfirmationTrigger enum and splits CloseTabConfirmationPolicy.decision into shortcut vs. tabCloseButton branches; adds CloseTabWarningSettings helpers for the new key; wires up SettingsView toggle.
Sources/AppDelegate.swift handleMainTerminalWindowShouldClose now calls confirmCloseMainWindow for every main terminal window close (not just the last); adds a debug handler hook for testing window-close confirmation.
Sources/Workspace.swift Replaces explicitUserCloseTabIds Set with explicitUserCloseTabSources dictionary keyed by CloseTabConfirmationTrigger; propagates the trigger through bonsplit close callbacks and the workspace-close-on-last-surface path.
Sources/TabManager.swift closeWorkspaceFromCloseTabGesture gains a trigger parameter mapping to shortcutTabClose/tabCloseButton sources; all shouldConfirmClose callsites receive the correct trigger.
Sources/ContentView.swift Sidebar tab X-button close updated to closeWorkspaceFromCloseTabGesture with .tabCloseButton trigger; middle-click close at line 13902 still calls closeWorkspaceWithConfirmation, bypassing both warning settings.
cmuxTests/TabManagerUnitTests.swift Adds comprehensive unit tests for X-button confirmation behavior; adds withCloseTabWarningConfig helper; updates existing tests to supply the required trigger parameter.
cmuxTests/AppDelegateShortcutRoutingTests.swift Adds two integration tests for the red-window-close-button dialog path using the new debugCloseMainWindowConfirmationHandler hook.
Resources/Localizable.xcstrings Adds three new setting strings and one search alias with entries for all 19 supported locales; ja has actual translations, all other non-English locales carry English placeholder text.
web/data/cmux.schema.json Adds warnBeforeClosingTabXButton boolean schema entry with default true, matching the runtime default.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["User closes tab"] --> B{Gesture?}
    B -->|"Sidebar X-button"| C["closeWorkspaceFromCloseTabGesture\ntrigger: .tabCloseButton"]
    B -->|"Keyboard shortcut"| D["closeWorkspaceFromCloseTabGesture\ntrigger: .shortcut"]
    B -->|"Middle-click"| E["closeWorkspaceWithConfirmation\nsource: .workspace ignores settings"]
    B -->|"Red window button"| F["windowShouldClose\nhandleMainTerminalWindowShouldClose"]
    C --> G{tabCloseButton policy}
    G -->|"warnBeforeClosingTabXButton=true"| H["Close workspace? dialog"]
    G -->|"warnBeforeClosingTabXButton=false"| I["Close immediately"]
    D --> J{shortcutTabClose policy}
    J -->|"warnBeforeClosingTab=true AND requiresConfirmation=true"| K["Close workspace? dialog"]
    J -->|"else"| L["Close immediately"]
    H --> M{Last workspace in window?}
    K --> M
    I --> M
    L --> M
    M -->|"Yes"| N["window.performClose nil"]
    M -->|"No"| O["closeWorkspace done"]
    N --> F
    F --> P["confirmCloseMainWindow: Close window? dialog --- SECOND DIALOG on X-button path"]
Loading

Comments Outside Diff (1)

  1. Sources/ContentView.swift, line 13898-13903 (link)

    P1 Middle-click bypasses both close-warning settings

    The middle-click gesture at this call site still invokes closeWorkspaceWithConfirmation, which uses the .workspace source in shouldConfirmClose. That source returns requiresConfirmation directly (process-running state only) and ignores both app.warnBeforeClosingTab and app.warnBeforeClosingTabXButton. After this PR the sidebar tab X-button respects warnBeforeClosingTabXButton while middle-click — another direct mouse-based close gesture on the same element — silently bypasses it. Updating this call to closeWorkspaceFromCloseTabGesture(tab, trigger: .tabCloseButton) would make both mouse close gestures consistent.

Reviews (5): Last reviewed commit: "Warn on red window close button" | Re-trigger Greptile

Comment thread Sources/cmuxApp.swift
Comment thread web/data/cmux.schema.json
coderabbitai[bot]
coderabbitai Bot previously requested changes May 23, 2026

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/cmuxApp.swift (1)

4733-4745: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the X-button warning default independent from the shortcut setting.

Line 4733 makes the new X-button preference inherit the shortcut default, and Line 4744 falls back to isEnabled(...) when the X-button key is unset. That makes the new setting effectively on-by-default and tied to warnBeforeClosingTab, which contradicts the separate opt-in behavior described for app.warnBeforeClosingTabXButton. It also means Reset All Settings will not restore X-button close behavior independently.

🐛 Proposed fix
 enum CloseTabWarningSettings {
     static let warnBeforeClosingTabKey = "warnBeforeClosingTabShortcut"
     static let warnBeforeClosingTabXButtonKey = "warnBeforeClosingTabXButton"
     static let defaultWarnBeforeClosingTab = true
-    static let defaultWarnBeforeClosingTabXButton = defaultWarnBeforeClosingTab
+    static let defaultWarnBeforeClosingTabXButton = false
@@
     static func isXButtonWarningEnabled(defaults: UserDefaults = .standard) -> Bool {
         if defaults.object(forKey: warnBeforeClosingTabXButtonKey) == nil {
-            return isEnabled(defaults: defaults)
+            return defaultWarnBeforeClosingTabXButton
         }
         return defaults.bool(forKey: warnBeforeClosingTabXButtonKey)
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/cmuxApp.swift` around lines 4733 - 4745, The isXButtonWarningEnabled
method currently falls back to isEnabled(...) causing the X-button preference to
inherit warnBeforeClosingTab; change it to treat warnBeforeClosingTabXButtonKey
independently by returning defaultWarnBeforeClosingTabXButton when the X-button
key is unset instead of calling isEnabled(...). Update
isXButtonWarningEnabled(defaults:) to check defaults.object(forKey:
warnBeforeClosingTabXButtonKey) and return defaults.bool(forKey:
warnBeforeClosingTabXButtonKey) or defaultWarnBeforeClosingTabXButton, leaving
isEnabled(...) and defaultWarnBeforeClosingTab untouched.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/data/cmux.schema.json`:
- Around line 301-302: The schema entry currently sets "default": true which
contradicts the intended opt-in behavior; change the default to false (or remove
the "default" key) so the setting is not enabled by default, and keep the
description that unset values inherit app.warnBeforeClosingTab; update the
description text if needed to make explicit that users must opt in to enable the
X-button warning.

---

Outside diff comments:
In `@Sources/cmuxApp.swift`:
- Around line 4733-4745: The isXButtonWarningEnabled method currently falls back
to isEnabled(...) causing the X-button preference to inherit
warnBeforeClosingTab; change it to treat warnBeforeClosingTabXButtonKey
independently by returning defaultWarnBeforeClosingTabXButton when the X-button
key is unset instead of calling isEnabled(...). Update
isXButtonWarningEnabled(defaults:) to check defaults.object(forKey:
warnBeforeClosingTabXButtonKey) and return defaults.bool(forKey:
warnBeforeClosingTabXButtonKey) or defaultWarnBeforeClosingTabXButton, leaving
isEnabled(...) and defaultWarnBeforeClosingTab untouched.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c01d5df1-de9d-4686-a802-5e1698b126a4

📥 Commits

Reviewing files that changed from the base of the PR and between 2e71dd1 and 6f722a8.

📒 Files selected for processing (4)
  • Sources/CommandPalette/CommandPaletteSettingsToggle.swift
  • Sources/cmuxApp.swift
  • cmuxTests/TabManagerUnitTests.swift
  • web/data/cmux.schema.json

Comment thread web/data/cmux.schema.json Outdated
@austinywang
austinywang dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] May 23, 2026 04:03

Dismissed after requested changes were addressed in later commits; CodeRabbit current check is passing and review threads are resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/cmuxApp.swift (1)

4759-4795: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Add a dedicated non-user close trigger instead of defaulting to .shortcut.

Workspace.splitTabBar(...shouldCloseTab:) falls back to closeConfirmationTrigger = .shortcut when a close isn’t explicitly marked via markExplicitClose(..., trigger:). Any programmatic/internal close path that calls bonsplitController.closeTab(...) / tab.closePanel(...) without marking (e.g. closing the default “Welcome” tabs) will therefore use the shortcut warning preference instead of a distinct non-user policy. Add a new CloseTabConfirmationTrigger case for non-user/programmatic closes and route those close requests through it.

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

In `@Sources/cmuxApp.swift` around lines 4759 - 4795, Add a new
non-user/programmatic trigger to CloseTabConfirmationTrigger (e.g., case
nonUser) and wire it through the confirmation logic: update
CloseTabConfirmationPolicy.decision(...) to handle .nonUser explicitly (use the
appropriate warning setting check or a new CloseTabWarningSettings API for
non-user closes), change any fallback in
Workspace.splitTabBar(...shouldCloseTab:) so it no longer defaults to .shortcut
but uses .nonUser for unmarked programmatic closes, and ensure programmatic
close call sites (bonsplitController.closeTab(...), tab.closePanel(...), or
markExplicitClose(..., trigger:)) mark programmatic closes with .nonUser; also
update any tests or settings references accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Resources/Localizable.xcstrings`:
- Around line 60979-61085: The localized entries for the string value "Warn
Before X-Button Tab Close" are marked as "translated" but still contain English
for multiple non-exempt locales; update the locale-specific values for the
listed locale keys ("de", "es", "fr", "it", "ko", "nb", "pt-BR", "ru", "uk",
"zh-Hans", "zh-Hant") replacing the copied-English text with proper translations
(no placeholders, machine markers, TODOs or empty strings) so each locale's
"stringUnit"."value" contains the correct translation while keeping the "state"
as "translated".
- Around line 77747-77853: The localization entries for
settings.search.alias.setting.app.warn-before-closing-tab-x-button in
Resources/Localizable.xcstrings incorrectly duplicate the English token
"app.warnBeforeClosingTabXButton ..." across many locales; replace those cloned
English values with real localized search-alias tokens (or mark locale as
exempt) so each non-exempt locale has an actual translated alias value instead
of the English placeholder, updating the stringUnit.value for the locales (e.g.,
"de", "fr", "ko", "zh-Hans", etc.) accordingly and ensuring state remains
"translated" only when a proper localized token is provided.

---

Outside diff comments:
In `@Sources/cmuxApp.swift`:
- Around line 4759-4795: Add a new non-user/programmatic trigger to
CloseTabConfirmationTrigger (e.g., case nonUser) and wire it through the
confirmation logic: update CloseTabConfirmationPolicy.decision(...) to handle
.nonUser explicitly (use the appropriate warning setting check or a new
CloseTabWarningSettings API for non-user closes), change any fallback in
Workspace.splitTabBar(...shouldCloseTab:) so it no longer defaults to .shortcut
but uses .nonUser for unmarked programmatic closes, and ensure programmatic
close call sites (bonsplitController.closeTab(...), tab.closePanel(...), or
markExplicitClose(..., trigger:)) mark programmatic closes with .nonUser; also
update any tests or settings references accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1b3db8a4-3b0f-49f8-b1fb-a544564fa3c9

📥 Commits

Reviewing files that changed from the base of the PR and between 6f722a8 and 7d24cf9.

📒 Files selected for processing (7)
  • Resources/Localizable.xcstrings
  • Sources/TabManager.swift
  • Sources/Workspace.swift
  • Sources/WorkspaceCloseTabsBatching.swift
  • Sources/cmuxApp.swift
  • cmuxTests/TabManagerUnitTests.swift
  • web/data/cmux.schema.json

Comment on lines +60979 to +61085
"ar": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"km": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "Warn Before X-Button Tab Close"
}

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 | 🏗️ Heavy lift

Replace copied-English locale values with real translations for non-exempt locales.

These three new user-facing keys are marked "translated" but still use English copy for locales beyond the repo’s known fallback-exempt set. Please provide locale-specific translations (at least for de, es, fr, it, ko, nb, pt-BR, ru, uk, zh-Hans, zh-Hant) instead of duplicated English values.

As per coding guidelines: Placeholder, copied English, machine marker, TODO, or empty translations must not be used to satisfy a locale slot in **/Resources/*.xcstrings. Based on learnings: fallback-English is intentionally accepted only for ar, bs, da, pl, th, km, tr.

Also applies to: 61104-61210, 61229-61335

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

In `@Resources/Localizable.xcstrings` around lines 60979 - 61085, The localized
entries for the string value "Warn Before X-Button Tab Close" are marked as
"translated" but still contain English for multiple non-exempt locales; update
the locale-specific values for the listed locale keys ("de", "es", "fr", "it",
"ko", "nb", "pt-BR", "ru", "uk", "zh-Hans", "zh-Hant") replacing the
copied-English text with proper translations (no placeholders, machine markers,
TODOs or empty strings) so each locale's "stringUnit"."value" contains the
correct translation while keeping the "state" as "translated".

Comment on lines +77747 to +77853
"ar": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"km": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "app.warnBeforeClosingTabXButton close tab confirmation x button mouse click tab strip terminal surface"
}

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 | 🏗️ Heavy lift

Localize the search-alias tokens per locale instead of cloning English text.

settings.search.alias.setting.app.warn-before-closing-tab-x-button currently fills most locale slots with identical English tokens. For non-exempt locales, this does not satisfy full i18n requirements for catalog entries marked translated.

As per coding guidelines: for Resources/*.xcstrings, copied English cannot be used as locale-fill translation.

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

In `@Resources/Localizable.xcstrings` around lines 77747 - 77853, The localization
entries for settings.search.alias.setting.app.warn-before-closing-tab-x-button
in Resources/Localizable.xcstrings incorrectly duplicate the English token
"app.warnBeforeClosingTabXButton ..." across many locales; replace those cloned
English values with real localized search-alias tokens (or mark locale as
exempt) so each non-exempt locale has an actual translated alias value instead
of the English placeholder, updating the stringUnit.value for the locales (e.g.,
"de", "fr", "ko", "zh-Hans", etc.) accordingly and ensuring state remains
"translated" only when a proper localized token is provided.

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 57b81f7. Configure here.

Comment thread Sources/TabManager.swift
case .shortcutTabClose:
return CloseTabConfirmationPolicy.shouldConfirm(requiresConfirmation: requiresConfirmation, trigger: .shortcut)
case .tabCloseButton:
return CloseTabConfirmationPolicy.shouldConfirm(requiresConfirmation: requiresConfirmation, trigger: .tabCloseButton)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pinned workspace skips confirmation

Medium Severity

Closing a pinned workspace from the sidebar X now uses the tab-close-button confirmation source. When app.warnBeforeClosingTabXButton is off, confirmPinnedWorkspaceClose treats that as “no confirmation needed” and closes immediately, unlike the previous closeWorkspaceWithConfirmation path that always showed the pinned-workspace dialog.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 57b81f7. Configure here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@web/data/cmux.schema.json`:
- Around line 299-302: Update the JSON schema description for the boolean
property warnBeforeClosingTabXButton to explicitly state the semantics for true
and false; change the description to something like: "When true, show a
close-tab confirmation before a tab-strip X button closes a tab; when false, do
not show the confirmation." Ensure this exact property name
(warnBeforeClosingTabXButton) is updated so consumers understand the boolean
conditions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 71d9833a-9ca8-4ca4-bed4-473ee02486da

📥 Commits

Reviewing files that changed from the base of the PR and between 7d24cf9 and ea17629.

📒 Files selected for processing (4)
  • Sources/ContentView.swift
  • Sources/cmuxApp.swift
  • cmuxTests/TabManagerUnitTests.swift
  • web/data/cmux.schema.json

Comment thread web/data/cmux.schema.json
Comment on lines +299 to +302
"warnBeforeClosingTabXButton": {
"type": "boolean",
"default": true,
"description": "Always show the close-tab confirmation before a tab-strip X button closes a tab."

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 | ⚡ Quick win

Clarify boolean semantics in the schema description.

The phrase “Always show…” reads as unconditional behavior. For a boolean setting, describe the true condition explicitly (for example, “When true, show…”), so users don’t interpret this as non-configurable behavior.

Suggested edit
         "warnBeforeClosingTabXButton": {
           "type": "boolean",
           "default": true,
-          "description": "Always show the close-tab confirmation before a tab-strip X button closes a tab."
+          "description": "When true, show the close-tab confirmation before a tab-strip X button closes a tab."
         },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/data/cmux.schema.json` around lines 299 - 302, Update the JSON schema
description for the boolean property warnBeforeClosingTabXButton to explicitly
state the semantics for true and false; change the description to something
like: "When true, show a close-tab confirmation before a tab-strip X button
closes a tab; when false, do not show the confirmation." Ensure this exact
property name (warnBeforeClosingTabXButton) is updated so consumers understand
the boolean conditions.

This branch was successfully deployed

1 active deployment
Preview – cmux — 57b81f73 Deployed May 23, 2026 by vercel[bot]
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.

Warn (or disable) X-button tab close — currently only Cmd+W is gated by warnBeforeClosingTab

1 participant