cmux-next: optional Agent integrations helper in Settings
Stacked on manaflow-ai/cmux#21813 (hook status reports conflicts); review that first. This PR's diff against feat-cmux-next includes it until it lands.
Settings > Agents gets an optional Agent integrations card for the coding-agent hooks that let cmux show when an agent is working, waiting or done. It lists each provider's hook state and offers Install, Repair or Remove, with the CLI command to copy as a fallback.
It stays out of the way: the card is collapsed, reads nothing until opened, and changes nothing without a click. A deep link (focus=agents.integrations) opens it.
What it does
- Status comes from the bundled CLI,
cmux --json agent hook status. It's read once when the card opens and again on Refresh. - Install (state
absent) and Repair (partial) runcmux --json agent hook install <id>. Remove (installedorpartial) runsagent hook uninstall <id>. Status is read again after each one. A refusal from the CLI shows on that row in the CLI's own words. - Blocked (
conflict, added in #21813) means a file cmux didn't create, a symlink, or a non-file is in the way. The row offers no Install. It says what's there, shows the path, and givescmux agent hook install <id>to copy once the file is moved. Can't read (unavailable) says to check permissions. The host refuses Install over either state too, not just the page. - No CLI in the build: the card says so and still shows the command.
The install logic lives only in the Rust CLI (cmux-tui-hooks). Swift (SettingsAgentIntegrations) runs the CLI with ProcessRunner, parses the result, and keeps the row list. It accepts only provider ids the last status listed.
One limit: the app runs the CLI with the app's own environment. A CLAUDE_CONFIG_DIR or CODEX_HOME set only in a shell profile isn't seen, so the card targets the default paths. Each row shows its path so this is visible, and the copyable command is the fallback.
Files
- New target
CmuxNextAgentIntegrations:SettingsAgentIntegrations.swift(++Process.swift, split out because CmuxNextDaemon and CmuxNextSettings both export aJSONValue). It is aPageProvider; the App passes it the bundled CLI's location. It lives outside CmuxNextApp because the App target may not grow (check-app-size.sh). SettingsPageProviderroutescmux.settings.integrations.state|runto it, andPageFactorywires it. The provider's nil-host guards now share one helper, so CmuxNextApp ends with fewer source lines than the base.SettingsPageLayout.Card.agentIntegrationssits in the Agents trail. The exportedsettings-schema.jsonand its source stamp were updated to match (defaults_guard.py check-stamppasses).- React:
components/AgentIntegrations.tsx, plus ops, store, mock and gallery variants (agents-integrations,agents-integrations-no-cli). - 22
settingsWindow.agentIntegrations.*strings, translated into all 21 catalog locales.
Verification
- Red first (343228a4577):
bun test src/pages/settings/agentIntegrations.test.tsxat the test-only commit gave 0 pass, 4 fail. - After merging
feat-cmux-next(c5a1f900ec0c, merge c9ed6ee1d5e) and trimming two lines of filler copy (2813f171d96):bun test src/pages/settings src/gallerygave 132 pass at c9ed6ee1d5e, and the card, description-length and strings tests passed again at 2813f171d96. - Green (4101d5ae05b):
bun test src/pages/settings src/gallerygave 131 pass, including the 60-character description-line check in every locale.bun run typecheck,bun run lint,vp fmt --checkandscripts/lint-ios-package-conventions.share clean.scripts/localization_catalog.py checkreports no errors for the new keys. - Swift, on fleet minis via
cmux-ci run: red on 343228a4577 (cannot find 'SettingsAgentIntegrations' in scope). Green on a6e702fb47d:package-test-lane.sh suite Packages/macOS/CmuxNext SettingsAgentIntegrationsTestsgave 5 tests in 1 suite passed. Two test-only fixups landed in between: animport CmuxNextPages, and moving the fake CLI off the main actor. - Not verified: a native tagged build.
cmux-ci build cmuxcan't provision the dev backend from huge-blue (no route tocmux-dev-backend-1), so no tagged app was built or dogfooded. The screenshots below are the React Settings page from the webviews gallery build (agents-integrations*variants against the mock host), rendered in headless Chromium. They are not the native app. The full CmuxNext package build and suites run in this PR's CI.
Screenshots
Collapsed (the default):

Opened, light and dark: installed, needs repair, blocked by a file cmux didn't create, and not installed:


A build without the CLI:

Localization audit
There are 22 new keys in CmuxNextSettingsWindow/Localizable.xcstrings, translated into all 21 locales the catalog carries (the 9 required macOS locales among them), and regenerated into generated/strings.json. Every line is 60 characters or fewer in every locale. There's no bare English in the changed TSX or Swift. The CLI's English detail and refusal text is shown as-is, as other Settings cards do with daemon text.
Changelog
- Added: An optional Agent integrations card in Settings > Agents that installs, repairs or removes coding-agent hooks and explains when a file cmux didn't create is in the way.
No capture: the card is part of the webview Settings page. The gallery advisory run captures it (agents-integrations, agents-integrations-no-cli). The Swift side is a page provider with no native UI of its own.
🤖 Generated with Claude Code
Agent session: cosmic-gray