Skip to content

Extract browser-search settings into CmuxSettings (Wave-2 store, no namespace enum) - #6143

Merged
azooz2003-bit merged 3 commits into
mainfrom
feat-browsersearch-settings
Jun 15, 2026
Merged

azooz2003-bit merged 3 commits into
mainfrom
feat-browsersearch-settings

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jun 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Extracts the browser-search settings domain from Sources/Panels/BrowserPanel.swift into Packages/CmuxSettings using the Wave-2 settings-store shape:

  • BrowserSearchEngine now lives in CmuxSettings with the same cases, display names, built-in templates, remote-suggestion support, and search URL rendering behavior.
  • BrowserSearchConfiguration now lives in CmuxSettings as its own value type.
  • Replaces the app-target caseless namespace enum with BrowserSearchSettingsReading and BrowserSearchSettingsStore, with constructor-injected UserDefaults and instance methods for reads, configuration construction, URL-template validation/rendering, and custom-name normalization.
  • Updates app and test call sites to use BrowserSearchSettingsStore constants or constructed stores.
  • Adds package-level Swift Testing coverage for configuration factory output, URL-template validation/rendering, and custom-engine normalization with injected in-memory UserDefaults suites.

Defaults / wire format

Defaults key strings are preserved byte-identically:

  • browserSearchEngine
  • browserCustomSearchEngineName
  • browserCustomSearchEngineURLTemplate
  • browserSearchSuggestionsEnabled

Legacy default values are preserved in BrowserSearchSettingsStore:

  • default engine: google
  • default custom name: empty string
  • default custom URL template: https://www.google.com/search?q={query}
  • default search suggestions enabled: true

Destination decision

Destination is CmuxSettings because this code owns settings keys/defaults, defaults-backed reads, and settings-file validation behavior. That matches the prior Wave-2 settings cutover. If owners prefer a future browser-domain package for runtime-only search behavior, this PR keeps the settings storage seam isolated enough to split later without changing the persisted wire format.

BrowserPanel.swift reduction

BrowserPanel.swift budget was ratcheted from 13,595 to 13,358 lines: net -237 lines. The commit diff for that file is 6 additions and 243 deletions.

Validation

  • scripts/lint-ios-package-conventions.sh -> OK, no new lint:allow suppressions.
  • swift build in Packages/CmuxSettings -> passed.
  • swift test in Packages/CmuxSettings -> passed, 133 tests total including 4 new BrowserSearchSettingsStore tests.
  • xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/cmux-browsersearch build -> ** BUILD SUCCEEDED **.
  • xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/cmux-browsersearch-unit build -> ** BUILD SUCCEEDED **.
  • python3 scripts/swift_file_length_budget.py -> budget respected.
  • Localization audit: moved search-engine display strings reuse the existing 17 settings.browser.searchEngine.* keys; verified each has en and ja entries in Resources/Localizable.xcstrings.

Do not merge; leaving this for owner review.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Extracted browser-search settings into CmuxSettings with a Wave-2 store and protocol, preserving behavior, keys, and defaults. This isolates persistence and URL rendering, reduces BrowserPanel.swift by 237 lines, and improves testability.

  • Refactors

    • Moved BrowserSearchEngine and BrowserSearchConfiguration to CmuxSettings; same cases, display names, templates, suggestion support, and URL rendering; BrowserSearchEngine is now Identifiable.
    • Added BrowserSearchSettingsReading and BrowserSearchSettingsStore (injected UserDefaults) with current engine/config/suggestions and helpers for config factory, template validation/rendering, and custom-name normalization.
    • Updated app/tests to use BrowserSearchSettingsStore constants/APIs across BrowserPanel, BrowserPanelView, TerminalController, command-palette toggles, settings-file import, and catalog defaults.
    • Fixed test imports by pinning BrowserSearchEngine to CmuxSettings; added Swift tests in CmuxSettings for config factory, template validation/rendering, and normalization.
  • Migration

    • No changes required; existing preferences continue to work.
    • For new code, import CmuxSettings, depend on BrowserSearchSettingsReading, and replace BrowserSearchSettings.* calls with BrowserSearchSettingsStore.

