A coding agent works for a few minutes and then stops. Either it has finished, or it is waiting for you to say yes to a command. If you are not watching the terminal, you find out late. This post covers two ways to be told: a hook you can write in five minutes, and the tool I ended up building when the five-minute version broke.
The five-minute version: a Stop hook#
Claude Code runs a command of your choice on lifecycle events. Two matter here:
Stopfires when the main agent finishes its reply.Notificationfires when Claude Code needs your attention, such as a permission prompt.
Add this to ~/.claude/settings.json (macOS shown):
{
"hooks": {
"Stop": [
{ "hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" }] }
],
"Notification": [
{ "hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Ping.aiff" }] }
]
}
}On Linux, swap afplay for paplay or aplay and a sound file you have. On Windows, PowerShell can play a .wav with (New-Object Media.SoundPlayer 'C:\Windows\Media\chimes.wav').PlaySync().
This works, and if it is all you need, stop here.
Where it stops being enough#
A one-line hook works on one machine. These are the problems that made me build a tool instead:
- It breaks on the next machine. Windows plays audio differently from macOS, and WSL cannot reach its own files from the Windows media player. A one-liner that works on your laptop fails on your desktop.
- Each editor has its own hook format, and the format changes between releases. I wanted the same behaviour in Claude Code, Cursor and Codex.
- One sound for everything is not information. "Finished" and "waiting for permission" need different answers from you, and so do a subagent finishing and a usage limit coming up.
- Away from the desk, a sound does nothing. I wanted a desktop toast, a spoken summary of the reply, or a message on my phone.
echook#
echook is the free, open-source tool I built for this. It plays a sound, shows a desktop notification, reads the agent's reply aloud or posts to Slack, Discord, Teams or ntfy when Claude Code, Cursor or Codex finishes, asks for permission or nears a usage limit. It runs locally on Windows, macOS and Linux, and sends nothing anywhere unless you set a webhook.
The quickest install is to ask your agent:
Install echook from github.com/ChanMeng666/echook and set it up for me.
It reads the docs, runs the commands and checks the result. One step stays with you: type /reload-plugins once in a Claude Code session that was already open.
If you prefer to run it yourself in Claude Code:
claude plugin marketplace add ChanMeng666/echook
claude plugin install audio-hooks@chanmeng-audio-hooksAfter that, every setting is a sentence to your agent: "mute audio for an hour", "switch to chimes", "send permission prompts to my Slack", "put a context-usage bar in my status line".
What it covers:
- 39 hook events, three on by default, each with its own sound.
- Four outputs: sound, desktop toast, speech that reads the agent's final message, and webhooks.
- A warning before the 5-hour and 7-day usage limits, fired once each.
- A status line that follows the agent you are viewing, including a subagent's model and context.
Which one should you use?#
If you use one editor on one machine and want one sound, write the hook. If you work across machines or editors, want different sounds for different events, or want to be reached away from the screen, use echook. Or read echook's source for its cross-platform audio handling if you would rather write your own.
The design notes are in Claude Code Audio Hooks: System Architecture.