Audio Notifications
Overview
Section titled “Overview”Audio notifications play sound files and announce session names via text-to-speech when session statuses change. Sound packs provide themed audio, volume is configurable per-event, and multiple sound variants per event are randomly selected for variety. Notifications fire for both Claude Code and external agents (OpenCode, etc.).
Quick Start
Section titled “Quick Start”- Create
~/.config/navi/sounds.yaml:
enabled: truepack: starcraft
triggers: waiting: true permission: true done: true error: true
tts: enabled: true-
Install a sound pack at
~/.config/navi/soundpacks/starcraft/with audio files named by event (e.g.,waiting.wav,done.mp3) -
Ensure a system audio player is installed (
paplay,aplay,mpv, orffplayon Linux;afplayon macOS) -
Notifications fire automatically when session statuses change.
Sound Packs
Section titled “Sound Packs”Sound packs are directories of audio files organized by event at ~/.config/navi/soundpacks/:
~/.config/navi/soundpacks/ starcraft/ waiting.wav waiting-1.wav # Multi-variant waiting-2.wav # Multi-variant permission.wav done.wav error-1.wav # Multi-variant error-2.wav # Multi-variant retro/ waiting.mp3 permission.mp3 done.mp3 error.mp3File Naming
Section titled “File Naming”- Single:
<event>.ext(e.g.,done.wav) - Multi-variant:
<event>-<N>.ext(e.g.,waiting-1.wav,waiting-2.wav) - Supported formats:
.wav,.mp3,.ogg,.flac
When multiple files exist for an event, one is randomly selected on each notification.
Managing Sound Packs
Section titled “Managing Sound Packs”TUI Picker
Section titled “TUI Picker”Press S in the session view to open the sound pack picker:
╭─────────────────────────────────────────╮│ Sound Packs ││ ││ ✓ starcraft (4 events, 7 files) ││ retro (4 events, 4 files) ││ minimal (3 events, 3 files) ││ ││ ↑↓: navigate Enter: select p: ││ preview Esc: close │╰─────────────────────────────────────────╯| Key | Action |
|---|---|
↑/↓ or k/j | Navigate packs |
Enter | Select pack (immediate hot-swap, persisted to config) |
p or Space | Preview a random sound from highlighted pack |
Esc | Close without changing |
If no packs are installed, a helpful message directs you to the soundpacks directory.
CLI Commands
Section titled “CLI Commands”navi sound list # List available packs with event/file countsnavi sound test <event> # Play configured sound for an eventnavi sound test-all # Play all enabled trigger events sequentiallyVolume Control
Section titled “Volume Control”volume: global: 80 # 0-100, default 100 events: # Per-event multiplier (0.0-1.0) error: 1.0 # Errors at full configured volume done: 0.7 # Done at 70% of global = 56 effective waiting: 0.5 # Waiting at 50% of global = 40 effectiveEffective volume = global * event_multiplier, clamped to 0-100. A volume of 0 skips playback entirely.
Backend Volume Flags
Section titled “Backend Volume Flags”| Player | Volume Flag |
|---|---|
paplay | --volume=0-65536 (PulseAudio native) |
pw-play | --volume=0.0-1.0 (float) |
afplay | -v 0.0-1.0 (float) |
mpv | --volume=0-100 (percentage) |
ffplay | -volume 0-100 (percentage) |
aplay | No volume flag (uses system mixer) |
Mute Toggle
Section titled “Mute Toggle”Press m in the session view to toggle mute. When muted:
- No sounds or TTS play
- “MUTED” indicator appears in the status line
- Mute state is session-only (resets on restart)
How It Works
Section titled “How It Works”The TUI polls sessions every 500ms. When a session’s status changes, the audio system:
- Checks if notifications are enabled and not muted
- Checks if the status has a trigger enabled
- Checks per-session cooldown (default 5 seconds)
- Resolves the sound file:
- First: explicit
files.<status>override in config - Then: active sound pack (random selection if multiple variants)
- Otherwise: no sound
- First: explicit
- Plays the sound with effective volume
- Speaks a TTS announcement after a 150ms delay (if TTS enabled)
All playback is non-blocking — audio runs in background goroutines. The first poll after startup is silent to avoid a burst of notifications.
External Agent Notifications
Section titled “External Agent Notifications”Audio notifications also fire for external agent (OpenCode, etc.) status changes:
- Each agent gets independent cooldown tracking via composite key (
sessionName:agentType) - Same sound/TTS configuration applies to all agents
- The background attach monitor also tracks agent state transitions
- On first poll, agent states are initialized without firing notifications
Configuration
Section titled “Configuration”Full configuration at ~/.config/navi/sounds.yaml:
enabled: true # Master togglepack: starcraft # Active sound pack name
volume: # Volume settings global: 80 # 0-100, default 100 events: # Per-event multiplier (0.0-1.0) error: 1.0 done: 0.7 waiting: 0.5
triggers: # Per-status enable/disable waiting: true permission: true working: false idle: false stopped: false done: true error: true
files: # Explicit per-status file overrides permission: ~/custom/alert.wav # Overrides pack for this event
tts: enabled: true # Text-to-speech announcements template: "{session} — {status}"
cooldown_seconds: 5 # Per-session cooldown intervalplayer: auto # Audio player: auto, paplay, afplay, aplay, mpv, ffplaytts_engine: auto # TTS engine: auto, say, espeak-ng, espeak, spd-sayConfiguration Reference
Section titled “Configuration Reference”| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Master toggle for all audio |
pack | string | — | Active sound pack directory name |
volume.global | int | 100 | Global volume (0-100) |
volume.events.<status> | float | 1.0 | Per-event volume multiplier (0.0-1.0) |
triggers.<status> | bool | varies | Whether to notify on this status |
files.<status> | string | — | Explicit file override (takes precedence over pack) |
tts.enabled | bool | true | Enable text-to-speech announcements |
tts.template | string | "{session} — {status}" | TTS announcement template |
cooldown_seconds | int | 5 | Minimum seconds between notifications per session |
player | string | "auto" | Audio player binary or "auto" for detection |
tts_engine | string | "auto" | TTS engine binary or "auto" for detection |
Default Triggers
Section titled “Default Triggers”| Status | Default |
|---|---|
waiting | enabled |
permission | enabled |
working | disabled |
idle | disabled |
stopped | disabled |
done | enabled |
error | enabled |
Backwards Compatibility
Section titled “Backwards Compatibility”The files: config still works without sound packs. If both pack: and files: are set, explicit files: entries override the pack for those specific events.
Audio Player Detection
Section titled “Audio Player Detection”When player: auto, navi searches for available backends:
| Platform | Detection Order |
|---|---|
| macOS | afplay (built-in) |
| Linux | paplay (PulseAudio) → aplay (ALSA) → ffplay (FFmpeg) → mpv |
TTS Engine Detection
Section titled “TTS Engine Detection”When tts_engine: auto, navi searches for available backends:
| Platform | Detection Order |
|---|---|
| macOS | say (built-in) |
| Linux | espeak-ng → espeak → spd-say (speech-dispatcher) |
The TTS template supports {session} and {status} placeholders.
Graceful Degradation
Section titled “Graceful Degradation”- Missing config file: audio disabled, no errors
- No audio player found: notifications silently skipped
- No TTS engine found: sound plays but no speech
- Missing sound file for a status: sound skipped, TTS still plays
- No sound packs installed: pack picker shows helpful message
- Malformed YAML: error returned, audio disabled
Related Features
Section titled “Related Features”- Session Monitoring — Status updates that trigger notifications
- Multi-Agent Support — External agent status changes also trigger audio
- Background Monitor — Audio notifications continue while attached to tmux