From e9afc22353128d7c9fa273d8432cbf2fe0e36157 Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Sat, 28 Mar 2026 03:57:25 -0700 Subject: [PATCH] Skip quit confirmation for tagged DEV builds (#2288) * Skip quit confirmation for tagged DEV builds Tagged DEV builds are ephemeral dev iterations, so the "Quit cmux?" dialog just adds friction. Check SocketControlSettings.launchTag() in both applicationShouldTerminate and handleQuitShortcutWarning to bypass the confirmation when a tag is present. Closes https://github.com/manaflow-ai/cmux/issues/2286 * Use bundle ID instead of env var for tagged DEV detection CMUX_TAG env var is only set when reload.sh --launch opens the app. When the user cmd-clicks the app path, it launches via Finder without the env var, so launchTag() returns nil and the quit dialog still shows. Switch to checking the bundle identifier (com.cmuxterm.app.debug.) which is baked into the built app and available regardless of how it was launched. Add SocketControlSettings.isTaggedDevBuild() helper. --------- Co-authored-by: Lawrence Chen --- Sources/AppDelegate.swift | 11 +++++++++++ Sources/SocketControlSettings.swift | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index cd623863..f1769ec7 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -2705,6 +2705,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent isTerminatingApp = true _ = saveSessionSnapshot(includeScrollback: true, removeWhenEmpty: false) + // Tagged DEV builds are ephemeral, skip quit confirmation entirely. + if SocketControlSettings.isTaggedDevBuild() { + return .terminateNow + } + // If the user already confirmed via the Cmd+Q shortcut warning dialog // (handleQuitShortcutWarning), skip the check to avoid a second alert. if isQuitWarningConfirmed { @@ -9005,6 +9010,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } private func handleQuitShortcutWarning() -> Bool { + // Tagged DEV builds are ephemeral, skip quit confirmation entirely. + if SocketControlSettings.isTaggedDevBuild() { + NSApp.terminate(nil) + return true + } + if !QuitWarningSettings.isEnabled() { NSApp.terminate(nil) return true diff --git a/Sources/SocketControlSettings.swift b/Sources/SocketControlSettings.swift index 8d44e573..9524cf51 100644 --- a/Sources/SocketControlSettings.swift +++ b/Sources/SocketControlSettings.swift @@ -533,6 +533,12 @@ struct SocketControlSettings { || bundleIdentifier.hasPrefix("com.cmuxterm.app.debug.") } + /// Tagged DEV builds have bundle IDs like `com.cmuxterm.app.debug.`. + static func isTaggedDevBuild(bundleIdentifier: String? = Bundle.main.bundleIdentifier) -> Bool { + guard let bundleIdentifier else { return false } + return bundleIdentifier.hasPrefix("\(baseDebugBundleIdentifier).") + } + static func taggedDebugSocketPath( bundleIdentifier: String?, environment: [String: String]