Menu Bar Icon States
Scope: macOS app (apps/macos). Rendering: CritterIconRenderer.makeIcon(...). Animation/state wiring: CritterStatusLabel + CritterStatusLabel+Behavior.swift.
States
| State | Trigger | Visual |
|---|---|---|
| Idle | Default | Normal blink/wiggle animation |
| Paused | isPaused=true | Status item uses appearsDisabled; no motion |
| Voice wake (big ears) | Wake word heard | Ears scale to 1.9x with earHoles=true (circular holes for readability); drops after silence |
| Working | isWorking=true or an active IconState | Faster leg wiggle (legWiggle up to 1.0) plus a small horizontal offset; additive to idle wiggle |
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.9andearHoles=truewithout changing the overall frame. - 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.