AI-operated audio notification system for Claude Code, Cursor IDE, and Codex CLI.
You type one slash command at install time. Then natural language forever.
Hear when your agent finishes, needs permission, or hits a rate limit β and pin a context-usage status line so you never lose your place.
v6.2.0 β 39 hook events across all three editors Β· 2 audio themes Β· webhooks Β· TTS Β· rate-limit alerts Β· status line. Renamed claude-code-audio-hooks β echook (Echo + Hook) in 5.2.1; existing installs keep working. Full history in the CHANGELOG.
Share This Project
promo-video.mp4
Built with Remotion, Claude Code, ElevenLabs & Suno. Source: echook-promo-video
Humans: don't install or configure echook by hand. Point your AI agent β Claude Code, Cursor, or Codex β at this repo and say:
"Install echook from
github.com/ChanMeng666/echookand set it up for me."Your agent reads the docs, runs every command, verifies the result, and reports back. The agent-facing source of truth is
AGENTS.md+llms.txt+ the liveaudio-hooks manifest. The only thing a human ever types by hand is one/reload-pluginsslash command (Claude Code has no CLI equivalent for it).All a human needs to know is what echook does β skim Key Features below β so you can ask your agent for it in plain English: "mute audio for an hour", "switch to chimes", "watch my
.envfile", "put a context-usage bar in my status line". Not sure what's possible? Just ask your agent "what can I configure in echook?"
Table of Contents
Latest: v6.2.0 β complete hook coverage + per-tool-type sounds on Cursor. 13 new lifecycle events (26 β 39 total): Claude Code's Setup / UserPromptExpansion / PostToolBatch / MessageDisplay, plus Cursor's granular per-tool-type events so shell commands, MCP calls, and file reads each get a distinct sound. All new events are opt-in.
Earlier highlights: v6.1.0 pinned the Claude Code startup banner into the status line with auto-reflow Β· v6.0.0 refocused echook to two tracks (audio/notification + status line) and made every operation a non-interactive CLI command.
π Full version history β CHANGELOG.md Β· GitHub Releases
echook does exactly two things, and does them well: (1) tells you what just happened in your AI session when you're not watching the window β a sound at your desk, a spoken summary when you're away, a desktop toast or webhook when you're in another app β and (2) a status line that keeps the facts you need pinned to the bottom of the terminal.
Hear (or get pinged) the moment your agent finishes, asks for permission, fails a tool, or hits a rate limit β so you can walk away and trust you'll be called back.
| Channel | What it's for |
|---|---|
| Audio | A sound at your desk the instant something needs you. Two themes β voice or chimes. |
| Desktop toast | A glanceable popup when you're in another window. |
| TTS | Speaks a sanitized summary of Claude's actual final message when you're away from the screen. |
| Webhook | Slack / Discord / Teams / ntfy / any HTTP endpoint β get alerts on your phone. |
Pins your Claude Code startup banner at the bottom (so it never scrolls away) and adds real-time context-window and quota bars β color-coded warnings before Claude enters the "agent dumb zone". Auto-reflows to fit any terminal width, so nothing is truncated.
| Color | Context used | Meaning | Action |
|---|---|---|---|
| π’ Green | < 50% | Safe β agent performs well | Keep working |
| π‘ Yellow | 50β80% | Caution β entering the "dumb zone" | /compact or /clear soon |
| π΄ Red | > 80% | Danger β frequent errors | /compact immediately |
29 customisable status-line segments
A few of the highlights (run audio-hooks statusline segments for the full live catalog):
| Segment | Shows |
|---|---|
model |
Model name (e.g. [Opus 4.8 (1M context)]) |
effort / thinking |
Reasoning effort (π§ high) / extended-thinking flag |
cc_version |
Claude Code's own version (β‘ CC v2.1.193) |
cwd / repo |
Working directory / git remote owner/name |
session_name / agent / output_style / vim |
Session label / --agent name / output style / vim mode |
branch / git_dirty / worktree |
Git branch / uncommitted-change count / managed worktree |
pr / added_dirs |
Pull-request number + review state / /add-dir count |
api_quota / weekly_quota |
5-hour & 7-day rate-limit bars + reset times |
context / tokens / exceeds_200k |
Context bar (+ tokens, /compact hint) / cache-hit ratio / >200K flag |
cost / duration / api_time / burn_rate |
Cost + lines diff / wall-clock time / API-wait share / $/hour |
version Β· sounds Β· webhook Β· theme Β· snooze |
echook version Β· sound count Β· webhook Β· audio theme Β· mute countdown |
Most richer segments self-omit when Claude Code doesn't supply their data, so a plain session stays clean. Pick segments with visible_segments (whitelist) or drop a few with hidden_segments (blacklist). Each logical line auto-reflows into as many rows as your terminal width needs β segments are never split, so nothing is cut off. Pin the width with statusline_settings.max_width.
Codex note: Codex's status line is not command-backed β it only accepts a fixed list of built-in item IDs. echook can't render custom Codex segments, but it can curate the list so it stops truncating:
audio-hooks statusline codex apply --preset balanced.
π Full reference: docs/STATUS_LINE.md β every segment, both editors, all flags.
| Feature | What it does |
|---|---|
| 39 hook events | Full lifecycle coverage across Claude Code, Cursor & Codex β session start, tool use, permission requests, rate-limit warnings, and Cursor's granular shell/MCP/file events. 6 on by default; toggle any in plain English. |
| 2 audio themes | default = ElevenLabs Jessica voice ("Task completed") Β· custom = modern UI chimes. Say "switch to chimes". |
| Rate-limit alerts | One-shot warning at 80% / 95% of your 5-hour or 7-day quota β warned once per threshold, never spammed. |
| Webhooks | Versioned audio-hooks.webhook.v1 payload, fire-and-forget, never blocks a hook. |
Full hook events table (39 events)
| 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 / posttooluse |
task-starting.mp3 / 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 Β· instructions_loaded |
config-change.mp3 Β· instructions-loaded.mp3 | ||
worktree_create / worktree_remove |
worktree-create.mp3 / worktree-remove.mp3 | ||
elicitation / elicitation_result |
elicitation.mp3 / elicitation-result.mp3 | ||
cwd_changed Β· file_changed |
cwd-changed.mp3 Β· file-changed.mp3 | literal filenames | |
setup (v6.2, Claude Code) |
setup-ready.mp3 | init / maintenance |
|
user_prompt_expansion Β· post_tool_batch Β· message_display (v6.2) |
(per event) | ||
shell_before / shell_after (v6.2, Cursor) |
shell-starting.mp3 / shell-done.mp3 | ||
mcp_before / mcp_after (v6.2, Cursor) |
mcp-starting.mp3 / mcp-done.mp3 | ||
file_read Β· agent_response Β· agent_thinking Β· workspace_open Β· tab_file_edit (v6.2, Cursor) |
(per event) |
Run audio-hooks hooks list for the live state, or see the CLI & Configuration Reference.
This is an AI-first project β you don't follow install steps yourself. You tell your AI agent what to do in plain English, and it runs every command and reports back.
flowchart TB
REPO["github.com/ChanMeng666/echook<br/>(source + GitHub Releases)"]
REPO --> CCP["Claude Code<br/>plugin marketplace"]
REPO --> CURB["Cursor 3.2.16+<br/>auto-bridge (Path A)"]
REPO --> CURN["Cursor native<br/>install --cursor (Path B)"]
REPO --> CXP["Codex plugin<br/>marketplace"]
REPO --> CXN["Codex native<br/>install --codex"]
CCP --> CLI["audio-hooks CLI<br/>+ JSON + /audio-hooks SKILL<br/>(identical everywhere)"]
CURB --> CLI
CURN --> CLI
CXP --> CLI
CXN --> CLI
CLI --> OUT["39 hook events Β· 2 themes Β· webhooks<br/>TTS Β· rate-limit alerts Β· status line"]
style REPO fill:#4A90E2,color:#fff
style CLI fill:#7ED321,color:#000
style OUT fill:#F5A623,color:#000
Find your editor, paste the prompt into your agent, done:
| Your editor / CLI | Tell your AI agent |
|---|---|
| Claude Code | "Install the audio-hooks plugin from github.com/ChanMeng666/echook." (Then type /reload-plugins once β the only manual step.) |
| Cursor (with Claude Code) | Nothing to install β Cursor 3.2.16+ auto-bridges the Claude Code plugin. "Run audio-hooks status and confirm editor_targets.cursor.state is bridged-via-claude-code." |
| Cursor (without Claude Code) | "Clone github.com/ChanMeng666/echook into ~/audio-hooks, run python ~/audio-hooks/bin/audio-hooks install --cursor, then verify with audio-hooks status + audio-hooks test all." |
| Codex | "Install the audio-hooks Codex plugin from github.com/ChanMeng666/echook, then verify with audio-hooks status + audio-hooks test all." |
π Full step-by-step install, upgrade, and verification for every path β docs/INSTALLATION_GUIDE.md. Your agent reads this for you.
Once installed (Claude Code, Cursor, or Codex β same CLI everywhere), every configuration is one message. You talk; your agent runs the right audio-hooks subcommand and reports back. You don't memorise anything.
sequenceDiagram
actor You as You
participant CC as Your AI Agent
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.
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: Unmute audio.
CC-->>You: audio-hooks snooze off β audio resumed.
end
rect rgb(254, 243, 199)
Note over You,CC: Hook Selection
You->>CC: Only fire on stop, notification, and<br/>permission_request β disable everything else.
CC-->>You: enable-only stop notification permission_request<br/>β 3 hooks active, rest disabled.
end
rect rgb(207, 250, 254)
Note over You,CC: Status Line & Webhooks
You->>CC: Install the status line, context usage only.
CC-->>You: statusline installed β visible segments: [context].
You->>CC: Send alerts to my Slack webhook and test it.
CC-->>You: Webhook set to slack format. Test delivered.
end
A few examples β paraphrase freely:
- "Switch to chimes" / "switch to voice"
- "Snooze audio for an hour" / "is audio muted?"
- "Enable rate-limit alerts at 80% and 95%"
- "Speak Claude's actual reply when done"
- "Watch my
.envfile for changes" - "Different sound for shell commands vs MCP calls in Cursor"
- "Why isn't audio playing? Diagnose and fix it."
π¬ Complete prompt reference (every option, with sequence diagrams) β docs/NATURAL_LANGUAGE_CONTROL.md.
flowchart LR
CC[Editor event<br/>Claude Code / Cursor / Codex] -->|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 markers]
HR -->|fires| AUDIO[Audio playback<br/>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
Your editor fires hook events as JSON on stdin. Native matchers route each event to hook_runner.py, which checks snooze state, rate-limit thresholds, debounce, and user filters β then fires audio, desktop notifications, TTS, and webhooks as configured.
ποΈ Internals, hook lifecycle, path resolution, and the build pipeline β docs/ARCHITECTURE.md.
| 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.
Agents start here: read
AGENTS.md(mirrored asCLAUDE.md) orllms.txt, then runaudio-hooks manifestβ the complete, live, truthful state of the project. Everything below is for curious humans.
- Something wrong? Just say "audio-hooks isn't working, diagnose and fix it" β or see docs/TROUBLESHOOTING.md.
- Uninstall? Say "uninstall audio-hooks completely." Details in the Installation Guide.
- Want to contribute? See CONTRIBUTING.md for the canonical-source workflow.
| Document | Purpose |
|---|---|
| AGENTS.md / CLAUDE.md | Agent-facing operating guide β critical rules (CLI-only, manifest-first, two-track scope) |
| llms.txt | AI-agent entrypoint |
| docs/INSTALLATION_GUIDE.md | Full install / upgrade / uninstall for Claude Code, Cursor & Codex |
| docs/NATURAL_LANGUAGE_CONTROL.md | Every natural-language prompt, with diagrams |
| docs/CLI_REFERENCE.md | CLI subcommands, config keys, env vars, error codes, logging |
| docs/ARCHITECTURE.md | System architecture and design decisions |
| docs/TROUBLESHOOTING.md | Diagnostic recipes for common issues |
| CHANGELOG.md | Detailed version history |
audio-hooks manifest |
Live source of truth β subcommands, hooks, config keys, error codes, env vars, editor targets. Always current. |
|
Design Philosophy β This project is AI-operated, not AI-assisted. A typical CLI tool: the human learns the tool. echook: the human says what they want, and the AI agent learns the tool and does the work. The human is upstream of the agent, not downstream of the CLI. |
This project is licensed under the MIT License β see LICENSE for details. Commercial use, modification, distribution, and private use all allowed.
Chan Meng Creator & Lead Developer |
