Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8780f34
Show one dialog when a confirmed close ends the last window
teamleaderleo Sep 27, 2026
6b350b1
Open the agent's pane when a Feed notification banner is clicked
teamleaderleo Sep 27, 2026
8dd2fcc
Guard factory shortcut defaults against same-context collisions
teamleaderleo Sep 27, 2026
c7005ba
Add changelog entry for #14960
teamleaderleo Sep 27, 2026
617be4a
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
7ae89a2
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
b7f383f
Merge branch 'main' of https://github.com/manaflow-ai/cmux into one-d…
teamleaderleo Sep 27, 2026
a0a1d76
Add warnBeforeClosingWorkspace setting
teamleaderleo Sep 27, 2026
f4c328f
Add changelog entry for #14979
teamleaderleo Sep 27, 2026
305d831
Merge one-dialog-per-close into workspace-close-warning
teamleaderleo Sep 27, 2026
abf88ca
Keep the pinned gate for batch closes that include a pinned workspace
teamleaderleo Sep 27, 2026
4158898
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
99a44c7
Move the release note into the PR description
teamleaderleo Sep 27, 2026
726c318
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
4e8ab67
Merge main (f5c179fb9427) into one-dialog-per-close
teamleaderleo Sep 27, 2026
3e00d5c
Merge one-dialog-per-close into workspace-close-warning
teamleaderleo Sep 27, 2026
a6584ab
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
a9f7867
Merge branch 'one-dialog-per-close' of github.com:manaflow-ai/cmux in…
teamleaderleo Sep 27, 2026
09542e7
Merge remote-tracking branch 'mf/main' into one-dialog-per-close
teamleaderleo Sep 27, 2026
ea886a1
Merge one-dialog-per-close into workspace-close-warning
teamleaderleo Sep 27, 2026
b7874ff
Merge main into workspace-close-warning
teamleaderleo Sep 27, 2026
58eb74b
Merge main into workspace-close-warning
teamleaderleo Sep 27, 2026
01c2bb7
Restore main's Localizable.xcstrings order
teamleaderleo Sep 27, 2026
7045691
Merge main into workspace-close-warning
teamleaderleo Sep 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ All notable changes to cmux are documented here.
- iOS (beta): Settings > About has a Support Information action that copies your account, install, and device IDs plus app version for support requests ([#13448](https://github.com/manaflow-ai/cmux/pull/13448)) -- thanks @azooz2003-bit!
- iOS (beta): Version 1.0.6 shows a one-time notice with the minimum Mac versions it needs, then opens the Mac pairing guide ([#14112](https://github.com/manaflow-ai/cmux/pull/14112)) -- thanks @azooz2003-bit!
- iOS (beta): Settings > Reset > Erase All Data on This Device signs out and returns the app to a fresh-install state ([#14140](https://github.com/manaflow-ai/cmux/pull/14140))
- Settings > App > Warn Before Closing Workspace (`app.warnBeforeClosingWorkspace`, on by default) turns off the "Close workspace?" prompts; pinned workspaces still ask ([#14979](https://github.com/manaflow-ai/cmux/pull/14979))

### Changed
- Each Settings toggle and picker row shows one fixed subtitle instead of text that changes with the selected value, and localized Settings titles and Feed, Dock, and Cloud Machines labels use corrected wording ([#14883](https://github.com/manaflow-ai/cmux/pull/14883)) -- thanks @agoodkind!
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,29 @@ public struct AppCatalogSection: SettingCatalogSection {
)
)

/// Gates the "Close workspace?" prompts (running processes, multi-workspace
/// close). The "Close pinned workspace?" prompt is not gated by it.
public let warnBeforeClosingWorkspace = DefaultsKey<Bool>(
id: "app.warnBeforeClosingWorkspace",
defaultValue: true,
userDefaultsKey: "warnBeforeClosingWorkspace",
userFacing: UserFacingSettingDescriptor(
title: String(
localized: "settings.app.warnBeforeClosingWorkspace",
defaultValue: "Warn Before Closing Workspace"
),
section: .app,
searchID: "warn-before-closing-workspace",
searchKeywords: ["close", "workspace", "confirmation", "command-shift-w", "cmd-shift-w", "agent", "running"],
control: .toggle(.init(
commandPalette: .init(
id: "warnBeforeClosingWorkspace",
keywords: ["warn", "close", "workspace", "confirmation", "cmd-shift-w"]
)
))
)
)

public let warnBeforeClosingTabXButton = DefaultsKey<Bool>(
id: "app.warnBeforeClosingTabXButton",
defaultValue: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ struct DefaultsKeyDirectAccessTests {
#expect(key.value(in: defaults) == true)
}

@Test func warnBeforeClosingWorkspaceDefaultsToEnabled() {
let defaults = makeScratchDefaults()
let key = AppCatalogSection().warnBeforeClosingWorkspace
#expect(key.id == "app.warnBeforeClosingWorkspace")
#expect(key.value(in: defaults) == true)

defaults.set(false, forKey: "warnBeforeClosingWorkspace")
#expect(key.value(in: defaults) == false)
}

@Test func undecodableStoredValueReadsAsDefault() {
let defaults = makeScratchDefaults()
let key = AppCatalogSection().confirmQuitMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct UserFacingSettingDescriptorTests {
let catalog = SettingCatalog()
let keys = [
catalog.app.warnBeforeClosingTab,
catalog.app.warnBeforeClosingWorkspace,
catalog.app.hideTabCloseButton,
catalog.app.renameSelectsExistingName,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ extension Array where Element == CuratedSettingEntry {
.init(section: .app, id: "warn-before-quit", title: String(localized: "settings.app.warnBeforeQuit", defaultValue: "Warn Before Quit"), synonyms: "Warn Before Quit app.confirmQuit quit confirmation command-q cmd-q exit close app"),
.init(userFacing: catalog.app.warnBeforeClosingTab),
.init(section: .app, id: "warn-before-closing-tab-x-button", title: String(localized: "settings.app.warnBeforeClosingTabXButton", defaultValue: "Warn Before Tab Close Button"), synonyms: "Warn Before Tab Close Button app.warnBeforeClosingTabXButton x button close tab confirmation terminal surface"),
.init(userFacing: catalog.app.warnBeforeClosingWorkspace),
.init(userFacing: catalog.app.hideTabCloseButton),
.init(userFacing: catalog.app.renameSelectsExistingName),
.init(section: .app, id: "palette-search-all", title: String(localized: "settings.app.commandPaletteSearchAllSurfaces", defaultValue: "Command Palette Searches All Surfaces"), synonyms: "Command Palette Searches All Surfaces app.commandPaletteSearchesAllSurfaces command palette search all surfaces cmd-p terminal browser markdown"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public struct AppSection: View {
@State private var confirmQuit: DefaultsValueModel<ConfirmQuitMode>
@State private var warnCloseTab: DefaultsValueModel<Bool>
@State private var warnCloseX: DefaultsValueModel<Bool>
@State private var warnCloseWorkspace: DefaultsValueModel<Bool>
@State private var hideCloseButton: DefaultsValueModel<Bool>
@State private var renameSelects: DefaultsValueModel<Bool>
@State private var paletteAllSurfaces: DefaultsValueModel<Bool>
Expand Down Expand Up @@ -138,6 +139,7 @@ public struct AppSection: View {
_confirmQuit = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.confirmQuitMode))
_warnCloseTab = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.warnBeforeClosingTab))
_warnCloseX = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.warnBeforeClosingTabXButton))
_warnCloseWorkspace = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.warnBeforeClosingWorkspace))
_hideCloseButton = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.hideTabCloseButton))
_renameSelects = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.renameSelectsExistingName))
_paletteAllSurfaces = State(initialValue: DefaultsValueModel(store: defaultsStore, key: catalog.app.commandPaletteSearchesAllSurfaces))
Expand All @@ -163,7 +165,7 @@ public struct AppSection: View {
AppChannelSwitchCard(hostActions: hostActions)
}
.task {
startSettingsObservation([language, appearance, appIcon, placement, inheritDir, minimalMode, keepWorkspaceOpen, firstClick, focusHistoryIncludesPanesAndTabs, equalizeSplitsOnCreate, fileDrop, preferredEditor, openSupported, openMarkdown, globalFontMagnification, markdownFontSize, markdownFontFamily, markdownMaxWidth, canvasPaneGap, canvasSnapping, fileEditorWordWrap, fileEditorSyntaxHighlighting, fileEditorLineNumbers, fileEditorIndentGuides, fileEditorCurrentLineHighlight, fileEditorTabWidth, iMessage, reorder, dockBadge, menuBarOnly, showInMenuBar, paneRing, paneFlash, desktopNotifications, agentPermissionPrompt, agentTurnComplete, agentIdleReminder, soundName, soundCommand, customSoundFile, soundOverrides, telemetry, confirmQuit, warnCloseTab, warnCloseX, hideCloseButton, renameSelects, paletteAllSurfaces])
startSettingsObservation([language, appearance, appIcon, placement, inheritDir, minimalMode, keepWorkspaceOpen, firstClick, focusHistoryIncludesPanesAndTabs, equalizeSplitsOnCreate, fileDrop, preferredEditor, openSupported, openMarkdown, globalFontMagnification, markdownFontSize, markdownFontFamily, markdownMaxWidth, canvasPaneGap, canvasSnapping, fileEditorWordWrap, fileEditorSyntaxHighlighting, fileEditorLineNumbers, fileEditorIndentGuides, fileEditorCurrentLineHighlight, fileEditorTabWidth, iMessage, reorder, dockBadge, menuBarOnly, showInMenuBar, paneRing, paneFlash, desktopNotifications, agentPermissionPrompt, agentTurnComplete, agentIdleReminder, soundName, soundCommand, customSoundFile, soundOverrides, telemetry, confirmQuit, warnCloseTab, warnCloseX, warnCloseWorkspace, hideCloseButton, renameSelects, paletteAllSurfaces])
await soundAgentCache.loadIfNeeded { await hostActions.notificationSoundAgentOptions() }
if languageAtAppear == nil { languageAtAppear = language.current }; if telemetryAtAppear == nil { telemetryAtAppear = telemetry.current }
}
Expand Down Expand Up @@ -872,6 +874,20 @@ public struct AppSection: View {
}
SettingsCardDivider()

// Warn Before Closing Workspace
SettingsCardRow(
configurationReview: .json(catalog.app.warnBeforeClosingWorkspace.id),
catalog.app.warnBeforeClosingWorkspace.userFacing!.title,
subtitle: warnCloseWorkspace.current
? String(localized: "settings.app.warnBeforeClosingWorkspace.subtitleOn", defaultValue: "Show a confirmation before closing a workspace with a running process, or several workspaces at once.")
: String(localized: "settings.app.warnBeforeClosingWorkspace.subtitleOff", defaultValue: "Workspaces close immediately without confirmation. Pinned workspaces still ask.")
) {
Toggle("", isOn: Binding(get: { warnCloseWorkspace.current }, set: { warnCloseWorkspace.set($0) }))
.labelsHidden()
.controlSize(.small)
}
SettingsCardDivider()

// Hide Tab Close Button
SettingsCardRow(
configurationReview: .json(catalog.app.hideTabCloseButton.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct SettingsRowAnchorResolutionTests {
"app.sendAnonymousTelemetry",
"app.warnBeforeClosingTab",
"app.warnBeforeClosingTabXButton",
"app.warnBeforeClosingWorkspace",
"app.workspaceInheritWorkingDirectory",
"automation.claudeBinaryPath",
"automation.claudeCodeIntegration",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct SettingsSearchIndexTests {
let index = SettingsSearchIndex(catalog: catalog)
let keys = [
catalog.app.warnBeforeClosingTab,
catalog.app.warnBeforeClosingWorkspace,
catalog.app.hideTabCloseButton,
catalog.app.renameSelectsExistingName,
]
Expand Down
Loading
Loading