Menu Bar Icon States
Scope: macOS app (apps/macos). Rendering: CritterIconRenderer.makeIcon(...). Animation/state wiring: CritterStatusLabel + CritterStatusLabel+Behavior.swift.
Dock icon
Inside the Mac app’s Dashboard, choose a Dock icon in Settings → This Mac → Dock icon:- Original (default): the original Molty silhouette on a paper tile.
- Heritage: the legacy README lobster with its raised claw.
- Clawmark: a bold, sculpted lobster pincer.
- Origami: a folded, faceted Molty.
- Pincer: a single claw silhouette with a rounded, flowing wrist.
- Open C: a circular claw with two opposing pincer tips.
apps/macos/Icon.icon; other vector designs are in
apps/macos/AppIconDesigns. After editing them, regenerate the pairs with
bash scripts/generate-mac-app-icons.sh and verify them with
bash scripts/generate-mac-app-icons.sh --check. The generator owns custom dark
backgrounds and monochrome foreground colors, and Apple’s asset compiler supplies the macOS mask and padding.
Packaging also compiles the primary Icon Composer document for native styling.
States
A tool-activity badge (SF Symbol puck, e.g.
chevron.left.slash.chevron.right for exec) can render on top of the same critter icon when a session has an active job or tool. That badge comes from IconState/ActivityKind; see Menu bar for the full state model.
Voice wake ears
- Trigger:
AppStateStore.shared.triggerVoiceEars(ttl: nil), called from the voice-wake capture pipeline (VoiceWakeRuntime) and from voice-wake debug/test tooling (VoiceWakeTester,VoiceWakeOverlayController). - Stop:
stopVoiceEars(), called when capture finalizes. - Silence window before finalizing:
2.0snormally,5.0sif only the trigger word was heard and no further speech followed (VoiceWakeRuntime.silenceWindow/triggerOnlySilenceWindow). - While boosted, idle blink/wiggle/leg/ear timers are suspended (
earBoostActivegates the animation task inCritterStatusLabel+Behavior).
Shapes and sizes
- Canvas: 18x18pt template image, rendered into a 36x36px bitmap backing store (2x) so the icon stays crisp on Retina.
- Ear scale defaults to
1.0; voice boost setsearScale=1.9without changing the overall frame. antennaDroop(0-1) folds the antennae down for the paused and sleeping poses.- Leg scurry uses
legWiggleup to1.0with a small horizontal jiggle.
Behavioral notes
- No external CLI/broker toggle for ears or working state; both are driven internally by app signals (
AppState.setWorking,AppState.triggerVoiceEars) to avoid accidental flapping. - Keep any new TTL short (well under 10s) so the icon returns to baseline quickly if a job hangs.