Soundpacks
A soundpack maps Claudio sound keys (such as success/git-success.wav) to
audio files. A pack can be a directory, a JSON manifest, or a git repository
that Claudio manages for you.
The first half of this page covers using and installing packs. The second covers building one. The last section explains how Claudio picks a sound, which you only need when debugging or naming files precisely.
Audio Formats
Claudio’s native player decodes:
- WAV: mono or stereo; 8-, 16-, 24-, or 32-bit PCM, or 32-bit float (float samples beyond full scale are clipped). Files with more than two channels are rejected.
- MP3: the info header frame that most encoders write is not played, and the encoder delay and padding recorded by LAME or ffmpeg are trimmed, so the sound starts on time. An MP3 with no such header still starts about 23 ms late at 48 kHz; that delay is part of the format.
- AIFF (and uncompressed AIFC): 16-, 24-, or 32-bit. Files with more than two channels are downmixed to stereo.
Playback reads at most 100 MiB from any audio file. An MP3 whose decoded PCM would exceed 100 MiB is rejected, so an MP3 well under that size on disk can still hit the limit.
Categories
Every event maps to one category, and each category is a directory in the pack:
| Category | Typical events | Directory |
|---|---|---|
| Loading | PreToolUse, SubagentStart |
loading/ |
| Success | successful PostToolUse |
success/ |
| Error | failed PostToolUse, PostToolUseFailure |
error/ |
| Interactive | prompts, notifications, permission requests | interactive/ |
| Completion | Stop, SubagentStop |
completion/ |
| System | session start, compaction | system/ |
default.wav at the pack root is the last fallback for every event.
Where Soundpacks Live
Claudio uses XDG base directories. On Linux and WSL the data directory is
~/.local/share; on macOS it is ~/Library/Application Support; on Windows
it is %LOCALAPPDATA%. On macOS and Windows the config directory is the same
folder as the data directory.
| Item | Linux / WSL | macOS | Windows |
|---|---|---|---|
| Installed packs | ~/.local/share/claudio/soundpacks/<name>/ |
~/Library/Application Support/claudio/soundpacks/<name>/ |
%LOCALAPPDATA%\claudio\soundpacks\<name>\ |
| Managed git clones | ~/.local/share/claudio/soundpack-repos/<name>/ |
~/Library/Application Support/claudio/soundpack-repos/<name>/ |
%LOCALAPPDATA%\claudio\soundpack-repos\<name>\ |
| Managed git registry | ~/.config/claudio/soundpacks.json |
~/Library/Application Support/claudio/soundpacks.json |
%LOCALAPPDATA%\claudio\soundpacks.json |
config.json |
~/.config/claudio/config.json |
~/Library/Application Support/claudio/config.json |
%LOCALAPPDATA%\claudio\config.json |
An installed JSON pack is a directory like any other, with its manifest at
soundpacks/<name>/soundpack.json.
XDG_DATA_HOME and XDG_CONFIG_HOME override these locations on every
platform, including Windows.
Built-In Packs
Four platform packs are compiled into the binary and need no install step.
claudio soundpack list shows them with the type embedded.
| Pack | What it plays |
|---|---|
windows |
Sounds from C:\Windows\Media |
wsl |
The same Windows sounds, reached through /mnt/c/Windows/Media |
darwin |
macOS system sounds from /System/Library/Sounds |
linux |
Seven synthesized tones shipped inside the binary, one per category plus default.wav |
The windows, wsl, and darwin packs only map to files that already ship
with the operating system. WSL gets its own pack, even though it runs the
Linux binary, because the Windows sound files are available there.
Using A Pack
Switching The Active Soundpack
claudio soundpack list
claudio soundpack use <name>
soundpack use sets default_soundpack in config.json. The name has to
be one that soundpack list shows: an embedded pack, a managed git pack, a
pack in the XDG soundpacks/ directory, or a pack listed in
soundpack_paths. soundpack list prints packs in that order. If two packs
share a name, the first one listed is the one Claudio plays.
To override the pack for one run without changing the config:
claudio --soundpack <name>
CLAUDIO_SOUNDPACK=<name> claudio
If the configured pack cannot be found, Claudio logs an error and falls back to the platform pack.
Installing A Pack From Git
A pack is shared as a git repository. Any public or private repository that contains a directory pack or a JSON pack works.
To find published packs:
claudio soundpack search # every published pack, most starred first
claudio soundpack search retro # narrowed by words
There is no central index to register with. search lists GitHub
repositories tagged with the topic claudio-soundpack and prints the
command that installs each one. See Publishing A Pack
to make yours show up.
claudio soundpack add https://github.com/owner/repo --name my-pack --default
claudio soundpack add gh:owner/repo --subdir packs/minimal --name minimal
add clones the repository into soundpack-repos/<name>/, validates it,
records it in the local soundpacks.json registry (name, source URL, ref,
commit), and adds the playable path to soundpack_paths. gh:owner/repo is
shorthand for https://github.com/owner/repo.git.
| Flag | Effect |
|---|---|
--name |
Name for the installed pack |
--subdir |
Directory or JSON file inside the repository to use as the pack |
--ref |
Branch, tag, or commit to check out |
--default |
Make it the active pack |
--replace |
Replace an existing managed pack with the same name |
--skip-validate |
Skip validation before adding |
Update one pack or all of them:
claudio soundpack update my-pack
claudio soundpack update --all
claudio soundpack update my-pack --force # discard local changes in the clone first
Claudio never fetches in the background or while handling hooks. A managed
pack stays at the commit it was cloned or last updated to until you run
soundpack update. Schedule that yourself if you want it automatic.
Check what is installed:
claudio soundpack status
claudio soundpack status my-pack
Removing A Pack
Managed git packs:
claudio soundpack remove my-pack # delete the clone and registry entry
claudio soundpack remove my-pack --keep-files # drop the registry entry, keep the clone
claudio soundpack remove my-pack --force # drop registry and config entries even if deleting the clone fails
remove also takes the pack out of soundpack_paths, and if it was the
active pack, resets default_soundpack to the platform default.
Packs installed with soundpack install have no remove command. Delete the
directory:
rm -rf "$XDG_DATA_HOME/claudio/soundpacks/my-pack" # adjust for your platform
Hooks skip a soundpack_paths entry that no longer exists. The next
soundpack install, add, remove, or use drops it from config.json and
prints the path it dropped; you can also delete the entry by hand.
If it was the active pack, pick another with claudio soundpack use <name>.
Until you do, Claudio logs an error on each event and uses the platform pack.
Building A Pack
Directory Soundpacks
In a directory pack, each sound key is a file path relative to the pack root:
my-pack/
default.wav
loading/
git-commit-start.wav
git-start.wav
bash-start.wav
loading.wav
success/
git-commit-success.wav
git-success.wav
bash-success.wav
success.wav
error/
git-commit-error.wav
git-error.wav
bash-error.wav
error.wav
interactive/
message-sent.wav
notification.wav
permission-request.wav
interactive.wav
completion/
agent-complete.wav
subagent-complete.wav
completion.wav
system/
session-start.wav
compacting.wav
post-compact.wav
system.wav
Sound keys always end in .wav, but the file does not have to. When the
exact .wav file is missing, Claudio looks for the same name with .mp3,
.aiff, .aif, or .mpeg, so success/success.mp3 answers for
success/success.wav.
One file per category plus default.wav is enough to cover every event.
Add more specific names as you go; Fallback Chains
lists which names Claudio tries for each event.
Validate and install:
claudio soundpack validate ./my-pack
claudio soundpack install ./my-pack --default
install validates the pack, copies it to <XDG_DATA_HOME>/claudio/soundpacks/<name>/,
and adds that path to soundpack_paths. --skip-validate skips the coverage
check; the copied pack is still checked for safety.
Claudio finds packs in the XDG soundpacks/ directory by name. If a
directory there contains soundpack.json, Claudio loads it as a JSON pack;
otherwise it reads the category layout above. A pack anywhere else needs an
entry in soundpack_paths or a full path. Scans skip .git directories.
JSON Soundpacks
A JSON pack maps sound keys to files stored next to the manifest:
{
"name": "system-sounds",
"description": "Small pack using existing local sounds",
"version": "1.0.0",
"mappings": {
"success/success.wav": "./sounds/success.wav",
"error/error.wav": "./sounds/error.mp3",
"loading/loading.wav": "./sounds/loading.wav",
"interactive/message-sent.wav": "./sounds/message-sent.aiff",
"default.wav": "./sounds/default.wav"
}
}
Rules:
nameand at least one entry inmappingsare required.descriptionandversionare optional.- Each value must be a relative path inside the manifest’s directory.
Absolute paths and
..are rejected, and a symlink that points outside the directory is rejected too. - An empty value means the key is not mapped yet; it is skipped.
validateandinstallreject a value whose file does not exist. If a file goes missing after install, Claudio logs a warning, skips that entry, and keeps using the rest of the pack.- A pack can have at most 10,000 mappings.
Create a template:
claudio soundpack init my-pack # writes ./my-pack.json
claudio soundpack init my-pack --dir ./packs # writes ./packs/my-pack.json
claudio soundpack init my-pack --from-platform # pre-fills the current platform pack's mappings
A plain init template lists every known key with an empty value. Fill in
the keys you want; the empty ones are skipped, so you can leave them in or
delete them. validate lists them as unmapped.
Validate and install:
claudio soundpack validate ./my-pack.json
claudio soundpack install ./my-pack.json --default
install copies the manifest and every file it references into
<XDG_DATA_HOME>/claudio/soundpacks/<name>/, keeping relative
subdirectories, writes the manifest there as soundpack.json, and adds it
to soundpack_paths. You can then refer to the pack by its directory name or
its name field.
Validation
claudio soundpack validate ./my-pack.json
claudio soundpack validate ./my-pack
The report shows:
- Coverage of known sound keys, overall and per category
- Broken references (mapped files that do not exist)
- Unsupported file extensions
- Empty mappings
Broken references fail validation. Empty mappings are reported as unmapped but do not fail it.
validate checks that a pack is complete. It does not open the audio. For
that, use audit.
Auditing And Mastering
A pack assembled from many sources has sounds at many levels and lengths. In
one real pack the loudest sound was 37 LU louder than the quietest, two
“sounds” were three-minute ambience loops, and every MP3 began with 20 to 200
ms of silence. audit finds these problems and master fixes them.
claudio soundpack audit ./my-pack
SOUND LENGTH LUFS PEAK HIT PITCH TREND TEXTURE FINDINGS
error/error.mp3 0.94s -29.4 -20.1 3 5663Hz steady tonal too-quiet, leading-silence
loading/git-pull-start.mp3 0.34s -8.4 -0.4 3 1242Hz steady tonal too-loud, peak-over-ceiling, leading-silence
system/session-start.mp3 227.69s -24.4 -7.6 2405 70Hz steady tonal too-long, too-quiet
Audit decodes each file with the decoders playback uses, so a file it accepts is a file Claudio can play.
Every mapped file in a JSON pack is checked regardless of its extension.
Content the playback decoders do not support, such as Ogg Vorbis, produces an
undecodable error instead of being skipped. These errors fail the audit
with or without --strict.
| Column | Meaning |
|---|---|
LENGTH |
Duration of the file, silence included. |
LUFS |
Loudness (ITU-R BS.1770, the measure streaming services normalize to). Sounds under 400 ms are too short for the standard’s gating, so they are measured ungated over their whole length. Mono files are measured as they play: on both speakers. |
PEAK |
True peak in dBTP, estimated by 4x oversampling. |
HIT |
Number of separate bursts: 1 for a single tone, 3 for a triple beep. It counts a new hit only after the level has dropped, so notes played over a held or ringing sound, quiet echoes and tremolo are not counted. |
PITCH |
The note: the lowest strong partial. --json also gives the strongest partial, which can be an overtone. |
TREND |
Whether the sound ends on a higher pitch than it starts on (rising), lower (falling), or neither. For noise, which has no pitch, it is whether the second half is brighter or duller than the first. |
TEXTURE |
tonal, mixed, or noisy. |
The last four columns describe the sound, so you (or an agent that cannot
hear) can tell sounds apart, spot the one file that is not like the others,
and check that errors do not sound like successes. They are instruments
with limits, not a specification. When a sound is right and a column
disagrees for a reason given above, keep the sound and note the reading;
do not thin out a ringing chord so that its notes get counted. --json adds attack
time, spectral centroid, silence at each end, and a hash per file.
What audit warns about, and why:
| Rule | Why it matters |
|---|---|
too-long |
A loading sound plays before every tool call. Past about a second it is still playing when the result sound starts. Limits are per category: loading 1s, success 1.5s, default 1.5s, error 2s, interactive 2.5s, completion 3s, system 6s. A file that answers for several categories gets the strictest. |
too-loud, too-quiet |
More than 1 LU from the -18 LUFS target. One volume setting should suit every sound. |
peak-over-ceiling |
True peak above -1 dBTP distorts on some outputs. |
clipping |
Runs of full-scale samples: the source was recorded or exported too hot. Mastering cannot undo this. |
leading-silence |
More than 15 ms of silence before the sound. The sound feels late. MP3 files nearly always have this, because encoders pad the start. |
trailing-silence |
More than 150 ms of silence after the sound. It keeps the player busy for nothing. |
Notes do not fail an audit. peak-limited marks a sound (usually a click)
that cannot reach the target without exceeding the peak ceiling.
duplicate marks files with identical bytes: in a directory pack that is
the only way to reuse a sound, in a JSON pack map both keys to one file
instead. unreferenced marks audio a JSON pack ships but never maps.
--strict makes warnings fail the command, which is what you want in CI.
--target-lufs, --tolerance, --peak-ceiling, and --max-duration
loading=800ms,system=4s change the standard.
master writes a copy of the pack that passes:
claudio soundpack master ./raw-pack --out ./my-pack
claudio soundpack audit ./my-pack --strict
For each sound it trims silence from both ends, cuts anything over its
category’s limit (with a fade), and applies one gain so the sound sits at the
target without its peak crossing the ceiling. For most sounds that is all:
nothing is compressed, so the sound keeps its shape. A sound that gain alone
leaves short of the target has a few peaks standing far above the rest of
it, which is what a recorded knock or click looks like. master holds just
those peaks down (by at most 9 dB, starting 2 ms ahead of each one) so the
body of the sound can come up, and reports it as peaks limited. You do
not need to add drive to a recipe to make a spiky recording loud enough. Output is 48 kHz 16-bit WAV, mono when
both channels are identical: the player’s own format, so nothing is resampled
at play time and there is no encoder padding.
Sounds reported as truncated lost their end. master keeps the first part
of the sound, which is not always the part worth keeping. For those, cut the
source file yourself and master again.
A Pack Repository
This layout keeps the raw material, records which sound answers for which key, and makes the published pack a build product:
my-pack/
source/
soundpack.json # manifest over the raw files: key -> raw file
raw/*.mp3|wav|aiff # anything Claudio can decode, any length or level
soundpack.json # built: key -> sounds/...wav
sounds/ # built: mastered WAVs
README.md
claudio soundpack master source/soundpack.json --out .
claudio soundpack audit soundpack.json --strict
claudio soundpack validate soundpack.json
The source manifest is an ordinary JSON pack, so it can map many keys to one
raw file. master writes each raw file once however many keys use it, and
soundpack add picks up the soundpack.json at the repository root. Audio
under source/ is not part of the built pack and is not audited with it.
To hold the pack to the standard, run the audit in CI:
# .github/workflows/audit.yml
name: audit
on: [push, pull_request]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: stable
- run: go install claudio.click/cmd/claudio@latest
- run: claudio soundpack validate soundpack.json
- run: claudio soundpack audit soundpack.json --strict
Publishing A Pack
Three conventions make a pack findable and installable by name:
- Name the repository
claudio-soundpack-<name>. - Keep the pack at the repository root:
soundpack.json, or a directory pack’s category folders. -
Add the GitHub topic
claudio-soundpack:gh repo edit --add-topic claudio-soundpack
claudio soundpack search then lists it, and anyone can install it with
claudio soundpack add gh:<owner>/claudio-soundpack-<name> --name <name>.
Put a one-line description on the repository; it is what search shows.
Synthesizing Sounds
You do not need recordings to make a pack. synth renders sounds from a
JSON recipe, so a pack can be written, reviewed and changed as text, and
everything in it is your own work.
{
"name": "my-pack",
"description": "Soft wooden taps",
"version": "1.0.0",
"sounds": {
"tick": {
"about": "one short woody tap",
"layers": [
{"freq": 900, "freq_end": 500, "dur": 0.03, "decay": 0.03, "sustain": 0},
{"wave": "noise", "dur": 0.01, "highpass": 2000, "gain": -12}
]
},
"done": {
"about": "two rising notes with a little room",
"layers": [{"wave": "triangle", "notes": ["C5", "G5"], "step": 0.09, "dur": 0.08, "release": 0.12}],
"effects": [{"type": "reverb", "size": 0.3, "mix": 0.15}]
}
},
"mappings": {
"default.wav": "tick",
"loading/loading.wav": "tick",
"success/success.wav": "done"
}
}
claudio soundpack synth source/recipe.json --out source # source/synth/*.wav + source/soundpack.json
claudio soundpack master source/soundpack.json --out . # soundpack.json + sounds/
claudio soundpack audit soundpack.json --strict
A sound is one or more layers mixed together, then passed through effects in order. Times are in seconds and gains in dB.
| Layer setting | Meaning |
|---|---|
wave |
sine (default), triangle, square, saw, pulse, or noise. |
freq, freq_end |
Pitch in Hz or as a note name ("A4", "C#5", "Bb3"). freq_end glides to a second pitch over dur. |
notes, step |
A sequence instead of one pitch: each note lasts dur and starts step after the last. 0 is a rest. |
at, dur |
When the layer starts, and how long each note is held before its release. |
attack, decay, sustain, release |
The envelope. Defaults: 5 ms attack, no decay, sustain 1, 50 ms release. decay with "sustain": 0 is a pluck. |
gain, pan |
Level in dB; position from -1 (left) to 1 (right). |
harmonics |
Overtone levels for a sine, e.g. [1, 0.5, 0.25]. |
width |
Duty cycle of a pulse wave. |
fm |
{"ratio": 3.5, "index": 4, "index_end": 0}: frequency modulation. Non-integer ratios sound like bells and metal; a falling index sounds struck. |
vibrato, tremolo |
{"rate": 6, "depth": 0.3}. Vibrato depth is in semitones, tremolo depth from 0 to 1. |
voices, detune |
Stacked copies spread over +/- detune cents and across the stereo field. |
lowpass, highpass, q |
Filter cutoffs in Hz and resonance. lowpass_end and highpass_end sweep the cutoff over the note. |
A layer can also play a recording instead of an oscillator:
| Sample setting | Meaning |
|---|---|
sample |
Path to a WAV, MP3 or AIFF file, relative to the recipe. It must stay inside the recipe’s directory. |
start, end |
The slice to play, in seconds into the file. Without end it plays to the end of the file. |
speed |
Plays faster or slower, which moves the pitch too: 2 is an octave up and half as long. To tune a recording to a note, use target Hz divided by its measured Hz. |
reverse |
true plays the slice backwards. |
dur |
Optional. Leave it out to play the whole slice; set it to stop a long ring early, with release as the fade. |
A sample layer takes gain, pan, tremolo, the envelope and the filters,
mixes with oscillator layers in the same sound, and goes through the sound’s
effects. It has no attack and a 10 ms release unless you set them.
Effect type |
Settings |
|---|---|
reverb |
size (0 to 1), damp, mix |
delay |
time, feedback, mix |
drive |
amount (0 to 1) |
bitcrush |
bits, downsample |
lowpass, highpass |
freq, q |
about is a note to yourself about what the sound should be. It is not
rendered, but synth prints it beside each sound, and it is what you check
the audit’s HIT, PITCH and TREND columns against: a sound described as
“three falling notes” should audit as 3 hits, falling.
Rendering is deterministic, and a setting synth does not know is an error
rather than something it ignores.
Some things that hold across packs:
- Give each category a family resemblance and each sound in it a difference. Success rises or resolves, error falls or stays dissonant, loading is short and neutral.
- The sounds that fire most (
default.wav,loading/loading.wav,loading/bash-start.wav,success/success.wav) should be the shortest and plainest. Save the flourish forcompletion/agent-complete.wavandsystem/session-start.wav. - A reverb or delay tail counts toward a sound’s length. A loading sound has one second in total.
Building From Recordings
Most good packs start from recordings. The process:
- Download raw material into
source/raw/<collection>/. Keep the collection name in the path so it stays obvious where a file came from. -
Record where each file came from in
source/sources.jsonas you go, not afterwards:{ "sources": [ { "file": "raw/kenney/impact-sounds/impactWood_medium_000.wav", "title": "impactWood_medium_000", "author": "Kenney", "source": "https://kenney.nl/assets/impact-sounds", "license": "CC0 1.0", "license_url": "https://creativecommons.org/publicdomain/zero/1.0/" } ] }A file whose licence you cannot establish does not go in a pack you publish. Credit every author in the README; CC BY requires it.
- Find the sounds by measuring:
claudio soundpack audit source/raw/<collection>prints length, hits, pitch, trend and texture for every file. Ignore the warnings; raw material is not mastered yet. - Use them from the recipe as sample layers. Every cut, repitch and
fade is then written down, and the pack rebuilds from
source/recipe.jsonandsource/raw/. - Build and audit as for any pack:
synth,master,audit --strict.
Where to get recordings you may redistribute:
| Source | Licence | Notes |
|---|---|---|
| Kenney | CC0 | Designed interface, impact, sci-fi and game sounds, downloadable as zip files. OGG: convert with ffmpeg -i in.ogg out.wav. |
| Wikimedia Commons | Per file | Real-world recordings. The API returns each file’s licence and author, so a search can be filtered to public domain, CC0 and CC BY (see below). |
| Freesound | Per file | The largest library. Search and download need an API key; filter on license:"Creative Commons 0". |
| BigSoundBank | CC0 | Real-world recordings. The site blocks automated clients, so download by hand. |
Searching Commons for audio with its licence and author:
curl -s -A "my-pack-tooling/1.0 (https://example.com/contact)" --get \
"https://commons.wikimedia.org/w/api.php" \
--data-urlencode "action=query" --data-urlencode "format=json" \
--data-urlencode "generator=search" --data-urlencode "gsrnamespace=6" \
--data-urlencode "gsrsearch=filetype:audio singing bowl" \
--data-urlencode "prop=imageinfo" \
--data-urlencode "iiprop=url|size|extmetadata" \
--data-urlencode "iiextmetadatafilter=LicenseShortName|Artist|LicenseUrl"
Keep the response beside the downloads: it is your provenance record.
Commons asks for a descriptive User-Agent and rate-limits bulk
downloads: fetch one file every few seconds, and check that what you saved
is audio, because a throttled request returns an HTML error page with the
file’s name on it. Search results are loose (a search for “ratchet” also
returns pronunciations and songs), so choose by title and by measuring.
Sounds from films, television and games are copyrighted however they reach
you. A pack built from them is yours to use; whether to publish it is a
decision to make knowingly, and sources.json should say plainly where
each clip came from.
Choosing What To Cut
master handles level and silence. Deciding which two seconds of a long
recording to keep needs a look at the sound. If you cannot listen (or you
are an agent), render a spectrogram and read it as a picture:
ffmpeg -i source/raw/ambience.mp3 \
-lavfi "showspectrumpic=s=1200x300:scale=log:fscale=log" ambience.png
Time runs left to right and pitch bottom to top. Beeps show as short bright
bars, hum as a band along the bottom, silence as black. Pick the window that
holds the event you want, then cut it into source/ and point the source
manifest at the cut:
ffmpeg -ss 21.7 -t 5.8 -i ambience.mp3 \
-af "afade=t=in:d=0.15,afade=t=out:st=5.2:d=0.6" source/raw/session-start.wav
After mastering, run audit again and read the HIT, PITCH and TREND
columns to confirm the cut contains what you meant it to.
Using Tracking To Improve A Pack
Sound tracking is on by default. Use Claudio for a while, then list the keys it looked for and did not find:
claudio analyze missing --preset all-time --limit 50
The most frequent missing keys are usually the best sounds to add next.
How Sound Selection Works
Fallback Chains
For each event Claudio builds a list of candidate keys, from most specific to least specific, and plays the first one the pack has. Duplicate candidates are dropped.
PreToolUse
git commit run through the Bash tool:
loading/git-commit-start.wav
loading/git-commit.wav
loading/git-start.wav
loading/git.wav
loading/bash-start.wav
loading/bash.wav
loading/tool-start.wav
loading/loading.wav
default.wav
PostToolUse
A successful git commit:
success/git-commit-success.wav
success/git-success.wav
success/bash-success.wav
success/tool-complete.wav
success/success.wav
default.wav
A failed one uses the error/ category:
error/git-commit-error.wav
error/git-error.wav
error/bash-error.wav
error/tool-complete.wav
error/error.wav
default.wav
The post-tool chain skips the bare command key (success/git.wav), so a
generic command sound cannot stand in for a specific result.
Other Events
Events without a tool use a short chain: a specific key, an event key, the
category sound, and default.wav.
| Event | Keys tried before the category sound |
|---|---|
UserPromptSubmit |
interactive/message-sent.wav, interactive/prompt-submit.wav |
Notification |
interactive/notification.wav |
PermissionRequest |
interactive/permission-request.wav |
Stop |
completion/agent-complete.wav, completion/stop.wav |
SubagentStop |
completion/subagent-complete.wav, completion/subagent-stop.wav |
SubagentStart |
loading/subagent-start.wav |
SessionStart |
system/session-start.wav |
PreCompact |
system/compacting.wav, system/pre-compact.wav |
PostCompact |
system/post-compact.wav |
For example, Stop tries completion/agent-complete.wav,
completion/stop.wav, completion/completion.wav, then default.wav.
Command Parsing
For Bash tool events, Claudio parses the command string and recognizes the subcommands of:
gitnpmdockercargogopipyarnkubectl
For other commands, Claudio still tries command-level keys such as
loading/systemctl-start.wav, and treats the second word as a subcommand
(loading/systemctl-restart-start.wav) when it looks like one rather than a
file path, flag, or URL.
MCP Tools
MCP tools (names beginning with mcp__) first try the shared mcp keys,
then the full normalized tool name. For mcp__github__create_issue at
PreToolUse:
loading/mcp-start.wav
loading/mcp.wav
loading/mcp-github-create-issue-start.wav
loading/mcp-github-create-issue.wav
loading/tool-start.wav
loading/loading.wav
default.wav