From eb6caa5ce5e61c55700e5e89e4bfa2162396e9d6 Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:10:48 -0800 Subject: [PATCH] Default Claude Code integration to off --- Sources/GhosttyTerminalView.swift | 2 +- Sources/cmuxApp.swift | 17 ++++++++++++++-- cmuxTests/GhosttyConfigTests.swift | 31 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index 7bc8194f..600d3237 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -1354,7 +1354,7 @@ final class TerminalSurface: Identifiable, ObservableObject { env["CMUX_PORT_RANGE"] = String(Self.sessionPortRangeSize) } - let claudeHooksEnabled = UserDefaults.standard.object(forKey: "claudeCodeHooksEnabled") as? Bool ?? true + let claudeHooksEnabled = ClaudeCodeIntegrationSettings.hooksEnabled() if !claudeHooksEnabled { env["CMUX_CLAUDE_HOOKS_DISABLED"] = "1" } diff --git a/Sources/cmuxApp.swift b/Sources/cmuxApp.swift index 3a2e5264..f4d308ae 100644 --- a/Sources/cmuxApp.swift +++ b/Sources/cmuxApp.swift @@ -2263,13 +2263,26 @@ enum AppearanceSettings { } } +enum ClaudeCodeIntegrationSettings { + static let hooksEnabledKey = "claudeCodeHooksEnabled" + static let defaultHooksEnabled = false + + static func hooksEnabled(defaults: UserDefaults = .standard) -> Bool { + if defaults.object(forKey: hooksEnabledKey) == nil { + return defaultHooksEnabled + } + return defaults.bool(forKey: hooksEnabledKey) + } +} + struct SettingsView: View { private let contentTopInset: CGFloat = 8 private let pickerColumnWidth: CGFloat = 196 @AppStorage(AppearanceSettings.appearanceModeKey) private var appearanceMode = AppearanceSettings.defaultMode.rawValue @AppStorage(SocketControlSettings.appStorageKey) private var socketControlMode = SocketControlSettings.defaultMode.rawValue - @AppStorage("claudeCodeHooksEnabled") private var claudeCodeHooksEnabled = true + @AppStorage(ClaudeCodeIntegrationSettings.hooksEnabledKey) + private var claudeCodeHooksEnabled = ClaudeCodeIntegrationSettings.defaultHooksEnabled @AppStorage("cmuxPortBase") private var cmuxPortBase = 9100 @AppStorage("cmuxPortRange") private var cmuxPortRange = 10 @AppStorage(BrowserSearchSettings.searchEngineKey) private var browserSearchEngine = BrowserSearchSettings.defaultSearchEngine.rawValue @@ -2595,7 +2608,7 @@ struct SettingsView: View { private func resetAllSettings() { appearanceMode = AppearanceSettings.defaultMode.rawValue socketControlMode = SocketControlSettings.defaultMode.rawValue - claudeCodeHooksEnabled = true + claudeCodeHooksEnabled = ClaudeCodeIntegrationSettings.defaultHooksEnabled browserSearchEngine = BrowserSearchSettings.defaultSearchEngine.rawValue browserSearchSuggestionsEnabled = BrowserSearchSettings.defaultSearchSuggestionsEnabled openTerminalLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenTerminalLinksInCmuxBrowser diff --git a/cmuxTests/GhosttyConfigTests.swift b/cmuxTests/GhosttyConfigTests.swift index dddecf16..856407ba 100644 --- a/cmuxTests/GhosttyConfigTests.swift +++ b/cmuxTests/GhosttyConfigTests.swift @@ -162,6 +162,37 @@ final class GhosttyConfigTests: XCTestCase { ) } + func testClaudeCodeIntegrationDefaultsToDisabledWhenUnset() { + let suiteName = "cmux.tests.claude-hooks.\(UUID().uuidString)" + guard let defaults = UserDefaults(suiteName: suiteName) else { + XCTFail("Failed to create isolated user defaults suite") + return + } + defer { + defaults.removePersistentDomain(forName: suiteName) + } + + defaults.removeObject(forKey: ClaudeCodeIntegrationSettings.hooksEnabledKey) + XCTAssertFalse(ClaudeCodeIntegrationSettings.hooksEnabled(defaults: defaults)) + } + + func testClaudeCodeIntegrationRespectsStoredPreference() { + let suiteName = "cmux.tests.claude-hooks.\(UUID().uuidString)" + guard let defaults = UserDefaults(suiteName: suiteName) else { + XCTFail("Failed to create isolated user defaults suite") + return + } + defer { + defaults.removePersistentDomain(forName: suiteName) + } + + defaults.set(true, forKey: ClaudeCodeIntegrationSettings.hooksEnabledKey) + XCTAssertTrue(ClaudeCodeIntegrationSettings.hooksEnabled(defaults: defaults)) + + defaults.set(false, forKey: ClaudeCodeIntegrationSettings.hooksEnabledKey) + XCTAssertFalse(ClaudeCodeIntegrationSettings.hooksEnabled(defaults: defaults)) + } + private func rgb255(_ color: NSColor) -> RGB { let srgb = color.usingColorSpace(.sRGB)! var red: CGFloat = 0