AI-operated audio notification system for Claude Code.
You type one slash command at install time. Then natural language forever.
26 hook events, 2 audio themes, rate-limit alerts, webhooks, TTS, context monitor β all operated by Claude Code on your behalf.
Share This Project
promo-video.mp4
Built with Remotion, Claude Code, ElevenLabs & Suno. Source: claude-code-audio-hooks-promo-video
Table of Contents
v5.0 β AI-first redesign (click to expand)
v5.0 is an AI-first redesign. Every project surface is now machine-operable end-to-end so Claude Code can install, configure, snooze, troubleshoot, and upgrade the project on a human's behalf without any clicks, prompts, or doc reading.
| Highlight | Effect |
|---|---|
audio-hooks JSON CLI |
Single binary with 27 subcommands. JSON to stdout, stable error codes + suggested commands. |
/audio-hooks SKILL |
Natural-language activation: "snooze audio for an hour" β Claude runs it for you. |
| NDJSON structured logging | Schema audio-hooks.v1 with stable error code enums. |
| Plugin-native install | Two commands and you're done. |
| 4 new hook events | PermissionDenied, CwdChanged, FileChanged, TaskCreated β 26 total. |
| Native matcher routing | hooks.json registers per-matcher handlers with unique audio per variant. |
| Rate-limit alerts | One-shot warning at 80%/95% of your 5h or 7d quota. |
| TTS speak Claude's reply | Instead of "Task completed", TTS speaks Claude's actual final message. |
| Status line with context monitor | Color-coded Context and API Quota bars with /compact reminders. |
| ElevenLabs audio generator | One-line manifest edit + one-command rebuild for new audio. |
Plugin Installed β 26 hooks registered |
/audio-hooks SKILL active |
Context monitor status line |
Marketplace registration |
See CHANGELOG.md for full details.
For 99% of operations, you just talk to Claude Code in plain English. The exception is the one-time install: /reload-plugins has no CLI equivalent, so the human types it exactly once. Everything else β configure, snooze, theme, webhook, troubleshoot, uninstall β is pure natural language.
claudePaste this into Claude Code:
Please install the audio-hooks plugin from
github.com/ChanMeng666/claude-code-audio-hooks. Use the Bash tool to runclaude plugin marketplace add ChanMeng666/claude-code-audio-hooksthenclaude plugin install audio-hooks@chanmeng-audio-hooks. After both commands complete, tell me to type/reload-pluginsto activate the plugin.
/reload-plugins
Verify audio-hooks works by running
audio-hooks diagnoseandaudio-hooks test all. Then switch to the chime audio theme.
Total: 1 shell command + 2 natural-language prompts + 1 slash command = 4 things. From here on: natural language forever.
Install flow diagram
sequenceDiagram
participant Human
participant Terminal
participant Claude as Claude Code
participant Bash as Bash tool
participant Skill as /audio-hooks SKILL
participant CLI as audio-hooks CLI
Human->>Terminal: type `claude` to start a session
Human->>Claude: "install audio-hooks plugin from<br/>github.com/ChanMeng666/claude-code-audio-hooks via<br/>`claude plugin marketplace add` and `claude plugin install`"
Claude->>Bash: claude plugin marketplace add ChanMeng666/claude-code-audio-hooks
Bash-->>Claude: "Successfully added marketplace"
Claude->>Bash: claude plugin install audio-hooks@chanmeng-audio-hooks
Bash-->>Claude: "Installed audio-hooks. Run /reload-plugins to apply."
Claude-->>Human: "Plugin installed.<br/>Type /reload-plugins to activate it."
rect rgb(255, 230, 200)
Note over Human: The one manual slash command in the whole flow
Human->>Claude: /reload-plugins
Claude-->>Human: "Reloaded: 8 plugins, 37 hooks, 5 skills"
end
Human->>Claude: "verify audio-hooks works and switch to chime audio"
Claude->>Skill: SKILL activates on intent
Claude->>Bash: audio-hooks diagnose
Bash-->>Claude: {"ok":true,"errors":[],"warnings":[]}
Claude->>Bash: audio-hooks test all
Bash-->>Claude: {"ok":true,"passed":6,"failed":0}
Claude->>Bash: audio-hooks theme set custom
Bash-->>Claude: {"ok":true,"theme":"custom"}
Claude-->>Human: "Done. 26 hooks active, all tests passed,<br/>audio theme set to chimes."
Note over Human,CLI: From here on: pure natural language forever.
Once installed, you operate the project the same way β just talk to Claude Code. Every configuration is a single message:
sequenceDiagram
actor You as You
participant CC as Claude Code
rect rgb(219, 234, 254)
Note over You,CC: Audio Theme
You->>CC: Switch audio-hooks to the chime theme.
CC-->>You: audio-hooks theme set custom β switched to chimes.
You->>CC: Switch audio-hooks to the voice theme.
CC-->>You: audio-hooks theme set default β switched to ElevenLabs Jessica.
end
rect rgb(220, 252, 231)
Note over You,CC: Snooze & Mute
You->>CC: Snooze audio for 30 minutes.
CC-->>You: audio-hooks snooze 30m β muted until 3:45 PM.
You->>CC: Snooze audio for 8 hours.
CC-->>You: audio-hooks snooze 8h β quiet for the rest of the day.
You->>CC: Unmute audio.
CC-->>You: audio-hooks snooze off β audio resumed.
You->>CC: Is audio currently muted?
CC-->>You: audio-hooks snooze status β not snoozed.
end
rect rgb(254, 243, 199)
Note over You,CC: Hook Selection & Notification Mode
You->>CC: Configure audio-hooks to only fire on stop,<br/>notification, and permission_request β<br/>disable everything else.
CC-->>You: audio-hooks hooks enable-only stop notification<br/>permission_request β 3 hooks active, rest disabled.
You->>CC: Enable session_start and session_end hooks<br/>so I hear when sessions begin and end.
CC-->>You: session_start and session_end enabled.
You->>CC: Switch audio-hooks to audio-only mode,<br/>no desktop popups.
CC-->>You: Notification mode set to audio_only.
You->>CC: Switch to notification-only mode β<br/>desktop popups but no audio.
CC-->>You: Notification mode set to notification_only.
You->>CC: For the stop hook only, use desktop<br/>notification without audio.
CC-->>You: Per-hook override: stop β notification_only.
You->>CC: Make notifications more detailed.
CC-->>You: Detail level set to verbose.
end
sequenceDiagram
actor You as You
participant CC as Claude Code
rect rgb(237, 233, 254)
Note over You,CC: Webhooks & Integrations
You->>CC: Send audio-hooks alerts to my Slack webhook<br/>at https://hooks.slack.com/services/... and test it.
CC-->>You: Webhook set to slack format. Test delivered.
You->>CC: Send alerts to my Discord webhook instead.
CC-->>You: Webhook set to discord format. Test delivered.
You->>CC: Send alerts to ntfy at<br/>https://ntfy.sh/my-channel. Test it.
CC-->>You: Webhook set to ntfy format. Test delivered.
You->>CC: Only send stop and stop_failure events<br/>to the webhook, nothing else.
CC-->>You: Webhook hook_types set to [stop, stop_failure].
end
rect rgb(254, 226, 226)
Note over You,CC: TTS & Rate Limits
You->>CC: Enable audio-hooks TTS and have it speak<br/>Claude's actual final message instead of<br/>a generic announcement.
CC-->>You: TTS enabled with speak_assistant_message = true.
You->>CC: Set the stop hook TTS message to<br/>"Build finished" instead of the default.
CC-->>You: Custom TTS message for stop set.
You->>CC: Make sure audio-hooks rate-limit alerts are<br/>enabled with 80% and 95% thresholds for both<br/>5-hour and 7-day windows.
CC-->>You: Rate-limit alerts on β 80%, 95% for both windows.
end
rect rgb(207, 250, 254)
Note over You,CC: Status Line & Context Monitor
You->>CC: Install the audio-hooks status line<br/>in my Claude Code settings.
CC-->>You: audio-hooks statusline install β restart to see it.
You->>CC: Configure the status line to only show<br/>context usage.
CC-->>You: Visible segments set to [context].
You->>CC: Show only context and API quota<br/>in the status line.
CC-->>You: Visible segments set to [context, api_quota].
You->>CC: Reset the status line to show all segments.
CC-->>You: Visible segments reset to all.
end
rect rgb(232, 245, 233)
Note over You,CC: Focus Flow
You->>CC: Enable the audio-hooks focus flow<br/>with breathing exercises.
CC-->>You: Focus flow enabled β 4-7-8 breathing.
You->>CC: Switch focus flow to hydration reminders.
CC-->>You: Focus flow mode set to hydration.
You->>CC: Only show focus flow if Claude thinks<br/>for more than 30 seconds.
CC-->>You: min_thinking_seconds set to 30.
end
rect rgb(229, 231, 235)
Note over You,CC: Monitor, Debug & Uninstall
You->>CC: Enable the audio-hooks file_changed hook and<br/>configure it to watch .env and .envrc.
CC-->>You: file_changed enabled, watching [.env, .envrc].
You->>CC: Test all my audio-hooks hooks and tell me<br/>if any failed.
CC-->>You: audio-hooks test all β 26/26 passed.
You->>CC: What's the current state of audio-hooks?
CC-->>You: audio-hooks status β theme: default,<br/>18 hooks enabled, 0 errors.
You->>CC: Show me the last 20 errors and clear the log.
CC-->>You: 2 errors found (WEBHOOK_TIMEOUT). Log cleared.
You->>CC: What version of audio-hooks am I running?
CC-->>You: v5.1.1, plugin install.
You->>CC: Please uninstall audio-hooks completely.
CC-->>You: Plugin uninstalled. All hooks removed.
end
Each prompt is one message. Claude Code parses it, runs the right subcommand(s), and reports back. You don't memorise anything.
Plain-text prompt reference β copy-friendly table
| Goal | Paste this into Claude Code |
|---|---|
| Audio Theme | |
| Switch to chime sounds | "Switch audio-hooks to the chime theme." |
| Switch to voice sounds | "Switch audio-hooks to the voice theme." |
| Snooze & Mute | |
| Mute for 30 minutes | "Snooze audio for 30 minutes." |
| Mute for the rest of the day | "Snooze audio for 8 hours." |
| Unmute | "Unmute audio." |
| Check mute status | "Is audio-hooks currently muted?" |
| Hook Selection | |
| Only keep critical alerts | "Only fire audio-hooks on stop, notification, and permission_request. Disable everything else." |
| Enable session start/end sounds | "Enable the session_start and session_end hooks." |
| Enable tool execution sounds | "Enable pretooluse and posttooluse audio." |
| Notification Mode | |
| Audio only, no desktop popups | "Switch audio-hooks to audio-only mode." |
| Desktop popups only, no audio | "Switch audio-hooks to notification-only mode." |
| Per-hook override | "For the stop hook, use desktop notification without audio." |
| Make notifications verbose | "Make audio-hooks notifications more detailed." |
| Disable all notifications | "Disable all audio-hooks notifications entirely." |
| Focus Flow | |
| Breathing exercises | "Enable the audio-hooks focus flow with breathing exercises." |
| Hydration reminders | "Switch audio-hooks focus flow to hydration reminders." |
| Custom URL during thinking | "Set audio-hooks focus flow to open https://example.com during thinking." |
| Longer thinking delay | "Only show focus flow if Claude thinks for more than 30 seconds." |
| Webhooks | |
| Send alerts to Slack | "Send audio-hooks alerts to my Slack webhook at https://hooks.slack.com/services/... and test it." |
| Send alerts to Discord | "Send audio-hooks alerts to my Discord webhook at https://discord.com/api/webhooks/... and test it." |
| Send alerts to Teams | "Send audio-hooks alerts to my Teams webhook. Test it." |
| Send alerts to ntfy | "Send audio-hooks alerts to https://ntfy.sh/my-topic in ntfy format. Test it." |
| Only webhook certain events | "Only send stop and stop_failure events to the webhook." |
| Disable webhook | "Disable the audio-hooks webhook." |
| TTS (Text-to-Speech) | |
| Speak Claude's reply out loud | "Enable audio-hooks TTS and speak Claude's actual final message." |
| Custom TTS message for a hook | "Set the audio-hooks stop TTS message to 'Build finished'." |
| Limit spoken message length | "Limit audio-hooks TTS to 300 characters." |
| Rate-limit Alerts | |
| Enable with custom thresholds | "Enable audio-hooks rate-limit alerts at 80% and 95% for both windows." |
| Adjust 5-hour thresholds | "Set audio-hooks 5-hour rate-limit thresholds to 75% and 90%." |
| Status Line | |
| Add a status bar | "Install the audio-hooks status line." |
| Status bar: context only | "Only show context usage in the audio-hooks status line." |
| Status bar: context + API quota | "Show context and API quota in the audio-hooks status line." |
| Status bar: show everything | "Reset the audio-hooks status line to show all segments." |
| Remove status bar | "Uninstall the audio-hooks status line." |
| File Watching | |
| Watch .env for changes | "Enable the audio-hooks file_changed hook and watch .env and .envrc." |
| Monitor & Debug | |
| Test all hooks | "Test all audio-hooks and tell me if any failed." |
| Show current state | "Show the current audio-hooks status β enabled hooks, theme, and recent errors." |
| Why no sound? | "Audio-hooks isn't playing sounds. Diagnose and fix it." |
| Show recent errors | "Show me the last 20 audio-hooks errors." |
| Clear the log | "Clear the audio-hooks event log." |
| Check version | "What version of audio-hooks am I running?" |
| Adjust debounce timing | "Set audio-hooks debounce to 1000ms." |
| Uninstall | |
| Uninstall | "Please uninstall audio-hooks completely." |
flowchart LR
CC[Claude Code event] -->|stdin JSON| MR{native matcher<br/>routing}
MR -->|session_start_resume| HR[hook_runner.py]
MR -->|stop_failure_rate_limit| HR
MR -->|notification_idle_prompt| HR
MR -->|...| HR
HR -->|reads| RL[rate-limit pre-check<br/>marker debounce]
HR -->|reads| CFG[user_preferences.json]
HR -->|reads| MARK[snooze + focus-flow markers]
HR -->|fires| AUDIO[Audio playback<br/>26 MP3s, 2 themes]
HR -->|fires| NOTIF[Desktop notification]
HR -->|fires| TTS[TTS announcement]
HR -->|fires| WH[Webhook subprocess<br/>fire-and-forget]
HR -->|writes| LOG[(NDJSON event log<br/>schema audio-hooks.v1)]
style CC fill:#4A90E2,color:#fff
style HR fill:#7ED321,color:#000
style RL fill:#F5A623,color:#000
style AUDIO fill:#F5A623,color:#000
style WH fill:#9013FE,color:#fff
style LOG fill:#50E3C2,color:#000
Claude Code fires hook events as JSON on stdin. Native matchers in hooks.json route each event to hook_runner.py with a synthetic event name. The runner checks snooze state, rate-limit thresholds, debounce, and user filters β then fires audio playback, desktop notifications, TTS, and webhooks as configured.
Β Β AI Control Surfaceflowchart TB
USER[Human] -->|natural language| CLAUDE[Claude Code]
CLAUDE -->|activates| SKILL[/audio-hooks SKILL/]
SKILL -->|invokes via Bash tool| BIN[bin/audio-hooks]
BIN -->|reads| CONFIG[(user_preferences.json<br/>in plugin data dir)]
BIN -->|reads| MARKERS[(snooze + focus-flow markers)]
BIN -->|reads| LOGS[(NDJSON event log)]
BIN -->|writes| CONFIG
BIN -->|writes| MARKERS
BIN -->|invokes| HR[hook_runner.run_hook<br/>for `audio-hooks test`]
BIN -->|JSON to stdout| CLAUDE
CLAUDE -->|reports back| USER
style USER fill:#4A90E2,color:#fff
style CLAUDE fill:#9013FE,color:#fff
style SKILL fill:#7ED321,color:#000
style BIN fill:#F5A623,color:#000
|
Β Β Hook Lifecycleflowchart TD
EVT[Hook event fires<br/>e.g. Stop] --> SNOOZE{snooze<br/>active?}
SNOOZE -->|yes| EXIT0[exit 0 silent]
SNOOZE -->|no| RL{rate_limits<br/>in stdin?}
RL -->|yes| RLCHK{crossed<br/>threshold?}
RLCHK -->|yes| RLAUDIO[play warning audio<br/>+ write debounce marker]
RLCHK -->|no| DEB
RL -->|no| DEB{debounced<br/>recently?}
RLAUDIO --> DEB
DEB -->|yes| EXIT0
DEB -->|no| FILTER{user filter<br/>matches?}
FILTER -->|yes, exclude| EXIT0
FILTER -->|no| ENABLED{hook<br/>enabled?}
ENABLED -->|no| EXIT0
ENABLED -->|yes| FIRE[play audio + notif + TTS + webhook]
FIRE --> LOG[write NDJSON event]
style EVT fill:#4A90E2,color:#fff
style FIRE fill:#7ED321,color:#000
style RLAUDIO fill:#F5A623,color:#000
style EXIT0 fill:#999,color:#fff
|
Β Β Plugin Layoutflowchart TB
REPO[claude-code-audio-hooks/]
REPO --> CP[.claude-plugin/marketplace.json]
REPO --> PLUGINS[plugins/audio-hooks/]
REPO --> CANON[CANONICAL SOURCE]
PLUGINS --> P_MANIFEST[.claude-plugin/plugin.json]
PLUGINS --> P_HOOKS[hooks/hooks.json<br/>matcher-scoped]
PLUGINS --> P_RUNNER[runner/run.py]
PLUGINS --> P_SKILL[skills/audio-hooks/SKILL.md]
PLUGINS --> P_BIN[bin/ β audio-hooks + statusline]
PLUGINS --> P_AUDIO[audio/ β bundled MP3s]
PLUGINS --> P_CONFIG[config/default_preferences.json]
CANON --> C_HOOKS[hooks/hook_runner.py]
CANON --> C_BIN[bin/audio-hooks + audio-hooks.py + .cmd]
CANON --> C_AUDIO[audio/default + audio/custom]
CANON --> C_CONFIG[config/]
CANON --> C_SCRIPTS[scripts/ β install + build-plugin + uninstall]
C_HOOKS -.->|build-plugin.sh syncs| P_HOOKS
C_BIN -.->|build-plugin.sh syncs| P_BIN
C_AUDIO -.->|build-plugin.sh syncs| P_AUDIO
style REPO fill:#4A90E2,color:#fff
style PLUGINS fill:#7ED321,color:#000
style CANON fill:#F5A623,color:#000
|
Real-time context window and API quota bars β color-coded warnings before Claude enters the "agent dumb zone".
[Opus] Audio Hooks v5.1.1 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[MUTED 23m] feat/audio-v5 API Quota: 78% Context: 65% /compact
| Color | Range | Meaning | Action |
|---|---|---|---|
| Green | < 50% | Safe β agent performs well | Keep working |
| Yellow | 50-80% | Caution β entering the "dumb zone" | Type /compact or /clear |
| Red | > 80% | Danger β agent makes frequent errors | Type /compact immediately |
10 customisable segments
| Segment | Shows |
|---|---|
model |
Model name (e.g. [Opus]) |
version |
Audio Hooks version |
sounds |
Enabled sound count |
webhook |
Webhook status |
theme |
Audio theme |
snooze |
Mute countdown (when active) |
focus |
Focus Flow mode (when active) |
branch |
Git branch name |
api_quota |
API usage quota bar |
context |
Context window usage bar |
| Theme | Style | Source |
|---|---|---|
default |
ElevenLabs Jessica voice β short spoken phrases like "Task completed" | audio/default/*.mp3 |
custom |
Modern UI sound effects (chimes, beeps) | audio/custom/chime-*.mp3 |
Say "switch to chimes" or "switch to voice" β Claude Code handles the rest.
26 events covering the full Claude Code lifecycle β from session start to file changes, permission requests to rate-limit warnings. 6 are enabled by default; toggle any with natural language.
Full hook events table
| Hook | Default | Audio file | Native matchers |
|---|---|---|---|
notification |
on | notification-urgent.mp3 | permission_prompt / idle_prompt / auth_success / elicitation_dialog |
stop |
on | task-complete.mp3 | |
subagent_stop |
on | subagent-complete.mp3 | agent type |
permission_request |
on | permission-request.mp3 | tool name |
permission_denied |
on | permission-denied.mp3 | |
task_created |
on | task-created.mp3 | |
task_completed |
team-task-done.mp3 | ||
session_start |
session-start.mp3 | startup / resume / clear / compact |
|
session_end |
session-end.mp3 | clear / resume / logout / prompt_input_exit |
|
pretooluse |
task-starting.mp3 | tool name | |
posttooluse |
task-progress.mp3 | tool name | |
posttoolusefailure |
tool-failed.mp3 | tool name | |
userpromptsubmit |
prompt-received.mp3 | ||
subagent_start |
subagent-start.mp3 | agent type | |
precompact / postcompact |
notification-info.mp3 / post-compact.mp3 | manual / auto |
|
stop_failure |
stop-failure.mp3 | rate_limit / authentication_failed / billing_error / server_error / unknown |
|
teammate_idle |
teammate-idle.mp3 | ||
config_change |
config-change.mp3 | ||
instructions_loaded |
instructions-loaded.mp3 | ||
worktree_create / worktree_remove |
worktree-create.mp3 / worktree-remove.mp3 | ||
elicitation / elicitation_result |
elicitation.mp3 / elicitation-result.mp3 | ||
cwd_changed |
cwd-changed.mp3 | ||
file_changed |
file-changed.mp3 | literal filenames |
Fan out hook events to Slack, Discord, Teams, ntfy, or any HTTP endpoint. Versioned audio-hooks.webhook.v1 payload. Fire-and-forget via subprocess β never blocks the hook. Say "send alerts to my Slack" and Claude Code sets it up.
Watches every hook's stdin for rate_limits and plays a one-shot warning at configurable thresholds (default 80%/95%). Each (window, threshold, resets_at) fires exactly once β warned at 80%, again at 95%, never spammed.
Instead of a static "Task completed", TTS speaks Claude's actual final message (truncated to 200 chars). Off by default β privacy-conscious. Say "speak Claude's actual reply when done" to enable.
Anti-distraction micro-task during Claude's thinking time: guided breathing exercise, hydration reminder, custom URL, or shell command. Auto-closes when Claude finishes. Say "enable focus flow with breathing exercises".
CLI, configuration, environment variables, error codes, logging, manual install (click to expand)
Single Python binary on PATH. JSON output, no prompts, no spinners.
| Subcommand | Purpose |
|---|---|
audio-hooks manifest |
Canonical introspection β every subcommand, hook, config key, error code, env var |
audio-hooks manifest --schema |
JSON Schema for user_preferences.json |
audio-hooks status |
Full state snapshot |
audio-hooks version |
Version + install mode detection |
audio-hooks get <dotted.key> |
Read any config key |
audio-hooks set <dotted.key> <value> |
Write any config key (auto-coerces) |
audio-hooks hooks list |
All 26 hooks with current state |
audio-hooks hooks enable/disable <name> |
Toggle a hook |
audio-hooks hooks enable-only <a> <b> |
Exclusive enable |
audio-hooks theme list/set <name> |
Audio theme |
audio-hooks snooze [duration]/off/status |
Mute hooks (default 30m) |
audio-hooks webhook/set/clear/test |
Webhook config + test |
audio-hooks tts set ... |
TTS config |
audio-hooks rate-limits set ... |
Rate-limit alert thresholds |
audio-hooks test <hook|all> |
Smoke-test hooks |
audio-hooks diagnose |
System check |
audio-hooks logs tail/clear |
NDJSON event log |
audio-hooks install/uninstall |
Non-interactive install/uninstall |
audio-hooks statusline show/install/uninstall |
Status line management |
| Key | Type | Default | Effect |
|---|---|---|---|
audio_theme |
default | custom |
default |
Voice recordings vs chimes |
enabled_hooks.<hook> |
bool | varies | Per-hook toggle |
playback_settings.debounce_ms |
int | 500 | Min ms between same hook firing |
notification_settings.mode |
enum | audio_and_notification |
audio_only / notification_only / audio_and_notification / disabled |
notification_settings.detail_level |
enum | standard |
minimal / standard / verbose |
webhook_settings.enabled |
bool | false |
Webhook fan-out |
webhook_settings.url |
string | "" |
Target URL |
webhook_settings.format |
enum | raw |
slack / discord / teams / ntfy / raw |
webhook_settings.hook_types |
array | ["stop","notification",...] |
Which hooks fire the webhook |
tts_settings.enabled |
bool | false |
TTS announcements |
tts_settings.speak_assistant_message |
bool | false |
TTS Claude's actual reply on stop |
tts_settings.assistant_message_max_chars |
int | 200 | Truncation cap |
rate_limit_alerts.enabled |
bool | true |
Watch stdin rate_limits |
rate_limit_alerts.five_hour_thresholds |
int[] | [80, 95] |
5h window thresholds |
rate_limit_alerts.seven_day_thresholds |
int[] | [80, 95] |
7d window thresholds |
focus_flow.enabled / mode / min_thinking_seconds / breathing_pattern |
mixed | off / breathing / 15 / 4-7-8 |
Anti-distraction micro-task |
statusline_settings.visible_segments |
string[] | [] (all) |
Status line segments to show |
| Variable | Purpose |
|---|---|
CLAUDE_PLUGIN_DATA |
Plugin install state directory (auto-set by Claude Code) |
CLAUDE_PLUGIN_ROOT |
Plugin install root (auto-set) |
CLAUDE_AUDIO_HOOKS_DATA |
Explicit override for state directory |
CLAUDE_AUDIO_HOOKS_PROJECT |
Explicit override for project root |
CLAUDE_HOOKS_DEBUG |
1 to write debug-level events to NDJSON log |
CLAUDE_NONINTERACTIVE |
1 to force scripts into non-interactive mode |
ELEVENLABS_API_KEY |
Used by scripts/generate-audio.py (never logged) |
| Code | When | Suggested fix |
|---|---|---|
AUDIO_FILE_MISSING |
Audio file doesn't exist | audio-hooks diagnose |
AUDIO_PLAYER_NOT_FOUND |
No audio player binary | audio-hooks diagnose |
AUDIO_PLAY_FAILED |
Player exited with error | audio-hooks test |
INVALID_CONFIG |
user_preferences.json malformed |
audio-hooks manifest --schema |
CONFIG_READ_ERROR |
Can't read config | audio-hooks status |
WEBHOOK_HTTP_ERROR |
Webhook returned non-2xx | audio-hooks webhook test |
WEBHOOK_TIMEOUT |
Webhook timed out | audio-hooks webhook test |
NOTIFICATION_FAILED |
Desktop notification failed | audio-hooks diagnose |
TTS_FAILED |
TTS engine failed | audio-hooks tts set --enabled false |
SETTINGS_DISABLE_ALL_HOOKS |
disableAllHooks: true in settings |
audio-hooks diagnose |
DUAL_INSTALL_DETECTED |
Both install methods active | bash scripts/uninstall.sh --yes |
PROJECT_DIR_NOT_FOUND |
Can't locate project | audio-hooks status |
UNKNOWN_HOOK_TYPE |
Unrecognised hook name | audio-hooks hooks list |
INTERNAL_ERROR |
Unexpected error | audio-hooks logs tail |
Every event is one JSON object per line at ${CLAUDE_PLUGIN_DATA}/logs/events.ndjson. Schema audio-hooks.v1.
{"ts":"2026-04-11T10:23:45.123Z","schema":"audio-hooks.v1","level":"info","hook":"stop","session_id":"abc","action":"play_audio","audio_file":"chime-task-complete.mp3","duration_ms":42}Levels: debug, info, warn, error. Log rotation: 5 MB cap, 3 files kept.
Plugin install (two slash commands inside Claude Code):
/plugin marketplace add ChanMeng666/claude-code-audio-hooks
/plugin install audio-hooks@chanmeng-audio-hooks
/reload-plugins
Legacy script install (pre-v5.0, still works):
git clone https://github.com/ChanMeng666/claude-code-audio-hooks.git
cd claude-code-audio-hooks
bash scripts/install-complete.sh # auto non-interactive on non-TTYBoth paths share the same hook_runner.py and audio-hooks CLI. They are mutually exclusive β audio-hooks diagnose reports DUAL_INSTALL_DETECTED if both are active.
scripts/generate-audio.py reads config/audio_manifest.json and regenerates audio via the ElevenLabs API:
ELEVENLABS_API_KEY=sk_... python scripts/generate-audio.py # generate missing
ELEVENLABS_API_KEY=sk_... python scripts/generate-audio.py --force # regenerate all
python scripts/generate-audio.py --dry-run # previewTo add a new audio file: edit config/audio_manifest.json, run the generator, then bash scripts/build-plugin.sh.
| Platform | Audio player | Status |
|---|---|---|
| Windows (PowerShell / Git Bash / WSL2) | PowerShell MediaPlayer | Fully supported |
| macOS | afplay |
Fully supported |
| Linux | mpg123 / ffplay / paplay / aplay (auto-detected) |
Fully supported |
Python 3.6+ is the only runtime requirement.
Β Β No sound at allRun |
Β Β Hearing double soundsBoth legacy script install and plugin install are active. Diagnose reports |
Β Β Plugin won't installRun |
Β Β pretooluse / posttooluse too noisyThey fire on every tool execution (Read, Glob, Grep, etc.) β disabled by default for this reason. Enable explicitly with "enable pretooluse and posttooluse audio". |
Plugin install: say "uninstall audio-hooks" or manually:
/plugin uninstall audio-hooks@chanmeng-audio-hooks
Legacy script install:
bash scripts/uninstall.sh --yes # preserve config + audio
bash scripts/uninstall.sh --yes --purge # remove everythingRepository layout, workflow, and contribution guide (click to expand)
claude-code-audio-hooks/
βββ .claude-plugin/marketplace.json
βββ plugins/audio-hooks/ # plugin layout (populated by build-plugin.sh)
β βββ .claude-plugin/plugin.json
β βββ hooks/hooks.json
β βββ runner/run.py
β βββ skills/audio-hooks/SKILL.md
β βββ bin/
β βββ audio/
β βββ config/default_preferences.json
βββ hooks/hook_runner.py # CANONICAL
βββ bin/ # CANONICAL
β βββ audio-hooks / audio-hooks.py / audio-hooks.cmd
β βββ audio-hooks-statusline / .py / .cmd
βββ audio/ # CANONICAL: 26 default + 26 custom
βββ config/
β βββ default_preferences.json
β βββ user_preferences.schema.json
β βββ audio_manifest.json
βββ scripts/
β βββ install-complete.sh / install-windows.ps1
β βββ uninstall.sh / build-plugin.sh
β βββ generate-audio.py
β βββ ...
βββ CLAUDE.md
βββ README.md
βββ CHANGELOG.md
- Edit canonical files (
/hooks/,/bin/,/audio/,/config/) - Run
bash scripts/build-plugin.shto sync into plugin layout - CI verifies in-sync via
bash scripts/build-plugin.sh --check - Validate:
claude plugin validate plugins/audio-hooks - Test:
python bin/audio-hooks.py test all
Pull requests welcome. Fork, clone, make changes to canonical files, run build-plugin.sh, validate, test end-to-end, and submit with a conventional commit message.
| Document | Purpose |
|---|---|
| CLAUDE.md | Canonical AI-facing operating guide |
| CHANGELOG.md | Detailed version history |
| docs/ARCHITECTURE.md | System architecture details |
audio-hooks manifest |
Live source of truth β always up to date |
|
Design Philosophy β This project is AI-operated, not AI-assisted. A typical CLI tool: the human learns the tool. claude-code-audio-hooks: the human says what they want, Claude Code learns the tool and does the work. The human is upstream of Claude Code, not downstream of the CLI. |
This project is licensed under the MIT License β see LICENSE for details.
- Commercial use allowed
- Modification allowed
- Distribution allowed
- Private use allowed
Chan Meng Creator & Lead Developer |



