https://github.com/chanmeng666/claude-code-audio-hooks
γStars make the code shine brighter!βοΈγπ Audio notification system for Claude Code that plays sound alerts when Claude finishes responding. Perfect for multitasking!
https://github.com/chanmeng666/claude-code-audio-hooks
audio-notifications automation bash claude-code cli-tools developer-tools hooks notification-system productivity wsl
Last synced: 24 days ago
JSON representation
γStars make the code shine brighter!βοΈγπ Audio notification system for Claude Code that plays sound alerts when Claude finishes responding. Perfect for multitasking!
- Host: GitHub
- URL: https://github.com/chanmeng666/claude-code-audio-hooks
- Owner: ChanMeng666
- License: mit
- Created: 2025-11-01T02:12:57.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2026-04-11T03:03:23.000Z (about 1 month ago)
- Last Synced: 2026-04-11T03:13:07.318Z (about 1 month ago)
- Topics: audio-notifications, automation, bash, claude-code, cli-tools, developer-tools, hooks, notification-system, productivity, wsl
- Language: Python
- Homepage: https://github.com/user-attachments/assets/3504d214-efac-4e01-84c0-426430b842d6
- Size: 4.65 MB
- Stars: 41
- Watchers: 1
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
[](#)
# Claude Code Audio Hooks
**AI-operated audio notification system for Claude Code & Cursor IDE.**
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.
**π 5.1.5 β Painless upgrades.** Existing users never lose config across upgrades. New `audio-hooks upgrade` wraps `claude plugin update` / `uninstall + install` with `--keep-data` automatically; auto-migration preserves your settings when new keys are added in future versions; dual-location backups survive even rough `claude plugin uninstall`. Run it any time you want to refresh the plugin code Cursor's bridge invokes. See [CHANGELOG](./CHANGELOG.md#515---2026-05-01).
[](https://opensource.org/licenses/MIT)
[](https://github.com/ChanMeng666/claude-code-audio-hooks)
[](https://github.com/ChanMeng666/claude-code-audio-hooks)
[](https://claude.ai/download)
[](#-install-in-60-seconds)
**Share This Project**
[![][share-x-shield]][share-x-link]
[![][share-linkedin-shield]][share-linkedin-link]
[![][share-reddit-shield]][share-reddit-link]
[![][share-telegram-shield]][share-telegram-link]
[![][share-whatsapp-shield]][share-whatsapp-link]
---
### Promotional Video
https://github.com/user-attachments/assets/3504d214-efac-4e01-84c0-426430b842d6
Built with Remotion, Claude Code, ElevenLabs & Suno. Source: claude-code-audio-hooks-promo-video
Table of Contents
- [What's New in v5.0](#-whats-new-in-v50)
- [Install in 60 Seconds](#-install-in-60-seconds)
- [Just Say It β Natural Language Control](#-just-say-it--natural-language-control)
- [How It Works](#-how-it-works)
- [Key Features](#-key-features)
- [Technical Reference](#-technical-reference)
- [Platform Support](#-platform-support)
- [Troubleshooting](#-troubleshooting)
- [Uninstall](#-uninstall)
- [For Developers](#-for-developers)
- [Documentation](#-documentation)
- [Contributing](#-contributing)
- [License](#-license)
- [Author](#-author)
---
## What's New in v5.0
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. |
### v5.0 in Action
Plugin Installed β 26 hooks registered
/audio-hooks SKILL active
Context monitor status line
Marketplace registration
See [`CHANGELOG.md`](CHANGELOG.md) for full details.
---
## Install in 60 Seconds
**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.
### Step 1 β Open Claude Code
```bash
claude
```
### Step 2 β Install with one prompt
Paste this into Claude Code:
> **Please install the audio-hooks plugin from `github.com/ChanMeng666/claude-code-audio-hooks`. Use the Bash tool to run `claude plugin marketplace add ChanMeng666/claude-code-audio-hooks` then `claude plugin install audio-hooks@chanmeng-audio-hooks`. After both commands complete, tell me to type `/reload-plugins` to activate the plugin.**
### Step 3 β Type `/reload-plugins` (the one manual slash command)
```text
/reload-plugins
```
### Step 4 β Verify and configure with one prompt
> **Verify audio-hooks works by running `audio-hooks diagnose` and `audio-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
```mermaid
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
github.com/ChanMeng666/claude-code-audio-hooks via
`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.
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,
audio theme set to chimes."
Note over Human,CLI: From here on: pure natural language forever.
```
---
## Just Say It β Natural Language Control
Once installed, you operate the project the same way β just talk to Claude Code. Every configuration is a single message:
```mermaid
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,
notification, and permission_request β
disable everything else.
CC-->>You: audio-hooks hooks enable-only stop notification
permission_request β 3 hooks active, rest disabled.
You->>CC: Enable session_start and session_end hooks
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,
no desktop popups.
CC-->>You: Notification mode set to audio_only.
You->>CC: Switch to notification-only mode β
desktop popups but no audio.
CC-->>You: Notification mode set to notification_only.
You->>CC: For the stop hook only, use desktop
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
```
```mermaid
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
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
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
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
Claude's actual final message instead of
a generic announcement.
CC-->>You: TTS enabled with speak_assistant_message = true.
You->>CC: Set the stop hook TTS message to
"Build finished" instead of the default.
CC-->>You: Custom TTS message for stop set.
You->>CC: Make sure audio-hooks rate-limit alerts are
enabled with 80% and 95% thresholds for both
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
in my Claude Code settings.
CC-->>You: audio-hooks statusline install β restart to see it.
You->>CC: Configure the status line to only show
context usage.
CC-->>You: Visible segments set to [context].
You->>CC: Show only context and API quota
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
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
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
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
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,
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.3, 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."* |
---
## How It Works
```mermaid
flowchart LR
CC[Claude Code event] -->|stdin JSON| MR{native matcher
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
marker debounce]
HR -->|reads| CFG[user_preferences.json]
HR -->|reads| MARK[snooze + focus-flow markers]
HR -->|fires| AUDIO[Audio playback
26 MP3s, 2 themes]
HR -->|fires| NOTIF[Desktop notification]
HR -->|fires| TTS[TTS announcement]
HR -->|fires| WH[Webhook subprocess
fire-and-forget]
HR -->|writes| LOG[(NDJSON event log
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 Surface
```mermaid
flowchart 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
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
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 Lifecycle
```mermaid
flowchart TD
EVT[Hook event fires
e.g. Stop] --> SNOOZE{snooze
active?}
SNOOZE -->|yes| EXIT0[exit 0 silent]
SNOOZE -->|no| RL{rate_limits
in stdin?}
RL -->|yes| RLCHK{crossed
threshold?}
RLCHK -->|yes| RLAUDIO[play warning audio
+ write debounce marker]
RLCHK -->|no| DEB
RL -->|no| DEB{debounced
recently?}
RLAUDIO --> DEB
DEB -->|yes| EXIT0
DEB -->|no| FILTER{user filter
matches?}
FILTER -->|yes, exclude| EXIT0
FILTER -->|no| ENABLED{hook
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 Layout
```mermaid
flowchart 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
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
```
---
## Key Features
### Status Line with Context Monitor
Real-time context window and API quota bars β color-coded warnings before Claude enters the "agent dumb zone".
```text
[Opus] Audio Hooks v5.1.3 | 6/26 Sounds | Webhook: ntfy | Theme: Voice
[MUTED 23m] feat/audio-v5 API Quota: 78% Context: 65% (130K/200K) /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 |
**Absolute counts (v5.1.3+).** When Claude Code reports the context window size, the segment also shows current/max tokens, e.g. `Context: 83% (166K/200K)`. This makes the math obvious when you `/model`-switch between context-window variants β switching from Opus 4.7 (1M) to Sonnet 4.6 (200K) keeps your tokens identical but shrinks the denominator 5Γ, so a sudden jump from `17%` to `83%` is **expected**, not a bug. See `docs/TROUBLESHOOTING.md#context-97-or-any-sudden-jump-right-after-switching-models` for the full explanation.
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 |
### Audio Themes
| 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 Hook Events
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 |
### Webhooks
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.
### Rate-limit Alerts
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.
### TTS β Speak Claude's Reply
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.
### Focus Flow
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"*.
---
## Technical Reference
CLI, configuration, environment variables, error codes, logging, manual install (click to expand)
### `audio-hooks` CLI
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 ` | Read any config key |
| `audio-hooks set ` | Write any config key (auto-coerces) |
| `audio-hooks hooks list` | All 26 hooks with current state |
| `audio-hooks hooks enable/disable ` | Toggle a hook |
| `audio-hooks hooks enable-only ` | Exclusive enable |
| `audio-hooks theme list/set ` | 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 ` | 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 |
### Configuration Keys
| Key | Type | Default | Effect |
|---|---|---|---|
| `audio_theme` | `default` \| `custom` | `default` | Voice recordings vs chimes |
| `enabled_hooks.` | 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 |
### Environment Variables
| 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) |
### Stable Error Codes
| 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` |
### NDJSON Event Log
Every event is one JSON object per line at `${CLAUDE_PLUGIN_DATA}/logs/events.ndjson`. Schema `audio-hooks.v1`.
```json
{"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.
### Manual Install Reference
**Plugin install** (two slash commands inside Claude Code):
```text
/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):
```bash
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-TTY
```
Both 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.
### ElevenLabs Audio Generator
`scripts/generate-audio.py` reads `config/audio_manifest.json` and regenerates audio via the ElevenLabs API:
```bash
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 # preview
```
To add a new audio file: edit `config/audio_manifest.json`, run the generator, then `bash scripts/build-plugin.sh`.
---
## Platform Support
| 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.
---
## Troubleshooting
Β Β No sound at all
Run `audio-hooks diagnose`, look for any error code, and run its `suggested_command`. Or just say: *"Audio-hooks isn't playing sounds. Diagnose and fix it."*
Β Β Hearing double sounds
Both legacy script install and plugin install are active. Diagnose reports `DUAL_INSTALL_DETECTED`. Fix: `bash scripts/uninstall.sh --yes` (removes legacy, preserves config).
Β Β Plugin won't install
Run `claude plugin validate plugins/audio-hooks` from the project root β surfaces manifest schema errors. v5.0.1+ verified clean on Claude Code v2.1.101.
Β Β pretooluse / posttooluse too noisy
They fire on every tool execution (Read, Glob, Grep, etc.) β disabled by default for this reason. Enable explicitly with *"enable pretooluse and posttooluse audio"*.
---
## Uninstall
**Plugin install:** say *"uninstall audio-hooks"* or manually:
```text
/plugin uninstall audio-hooks@chanmeng-audio-hooks
```
**Legacy script install:**
```bash
bash scripts/uninstall.sh --yes # preserve config + audio
bash scripts/uninstall.sh --yes --purge # remove everything
```
---
## For Developers
Repository layout, workflow, and contribution guide (click to expand)
### Repository Layout
```
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
```
### Workflow
1. Edit canonical files (`/hooks/`, `/bin/`, `/audio/`, `/config/`)
2. Run `bash scripts/build-plugin.sh` to sync into plugin layout
3. CI verifies in-sync via `bash scripts/build-plugin.sh --check`
4. Validate: `claude plugin validate plugins/audio-hooks`
5. Test: `python bin/audio-hooks.py test all`
### Contributing
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.
---
## Documentation
| Document | Purpose |
|---|---|
| [**CLAUDE.md**](CLAUDE.md) | Canonical AI-facing operating guide |
| [**CHANGELOG.md**](CHANGELOG.md) | Detailed version history |
| [**docs/ARCHITECTURE.md**](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.
---
## License
This project is licensed under the **MIT License** β see [LICENSE](LICENSE) for details.
- Commercial use allowed
- Modification allowed
- Distribution allowed
- Private use allowed
---
## Author
---
[![][back-to-top]](#readme-top)
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-black?style=flat-square
[share-x-shield]: https://img.shields.io/badge/-Share%20on%20X-black?labelColor=black&logo=x&logoColor=white&style=flat-square
[share-x-link]: https://x.com/intent/tweet?text=Check%20out%20Claude%20Code%20Audio%20Hooks%20-%20AI-operated%20audio%20notifications%20for%20Claude%20Code&url=https%3A%2F%2Fgithub.com%2FChanMeng666%2Fclaude-code-audio-hooks
[share-linkedin-shield]: https://img.shields.io/badge/-Share%20on%20LinkedIn-blue?labelColor=blue&logo=linkedin&logoColor=white&style=flat-square
[share-linkedin-link]: https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgithub.com%2FChanMeng666%2Fclaude-code-audio-hooks
[share-reddit-shield]: https://img.shields.io/badge/-Share%20on%20Reddit-orange?labelColor=black&logo=reddit&logoColor=white&style=flat-square
[share-reddit-link]: https://www.reddit.com/submit?title=Claude%20Code%20Audio%20Hooks%20-%20AI-operated%20audio%20notifications&url=https%3A%2F%2Fgithub.com%2FChanMeng666%2Fclaude-code-audio-hooks
[share-telegram-shield]: https://img.shields.io/badge/-Share%20on%20Telegram-blue?labelColor=blue&logo=telegram&logoColor=white&style=flat-square
[share-telegram-link]: https://t.me/share/url?text=Claude%20Code%20Audio%20Hooks%20-%20AI-operated%20audio%20notifications&url=https%3A%2F%2Fgithub.com%2FChanMeng666%2Fclaude-code-audio-hooks
[share-whatsapp-shield]: https://img.shields.io/badge/-Share%20on%20WhatsApp-green?labelColor=green&logo=whatsapp&logoColor=white&style=flat-square
[share-whatsapp-link]: https://api.whatsapp.com/send?text=Check%20out%20Claude%20Code%20Audio%20Hooks%20-%20AI-operated%20audio%20notifications%20for%20Claude%20Code%20https%3A%2F%2Fgithub.com%2FChanMeng666%2Fclaude-code-audio-hooks