Written for commit a4970eb. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Refactor
    • Centralized browser search settings handling, ensuring consistent defaults, custom search engine naming, and custom URL-template behavior across the app.
    • Browser smart navigation and URL/search fallbacks now use the same resolved search configuration.
    • Updated command palette and keyboard shortcut settings templates to use the unified search-suggestions default.
  • Bug Fixes
    • Improved validation for custom search URL templates (scheme/host checks) and correct query encoding/substitution.
  • Tests
    • Expanded/updated coverage for settings resolution, template validation, and fallback behavior.

@vercel

vercel Bot commented Jun 15, 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 Jun 15, 2026 2:00am
cmux-staging Building Building Preview, Comment Jun 15, 2026 2:00am

@coderabbitai

coderabbitai Bot commented Jun 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Moves browser search settings types (BrowserSearchEngine, BrowserSearchConfiguration, BrowserSearchSettings) out of BrowserPanel.swift into the CmuxSettings package as new public types with a BrowserSearchSettingsReading protocol and BrowserSearchSettingsStore struct. All app call sites and tests are migrated to the new package APIs.

Changes

Browser Search Settings Extraction into CmuxSettings

Layer / File(s) Summary
BrowserSearchEngine and BrowserSearchConfiguration value types
Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchEngine.swift, Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchConfiguration.swift
BrowserSearchEngine gains Identifiable conformance and new computed properties (id, displayName, searchURLTemplate, supportsRemoteSuggestions, searchURL). BrowserSearchConfiguration is introduced as a new public Equatable/Sendable struct with displayName, remoteSuggestionsEngine, and searchURL(query:).
BrowserSearchSettingsReading protocol and BrowserSearchSettingsStore implementation
Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsReading.swift, Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsStore.swift
Introduces the BrowserSearchSettingsReading protocol and implements it in BrowserSearchSettingsStore: a stateless Sendable struct with static key/default constants, UserDefaults-backed computed properties, URL template {query}/%s placeholder substitution, percent-encoding, and http/https host validation.
Remove local types from BrowserPanel and migrate all app call sites
Sources/Panels/BrowserPanel.swift, Sources/Panels/BrowserPanelView.swift, Sources/TerminalController.swift, Sources/KeyboardShortcutSettingsFileStore.swift, Sources/KeyboardShortcutSettingsFileStore+Template.swift, Sources/CommandPalette/CommandPaletteSettingsToggle.swift, Packages/CmuxSettings/Sources/CmuxSettings/Keys/BrowserCatalogSection.swift
Removes the 243-line local search settings implementation from BrowserPanel.swift, adds import CmuxSettings where needed, and migrates normalizeBrowserDefaults, navigateSmart, @AppStorage bindings, searchConfiguration, searchSuggestionsEnabled, parseBrowserSection, the settings template, the command palette toggle, the TerminalController search fallback, and BrowserCatalogSection keys to BrowserSearchSettingsStore APIs.
New store tests and migrated app tests
Packages/CmuxSettings/Tests/CmuxSettingsTests/BrowserSearchSettingsStoreTests.swift, cmuxTests/BrowserConfigTests.swift, cmuxTests/GhosttyConfigTests.swift, cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift
Adds BrowserSearchSettingsStoreTests covering custom engine configuration, invalid-template fallback, URL rendering/encoding, and name normalization. Migrates existing app tests from BrowserSearchSettings to BrowserSearchSettingsStore APIs and adds typealias disambiguation for ambiguous legacy types.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • manaflow-ai/cmux#4849: Directly related — introduced configurable search providers and custom URL template support using the same UserDefaults keys and URL template resolution behavior that this PR now centralizes in BrowserSearchSettingsStore.

Suggested reviewers

  • lawrencecchen

Poem

🐇 Hop hop, the settings roam no more in panel's den,
A package now holds the keys — clean and true!
{query} substituted, encoded just right,
BrowserSearchSettingsStore shines bright as dew.
The rabbit rejoices: one source of truth tonight! 🌙

