Settings > Browser > Extensions: import, add-unpacked, and live enable/disable for web extensions
Summary
- Adds opt-in browser web-extension management under Settings → Browser → Extensions.
- Introduces the
browser.webExtensionssetting for Safari app extensions and unpacked extension folders, with import, add, enable/disable, remove, and toolbar-visibility controls. - Reconciles settings live with one shared
WKWebExtensionController: enabled extensions load at startup and on change; disabled/removed extensions unload without discarding permission state unnecessarily. - Routes extension commands, toolbar actions, popup/popout windows, extension-owned navigation, passkeys, and active-tab/window lifecycle through the built-in browser.
- Replaces the earlier hardcoded Bitwarden path with a generic, fail-closed model. Nothing loads unless the user adds it or automation supplies
CMUX_BROWSER_EXTENSIONS. - Adds behavior coverage for settings observation and optimistic writes, discovery parsing, load/unload reconciliation and rollback, toolbar visibility, prewarmed WebView host scoping, shortcut precedence, navigation, metadata invalidation, and extension tab/window behavior.
This makes WebKit extension support user-manageable and safe to apply live instead of being tied to one extension or a fixed local path.
Screenshots
The Extensions card in Settings → Browser with the Bitwarden Safari extension imported and enabled:

Extensions showing in the browser:
Passkey flow working:
Testing
Final-head verification target: 840428a64281.
- Main/conflict integration:
- merged current
origin/mainthrough7fa5eabe26 - resolved the Xcode project conflict by preserving both browser-extension ownership and main’s background-workspace mount policy wiring
vendor/bonsplitremains pinned toa0400b3533db21afda4a5a59e695cbff588a39b7in the branch tree,origin/maintree, and clean detached submodule checkout; the unrelated newer bonsplit upstream commit was intentionally not introduced
- merged current
- Latest red/green navigation and identity proof:
- test-only commits:
034829f134and0a8a21234a - implementation commit:
5b6d933c98 - package path-identity regressions: 2 passed
- exact final-head app-host regressions:
repeatedReplacementForSameExtensionContextKeepsWebView()andextensionContextSwapPreservesLogicalNavigationHistory()both passed; Xcode reported** TEST SUCCEEDED **
- test-only commits:
- Earlier focused behavior validation retained across the review stack:
BrowserPrewarmedWebViewPoolTests: 13 passedBrowserWebExtensionReviewRegressionTests: 6 passedBrowserWebExtensionSupportTests: 14 non-WebKit-host tests passedBrowserExternalNavigationSchemeTests: 6 passedBrowserWebExtensionDiscoveryServiceTests: 1 passed- both affected Swift package suites: 6 tests each passed
- Static validation on the final merged head:
git diff --checkPackage.resolvedpolicy- workspace package grouping
- pbxproj normalization/check
- test-target wiring (485 files)
- diff-aware Swift file-length budget
- no user-facing strings changed by the final conflict/navigation fixes; the prior 26 added localization keys retain nonempty coverage across all 20 supported locales
- Tagged build:
./scripts/reload.sh --tag browser-extension-management- succeeded on the exact final merged head
- app:
/Users/austinwang/Library/Developer/Xcode/DerivedData/cmux-browser-extension-management/Build/Products/Debug/cmux DEV browser-extension-management.app
- Manual dogfood from the tagged build verified persistence, startup loading, live enable/disable, import/remove, toolbar popup, extension shortcut routing, and passkey sign-in.
Local runner note: this machine has no logged-in GUI console session, but the two targeted AppKit/WebKit regressions above completed successfully. CI remains authoritative for the broader key-window/WebKit-host matrix.
Demo Video
- No new video was recorded. The screenshots above show the settings UI, toolbar integration, and passkey result; the tagged build is available for dogfood.
Review Trigger (Copy/Paste as PR comment)
@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review
Checklist
- I tested the change locally
- I added or updated tests for behavior changes
- Docs/changelog update is not required for this settings/browser feature
- I requested bot reviews after my latest commit (copy/paste block above or equivalent)
- All code review bot comments are resolved
- All human review comments are resolved
🤖 Generated with Claude Code and iterated with Codex
[!NOTE]
Medium Risk
Touches global keyboard routing, shared JSON config concurrency, and extension load/navigation policy in the embedded browser—high user impact but guarded by macOS version checks and extensive tests in the full PR.
Overview
Adds Settings → Browser → Extensions so users can import Safari .appex extensions, add unpacked folders, and enable/disable/remove entries persisted as browser.webExtensions in cmux.json. The UI uses optimistic writes with rollback, host discovery/load-error streams, and duplicate-resource handling; only enabled entries are meant to load in the browser (macOS 15.4+).
Config plumbing: JSONConfigStore gains an atomic update(_:mutation:) and skip-no-op writes via mutateRoot returning Bool. JSONValueModel serializes writes, exposes hasObservedValue and write completion IDs for the extensions card.
Runtime wiring (in this diff): AppDelegate strongly retains browserWebExtensionHost and passes it into new TabManager / DockSplitStore instances; dock/browser panel creation hooks register extensions and notify the host on focus/metadata changes. New shortcut routing lets manifest keyboard commands run when cmux shortcuts (and browser focus mode) would otherwise block them, including before stale menu-shortcut suppression. Browser navigation policy gains extension-specific block/route-in-current-tab hooks; external URL handling moves into shared BrowserExternalNavigationPolicy helpers.
Also: SettingsHostActions discovery/support APIs, settings search anchor for web extensions, centralized NSWindow.cmuxShouldOwnCloseShortcut, and localized strings for the extensions UI and extension permission/errors.
Reviewed by Cursor Bugbot for commit 4a7e47809f24b5434b384a09f01c7aab7e8291ba. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
- New Features
- Added browser web extension support on macOS 15.4 and later.
- Manage extensions from Browser settings, including importing Safari extensions and adding unpacked extensions.
- Enable, disable, and remove configured extensions with duplicate and invalid-folder checks.
- Extension toolbar actions, popups, navigation, and keyboard commands are supported.
- Bug Fixes
- Improved browser panel and prewarmed web view handling when extensions are enabled.
- Documentation
- Added localized labels, help text, search keywords, and unsupported-platform messaging.