cmux NEXT Home: Chiefs' avatars move, slow at idle and livelier while working
Leo, 2026-11-01: "i also want them animated like how chatgpt animates their dots".
A Chief's own avatar in Home's list and pinned grid now moves: a slow loop at idle, and a quicker, deeper one while the Chief works (its turn is running, InboxRow.isTyping). Conversations without their own avatar, people and the CH monogram rows only move when they are a Chief's.
Versions (gallery)
ChiefAvatarMotionGalleryTests draws each style at idle and while working, one period in eight frames, to Packages/Shared/CmuxMessagesLab/.build/chief-avatar-motion-gallery.png (motion exaggerated 4x so a point reads on the sheet):
| Style | Idle | Working |
|---|---|---|
| Float (default) | bobs ±1 pt, 3.2 s | ±1.6 pt, 0.9 s |
| Breathe | grows up to 3.5%, 3.6 s | a double beat of 7%, 1.1 s (closest to ChatGPT's dot) |
| Sway | tilts ±2.5°, 4.0 s | ±5°, 1.0 s |
| Still | none | none |
I picked Float. It reads as "alive" at row size without changing the avatar's outline, and in a dense list it is the least distracting. Switch styles in Debug Settings > Home > Chief avatar motion (home.avatarMotion). Each avatar starts at its own phase (from its conversation id), so a list of Chiefs never moves in lockstep.
Stop conditions
Each one removes the loop and leaves the avatar at rest:
- Reduce Motion (system, or the cmux pin) and calm mode: Home's existing
reduceMotionDidChangepath. ui.animationSpeedoff, or Home's motion switch off: the host's gate isMotion.home.animatesLoops, re-read on.speedchanges.- App inactive, or the window not key, minimized, hidden or covered. The vendored list already tracks its window's key state (
setWindowActive), and that tracking re-applies every avatar. Applying also readsisVisible,isMiniaturizedandocclusionState. No new notification observers were added. - Off screen: a row or tile going back to the pool (scrolled away, or the conversation removed) stops its loop in
recycle. - Style Still.
Performance
- 0 main-thread work per frame. Each avatar's motion is one
CAKeyframeAnimation(48 steps,repeatCount = .infinity) added to its layer and run by the render server. There is no timer, display link or redraw. - A reload that keeps the same mode and style keeps the running loop (asserted by test), so a list update adds no animation work.
- Per configure, the cost is one
animation(forKey:)lookup and an equality check, O(1) per visible row. - No same-harness before/after frame numbers yet. That is a follow-up on the Home perf harness.
Design
- No module statics or KVC: the host's gate and style live on the list's controller (
CmuxSidebarView.avatarLoopGateandavatarMotionStyleare instance properties that forward to it), and eachSidebarRowLayerrecords what its avatar shows. - The vendored edits are marked
// cmux:.Patches/was regenerated by reverse-applying the base patch to recover the pin, then diffing again (no MessagesLab checkout on this host);sync-messageslab.sh --checkwas not run.
Tests
ChiefAvatarMotionTests (MessagesLab package) covers:
- idle vs working loops on rows and tiles;
- no motion without an avatar of its own, or with no motion asked;
- the same animation object kept across a reload;
- Reduce Motion, and the host's gate stopping and restarting loops;
- resigning key stopping them, and the real off-screen check;
- a pooled row stopping, and Still never starting;
- every loop closing (first frame equals last frame) and seeds differing in phase.
Observed / Not run
- Fleet: MessagesLab
ChiefAvatarMotionTests,ChiefAvatarMotionGalleryTests, and CmuxNextChiefHeaderMonogramTests,HomeChatHeaderDefaultTests,PerChiefPetTestsat the head (results in a comment below). - Not run: a DEV build watching the list live; the fresh-home launch (Chief area) follows in a comment.
No capture: the motion is in the gallery sheet; Leo tries the build.
Changelog
Added: Chiefs' avatars in Home's list move gently, and a little more while the Chief is working.
Agent session: agent session
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Chiefs' avatars in Home's list and pinned grid now move — a slow loop at idle and a livelier one while the Chief works (its turn is running). Each avatar's motion is one CAKeyframeAnimation run by the render server, so there's no main-thread work per frame.
Motion styles
- Float (default) bobs the avatar ±1 pt at 3.2 s; working is ±1.6 pt at 0.9 s.
- Breathe grows it up to 3.5%; working is a double beat of 7% (closest to ChatGPT's dot).
- Sway tilts ±2.5°; working is ±5°.
- Switch styles in Debug Settings > Home > Chief avatar motion; a style change restyles every avatar at once. Each avatar starts at its own phase (from its conversation id), so a list of Chiefs doesn't move in lockstep.
Stop conditions
- Reduce Motion, calm mode,
ui.animationSpeedoff, and Home's motion switch stop the loops. - Loops also stop when the app is inactive, the window is not key, minimized, hidden, or off screen, and when a row returns to the pool.
- A reload that keeps the same avatar keeps its running loop, so list updates add no animation work.
- Style Still never starts a loop.