[CMUX Next] Chief pet: floating pet, notices, quick reply and Settings (whole stack)
Summary
This PR lands the whole Chief pet stack. It targets feat-cmux-next and contains #21728 (floating panel), #21732 (notice deck) and #21736 (quick reply), plus the review fixes listed below. Merging it lands all four, and those three close as included. This section covers the settings part; the stacked PRs describe the rest and carry their side-by-sides.
The settings part: It adds two settings in a Chief Pet card under Settings > Agents (section home) and removes the chiefPet.enabled Debug Settings toggle.
- Show Chief Pet (
home.chiefPetEnabled), off by default. Help text: "A small Chief floats over every app and shows agent events above it. Drag it anywhere; click it to message the Chief or reply to a session." - Character (
home.chiefPetMascot): one of the Chief Dock's nine pixel mascots, the ones Codex generated (orb,orb-spark,orb-hood,machine,machine-cyan,machine-blue,moon,moon-blue,fox). It defaults toorb, as the dock does. An unknown id falls back to Orb and reports a diagnostic.
How the settings behave:
- The palette's settings rows pick both up through the schema.
cmux settings set home.chiefPetEnabled trueandcmux settings set home.chiefPetMascot foxchange them from the CLI. - Agents may set both (
agentSettableTable), since they change looks only. - The pet follows both live. Turning it off hides the pet, the notices and the reply box. Changing the character redraws the pet where it is.
- They're wired next to the other
follow(settings)services inAppDelegate. Showcase captures never start the pet.
The generated settings exports (schemas/settings/settings-schema.json, schemas/defaults/cmux-next.json, docs/mdm/*) and the Settings page string bundle are regenerated by the PR autofix job, which needs a Mac swift test. They aren't hand-edited here.
Review fixes (correctness review subagent)
- Reply safety: a typed reply goes into a terminal only while that notice is still its tab's unread notification. This is the same guard a
notify --replybanner uses. - Notices read elsewhere: a notice read on another client, on the phone, by closing its tab or by a daemon restart now leaves the pet. The pet reconciles against the unread count.
- Reply menu:
- Two notices with the same title stay two menu items.
- The chosen session survives refreshes. If it goes away, the box falls back to the Chief, never to another session.
- ⌘Return opens the target. Other ⌘ keys stop at the box instead of acting on the cmux window behind it.
- Clicks and opening:
- Notice capsules now receive the press, so a click opens the tab.
- An agent chat opens its own tab instead of a second copy in the floating chat.
- Deck edge case: a finished turn that arrives behind three waiting notices no longer animates or schedules a timer for a notice that isn't shown.
- Module and file rules:
CmuxNextFloatingno longer importsCmuxNextDaemon; the App maps the notification.- The notification service makes the pet, so
AppServices.swift,AppDelegate.swiftandCmuxConfigSnapshot.swiftdon't grow. - The
standardconstant was renamed toinitialfor the lint.
Reference
The character choices against the Codex-generated avatars (chief-pet-refs/codex-generated), both at 720 × 720. Each choice is drawn at the pet's 88 × 80 pt box at @2x:
Testing
ChiefPetSettingTests (CmuxNextSettingsTests) covers:
- off by default, with the row's default matching the parser's, in the Home section, as a toggle;
- cmux.json turning the pet on;
- a value that isn't a bool staying off, with a diagnostic;
- agents being allowed to set it;
- the character defaulting to Orb, accepting a mascot id, and rejecting an unknown one with a diagnostic;
- the character row's choices matching the mascot ids.
In ChiefPetTests:
everySettingIdIsAMascotpins the module's ids to the same list.controllerShowsThePetOnlyWhileItIsOndrives the observed switch: no panel while off; turning it on shows the pet; a click opens the reply box; turning it off hides both; turning it on again reuses the same panel.
What ran:
- The cmux-next fast tier passed on aba0ee4. It built
CmuxNextFloatingand every test target, including the new test files. - The
cmux-next swift testjob is skipped on PRs, so the new tests compiled but have not been executed. They run after merge. They were not run locally either (Linux host). lint-ios-package-conventions.shis clean on this stack's files.check-no-godfiles.shshows no growth.CmuxNextAppshrinks by about 140 source lines.
Known red checks:
defaults-snapshot: the generated settings exports (settings-schema.json,docs/mdm, defaults snapshot) need a Macswift testto regenerate. The PR autofix doesn't regenerate them; the base autofix bot does after merge. The two new defaults (home.chiefPetEnabledfalse,home.chiefPetMascot"orb") still need a defaults owner's approval.build / release-compilefails on every current feat-cmux-next PR.cmux-next checksfails only on the Chief first-turn token-cost check, which also fails on base.
Localization: 13 new strings in CmuxNextSettings/Localizable.xcstrings, all with 20 locales: the group, the toggle and its help, "Character", and the nine mascot names. Chief stays untranslated.
Changelog
Added: A floating Chief pet (Settings > Home > Show Chief Pet) that shows agent events over any app and lets you message the Chief or reply to a session without switching to cmux, with a choice of nine pixel characters
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds the Chief pet to Settings > Agents: a pixel mascot floating over every app that shows agent notices above it and offers a quick reply. Replaces the Debug Settings toggle with home.chiefPetEnabled (off by default, user-only) and home.chiefPetMascot (nine mascots, Orb by default, agent-settable); the pet follows both settings live.
- Notices, their bubble, and the reply box live in the new
CmuxNextFloatingtarget; the notification service feeds the pet only events that would alert on this Mac, and a notice read elsewhere leaves the pet. - A typed reply enters a terminal only while the notice is still that tab's unread notification, and only for an agent's or
notify --replynotice; other terminal notices open their tab, and a session that leaves drops the text instead of sending it to the Chief. ⌘Return opens the target and the chosen session survives refreshes. - The pet, notices, and reply box stay out of screen shares; unknown mascot ids fall back to Orb with a diagnostic.
- The bubble and reply field draw their title from the type scale.
- Generated settings exports for MDM and the defaults snapshot are regenerated after each base merge, and the CI target graph lists the new floating surfaces.
- Home's Keyboard Shortcuts link now opens in the background instead of on the main thread.