🚥 Pre-merge checks | ✅ 20 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (20 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: extracting browser-search settings into CmuxSettings using a Wave-2 store pattern without a namespace enum.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed PR introduces no Swift 6 actor isolation violations. BrowserSearchEngine and BrowserSearchConfiguration are Sendable value types without @MainActor (correct). BrowserSearchSettingsStore uses noniso...
Cmux Swift Blocking Runtime ✅ Passed PR introduces no blocking/timing synchronization. New BrowserSearchSettingsStore is stateless Sendable struct using thread-safe UserDefaults. All modifications are pure synchronous code; pre-existi...
Cmux Expensive Synchronous Load ✅ Passed BrowserSearchSettingsStore performs lightweight UserDefaults reads and string/URL validation, not expensive synchronous disk/syscall loads like the canonical rule example (RestorableAgentSessionInd...
Cmux Cache Substitution Correctness ✅ Passed BrowserSearchSettingsStore is a stateless struct with fresh UserDefaults reads on each computed property access, used only for transient operations (navigation, file validation), never stored acros...
Cmux No Hacky Sleeps ✅ Passed Check not applicable: PR contains only Swift files. The "cmux no hacky sleeps" rule explicitly covers TypeScript, JavaScript, shell, and non-Swift build/runtime scripts; Swift is handled by separat...
Cmux Algorithmic Complexity ✅ Passed No algorithmic complexity violations: no nested collection scans, per-item rescans, or full-collection operations; string operations on fixed-size inputs (URLs, queries) called once per user action...
Cmux Swift Concurrency ✅ Passed PR extracts browser-search settings to CmuxSettings with synchronous, Sendable types (protocol, struct, enums) and synchronous validation methods; no Dispatch, Combine, completion handlers, or fire...
Cmux Swift @Concurrent ✅ Passed PR adds only synchronous code (BrowserSearchSettingsStore, BrowserSearchSettingsReading, etc.) with no async functions, @concurrent annotations, or concurrency violations. All usage patterns are ap...
Cmux Swift File And Package Boundaries ✅ Passed PR extracts browser-search settings to CmuxSettings package following proper boundaries: all new files are well under 400 lines (50–158 lines each); BrowserPanel.swift reduced by 237 lines; oversiz...
Cmux Swift Logging ✅ Passed PR adds no logging statements (print, debugPrint, dump, NSLog, Logger) in production code; all new CmuxSettings files and modified app files are clean per swift-logging.md rules.
Cmux User-Facing Error Privacy ✅ Passed PR does not violate user-facing error privacy rules. Search engine names appear only in pre-existing localized UI labels and configuration values, not in error messages. No vendor/provider names, c...
Cmux Full Internationalization ✅ Passed PR reuses existing localization keys (settings.browser.searchEngine.* and settings.browser.searchSuggestions) verified with en/ja translations; BrowserSearchEngine uses String(localized:defaultValu...
Cmux Swiftui State Layout ✅ Passed PR creates BrowserSearchSettingsStore as a stateless Sendable struct, used inline in computed properties. No new @Observable/@ObservedObject/@StateObject state introduced; @AppStorage usage is lega...
Cmux Architecture Rethink ✅ Passed PR extracts browser search settings into CmuxSettings following Wave-2 pattern; all new code is clean with no timing/dispatch/locks/observers/side-channels, maintains single source of truth (UserDe...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR extracts browser search settings to CmuxSettings with no new/modified NSWindow, NSPanel, NSWindowController, or SwiftUI Window code; BrowserPanel.swift reduced 237 lines.
Cmux Source Artifacts ✅ Passed All changed files are hand-written Swift source, tests, and config files intentionally added to support browser search settings extraction. No artifact directories, generated logs, build output, or...
Description check ✅ Passed PR description is comprehensive and well-structured, covering all template sections with detailed technical information about the refactoring, defaults preservation, validation results, and migration guidance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat-browsersearch-settings

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 Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extracts the browser-search settings domain from BrowserPanel.swift into the CmuxSettings package as a Wave-2 store, replacing the caseless BrowserSearchSettings namespace enum with a proper BrowserSearchSettingsStore struct and BrowserSearchSettingsReading protocol seam. All UserDefaults key strings, default values (except customSearchEngineURLTemplate, noted in a prior thread), and behavioral logic are preserved byte-identically.

  • New package types: BrowserSearchSettingsStore (injected UserDefaults, stateless Sendable struct), BrowserSearchSettingsReading (protocol seam for test injection), BrowserSearchConfiguration, and BrowserSearchEngine with full displayName/searchURLTemplate/supportsRemoteSuggestions/searchURL implementations.
  • App-target call sites in BrowserPanel, BrowserPanelView, TerminalController, CommandPaletteSettingsToggle, and KeyboardShortcutSettingsFileStore are mechanically updated to BrowserSearchSettingsStore constants and instance APIs; no behavioral regressions.
  • Test coverage adds four Swift Testing tests in the package with isolated UserDefaults suites, and all existing cmuxTests/BrowserConfigTests.swift tests are migrated without losing assertions.

Confidence Score: 5/5

Safe to merge; this is a mechanical extraction with no behavioral changes to production search URL rendering, defaults keys, or default values (the catalog defaultValue delta is noted in a prior thread).

The change is a well-scoped extraction: keys, defaults, and URL-rendering logic are moved verbatim, the build and test suite pass, and existing tests cover every behavioral path that was migrated. The open design questions about store allocation inside BrowserSearchConfiguration and BrowserSearchEngine are already captured in earlier review threads and do not affect correctness today.

Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchConfiguration.swift and BrowserSearchEngine.swift — see prior thread comments about the store-allocation pattern inside those value types.

Important Files Changed

Filename Overview
Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsStore.swift New Wave-2 store: stateless Sendable struct with injected UserDefaults, correct nonisolated(unsafe) annotation; creates BrowserSearchSettingsStore() instances inside BrowserSearchConfiguration and BrowserSearchEngine to call stateless helpers (already flagged in prior review threads)
Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchConfiguration.swift New value type; displayName and searchURL(query:) construct BrowserSearchSettingsStore() with .standard defaults even when struct was built from an injected suite — already flagged in a prior thread
Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchEngine.swift Expanded from a one-liner enum to a full value type with displayName, searchURLTemplate, supportsRemoteSuggestions, and searchURL(query:); searchURL(query:) unnecessarily allocates a BrowserSearchSettingsStore to call a stateless URL-rendering helper — already flagged in prior thread
Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsReading.swift Clean new Sendable protocol seam for dependency injection in tests; correct shape and doc comments
Packages/CmuxSettings/Sources/CmuxSettings/Keys/BrowserCatalogSection.swift Keys and defaultValues now sourced from BrowserSearchSettingsStore constants; customSearchEngineURLTemplate defaultValue changed from "" to the Google URL — behavior delta already flagged in prior thread
Packages/CmuxSettings/Tests/CmuxSettingsTests/BrowserSearchSettingsStoreTests.swift Four new Swift Testing tests with isolated UserDefaults suites; covers config factory fallback, template validation/rendering, and custom-name normalization correctly
Sources/Panels/BrowserPanel.swift Removes ~237 lines by deleting BrowserSearchSettings/BrowserSearchEngine/BrowserSearchConfiguration; call sites updated to BrowserSearchSettingsStore; no behavioral change
Sources/Panels/BrowserPanelView.swift @AppStorage keys and defaults updated to BrowserSearchSettingsStore constants; searchConfiguration and searchSuggestionsEnabled computed properties migrated cleanly with no behavior change
Sources/TerminalController.swift One-line migration: BrowserSearchSettings.currentConfiguration() replaced with BrowserSearchSettingsStore().currentConfiguration; equivalent behavior
Sources/KeyboardShortcutSettingsFileStore.swift Browser section import migrated to BrowserSearchSettingsStore instance; normalizedCustomSearchEngineName and isValidSearchURLTemplate calls now go through the instance API correctly
cmuxTests/BrowserConfigTests.swift All test call sites migrated from BrowserSearchSettings static methods to BrowserSearchSettingsStore instance methods; type alias updated to pin CmuxSettings.BrowserSearchEngine to resolve ambiguity

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class BrowserSearchSettingsReading {
        <<protocol, Sendable>>
        +currentSearchEngine: BrowserSearchEngine
        +currentConfiguration: BrowserSearchConfiguration
        +currentSearchSuggestionsEnabled: Bool
        +configuration(engineRaw:customName:customURLTemplate:) BrowserSearchConfiguration
        +normalizedCustomSearchEngineName(raw:) String?
        +isValidSearchURLTemplate(raw:) Bool
        +searchURL(fromTemplate:query:) URL?
    }

    class BrowserSearchSettingsStore {
        <<struct, Sendable>>
        +static searchEngineKey: String
        +static customSearchEngineNameKey: String
        +static customSearchEngineURLTemplateKey: String
        +static searchSuggestionsEnabledKey: String
        +static defaultSearchEngine: BrowserSearchEngine
        +static defaultCustomSearchEngineName: String
        +static defaultCustomSearchEngineURLTemplate: String
        +static defaultSearchSuggestionsEnabled: Bool
        -nonisolated(unsafe) defaults: UserDefaults
        +init(defaults: UserDefaults)
    }

    class BrowserSearchConfiguration {
        <<struct, Equatable, Sendable>>
        +engine: BrowserSearchEngine
        +customName: String
        +customURLTemplate: String
        +displayName: String
        +remoteSuggestionsEngine: BrowserSearchEngine?
        +searchURL(query:) URL?
    }

    class BrowserSearchEngine {
        <<enum, RawRepresentable, Identifiable, Sendable>>
        +google, duckduckgo, bing, kagi, startpage
        +brave, perplexity, exa, yahoo, ecosia
        +qwant, mojeek, wikipedia, github, baidu, yandex, custom
        +displayName: String
        +searchURLTemplate: String?
        +supportsRemoteSuggestions: Bool
        +searchURL(query:) URL?
    }

    BrowserSearchSettingsStore ..|> BrowserSearchSettingsReading
    BrowserSearchSettingsStore ..> BrowserSearchConfiguration : produces
    BrowserSearchConfiguration --> BrowserSearchEngine : contains
    BrowserSearchConfiguration ..> BrowserSearchSettingsStore : creates (standard defaults)
    BrowserSearchEngine ..> BrowserSearchSettingsStore : creates (standard defaults)
Loading

Reviews (2): Last reviewed commit: "Refresh browser search test length budge..." | Re-trigger Greptile

Comment on lines +31 to +53
public var displayName: String {
guard engine == .custom else { return engine.displayName }
return BrowserSearchSettingsStore().normalizedCustomSearchEngineName(customName)
?? engine.displayName
}

/// Built-in engine to query for remote suggestions, if supported.
public var remoteSuggestionsEngine: BrowserSearchEngine? {
guard engine.supportsRemoteSuggestions else { return nil }
return engine
}

/// Renders a search URL for the given query.
///
/// - Parameter query: The raw search query.
/// - Returns: An allowed `http` or `https` URL, or `nil` when the
/// configured template cannot produce one.
public func searchURL(query: String) -> URL? {
if engine == .custom {
return BrowserSearchSettingsStore().searchURL(fromTemplate: customURLTemplate, query: query)
}
return engine.searchURL(query: query)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 BrowserSearchConfiguration silently escapes the injected-defaults seam

Both displayName and searchURL(query:) construct a BrowserSearchSettingsStore() using .standard defaults, regardless of which suite the outer store was initialized with. The helpers they delegate to — normalizedCustomSearchEngineName and searchURL(fromTemplate:query:) — are pure string functions that don't read defaults today, so tests pass and production is correct. The danger is forward-looking: any developer who later adds a setting read inside those helpers (e.g., a scheme allow-list or a locale-aware template) will not realize that BrowserSearchConfiguration always escapes to .standard, silently making the injected suite invisible to these two paths. Since customName and customURLTemplate are already stored fields on the struct, both helpers could be called as static methods or free functions without involving the store at all.

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!

Comment on lines +154 to +157
public func searchURL(query: String) -> URL? {
guard let template = searchURLTemplate else { return nil }
return BrowserSearchSettingsStore().searchURL(fromTemplate: template, query: query)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Value type constructing a store to call a pure function

BrowserSearchEngine.searchURL(query:) creates a BrowserSearchSettingsStore() solely to invoke searchURL(fromTemplate:query:), which is a stateless URL-rendering function. This inverts the dependency: a plain value enum in the same package should not depend on the settings store. Because searchURLTemplate is already a computed property on the enum, the URL construction from that string could be done with the same inline logic as the store uses, without the BrowserSearchSettingsStore() allocation. This also means every built-in engine search from BrowserSearchConfiguration.searchURL(query:) goes through two store allocations — one constructed by BrowserSearchConfiguration and one by the engine — each doing nothing with defaults.

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!

Comment on lines 17 to 22
public let customSearchEngineURLTemplate = DefaultsKey<String>(
id: "browser.customSearchEngineURLTemplate",
defaultValue: "",
userDefaultsKey: "browserCustomSearchEngineURLTemplate"
defaultValue: BrowserSearchSettingsStore.defaultCustomSearchEngineURLTemplate,
userDefaultsKey: BrowserSearchSettingsStore.customSearchEngineURLTemplateKey
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Catalog defaultValue for customSearchEngineURLTemplate changed from "" to the Google URL

The old catalog entry had defaultValue: "" while BrowserSearchSettings.defaultCustomSearchEngineURLTemplate was always "https://www.google.com/search?q={query}". Those were inconsistent; this PR aligns them. However, the PR description only claims "Defaults key strings are preserved byte-identically" without calling out this value change. Any catalog consumer that reads BrowserCatalogSection().customSearchEngineURLTemplate.defaultValue directly — for example, a settings-export path that renders the fallback default before the user has set a value — will now see the Google URL instead of an empty string. This is probably the right behavior (it now matches what register(defaults:) installs via normalizeBrowserDefaults), but it should be explicitly confirmed rather than left as an implicit side effect of the refactor.

@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 `@Sources/Panels/BrowserPanel.swift`:
- Around line 4077-4080: In the BrowserPanel.swift defaults registration around
the searchEngineKey assignment, the search engine value is not being
canonicalized during bootstrap like other settings in the same registration
block. Resolve the engine value by instantiating a BrowserSearchSettingsStore
with the defaults dictionary being built, then extract the canonicalized
rawValue from that resolved store instance and write it back to the
BrowserSearchSettingsStore.searchEngineKey entry instead of using the raw
default directly. This ensures that stale or invalid engine values do not
persist and keeps AppStorage consumers synchronized with the navigation
fallback.
🪄 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: fd1b6791-b5f7-47f3-9829-7781d9299ee2

📥 Commits

Reviewing files that changed from the base of the PR and between f22feb1 and b7c093b.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (15)
  • Packages/CmuxSettings/Sources/CmuxSettings/Keys/BrowserCatalogSection.swift
  • Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsReading.swift
  • Packages/CmuxSettings/Sources/CmuxSettings/Stores/BrowserSearchSettingsStore.swift
  • Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchConfiguration.swift
  • Packages/CmuxSettings/Sources/CmuxSettings/Values/BrowserSearchEngine.swift
  • Packages/CmuxSettings/Tests/CmuxSettingsTests/BrowserSearchSettingsStoreTests.swift
  • Sources/CommandPalette/CommandPaletteSettingsToggle.swift
  • Sources/KeyboardShortcutSettingsFileStore+Template.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/Panels/BrowserPanel.swift
  • Sources/Panels/BrowserPanelView.swift
  • Sources/TerminalController.swift
  • cmuxTests/BrowserConfigTests.swift
  • cmuxTests/GhosttyConfigTests.swift
  • cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift

Comment on lines +4077 to +4080
BrowserSearchSettingsStore.searchEngineKey: BrowserSearchSettingsStore.defaultSearchEngine.rawValue,
BrowserSearchSettingsStore.customSearchEngineNameKey: BrowserSearchSettingsStore.defaultCustomSearchEngineName,
BrowserSearchSettingsStore.customSearchEngineURLTemplateKey: BrowserSearchSettingsStore.defaultCustomSearchEngineURLTemplate,
BrowserSearchSettingsStore.searchSuggestionsEnabledKey: BrowserSearchSettingsStore.defaultSearchSuggestionsEnabled,

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

Write back the canonical search-engine value during bootstrap.

register(defaults:) won’t overwrite an existing invalid browserSearchEngine, so this migration leaves stale raw values persisted while other settings in this same method are canonicalized. Resolve the engine through BrowserSearchSettingsStore(defaults:) and write the resolved rawValue back here so AppStorage/settings consumers stay in sync with the navigation fallback.

🤖 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/Panels/BrowserPanel.swift` around lines 4077 - 4080, In the
BrowserPanel.swift defaults registration around the searchEngineKey assignment,
the search engine value is not being canonicalized during bootstrap like other
settings in the same registration block. Resolve the engine value by
instantiating a BrowserSearchSettingsStore with the defaults dictionary being
built, then extract the canonicalized rawValue from that resolved store instance
and write it back to the BrowserSearchSettingsStore.searchEngineKey entry
instead of using the raw default directly. This ensures that stale or invalid
engine values do not persist and keeps AppStorage consumers synchronized with
the navigation fallback.

@azooz2003-bit
azooz2003-bit merged commit bd80f9e into main Jun 15, 2026
24 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-browsersearch-settings branch June 15, 2026 02:26

This branch was successfully deployed

1 active deployment
Preview – cmux — a4970eba Deployed Jun 15, 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.

1 participant