How to make Claude Code play a sound or speak when it finishes.
Two hooks in ~/.claude/settings.json do it: Stop for “done” and Notification for “needs you”. Copy the config for your OS, then choose between a chime, a spoken sentence, or a voice layer.
Tested on Claude Code 2.1.288 · macOS, Linux, Windows · Updated October 2026
The short answer
Add a Stop hook for “done” and a Notification hook for “needs you”.
Claude Code runs shell commands on lifecycle events through hooks. The Stop event fires when Claude finishes responding, so it is the reliable “task finished” signal. The Notification event fires when Claude needs your permission or is waiting on your input. Point each one at a sound command in ~/.claude/settings.json: afplay on macOS, paplay on Linux, or PowerShell on Windows.
To make Claude Code speak instead of chime, pipe the Stop hook’s last_assistant_message field into a text-to-speech command such as say. The Claude Code CLI has voice dictation for input but no built-in voice output, and requests for a native completion chime were closed as not planned (#25267, #45014), so hooks are the supported path. For spoken summaries across several sessions, use a voice layer such as Heard.
Two hooks cover it. Tested with Claude Code 2.1.288 on macOS.
Every option
Five ways to hear Claude Code, from a bell to a voice layer.
Start with the lightest option that solves your problem. The first three are built from Claude Code settings and your operating system, with nothing to install.
Option
What you hear
Setup
Platforms
Cost
Terminal bellpreferredNotifChannel
A bell, or a desktop banner in Ghostty, Kitty and iTerm2
One setting
Any terminal
Free
Sound hookafplay · paplay · PowerShell
Distinct “done” and “needs you” tones
Two hooks, five minutes
macOS, Linux, Windows
Free
Speech hooksay · spd-say
Claude’s final message, read word for word
One hook plus jq
macOS, Linux, Windows
Free
Plugins and extensionsClaude Notifier · Agent Ping
Sound packs, banners, or read-aloud
One install command
Varies by tool
Free, open source
HeardVoice layer
Short spoken summaries instead of raw text; answer back on Power
Heard is our product. The other four options are free and work today.
(1)Step 1 · macOS sound
Play a sound when Claude finishes or needs you.
Add both hooks to ~/.claude/settings.json, or to .claude/settings.json inside a repo to scope them to that project. The permission_prompt matcher limits the Notification hook to permission requests, so the “needs you” tone always means you have a decision to make. Leave the matcher empty to also hear idle_prompt, which fires when Claude has been waiting on you.
Claude Code only fires Notification when you appear to be away from the terminal, so use Stop as your completion signal: it fires at the end of every turn. Any file in /System/Library/Sounds works. Glass and Funk are different enough to tell apart without looking.
Every Stop hook receives a JSON payload on stdin, and its last_assistant_message field holds the text of Claude’s final reply. Pipe it through jq into a text-to-speech command and Claude Code reads its own result aloud. We checked the payload and this exact command against Claude Code 2.1.288.
Cap the length. A final message can be a long report, and say reads every word, including file paths and code. 300 characters is usually one or two sentences. "async": true lets Claude Code carry on while the voice is still speaking.
The hook shape is identical on every platform; only the commands change. On Linux, paplay plays the freedesktop sounds through PulseAudio or PipeWire, and spd-say speaks text. On Windows, PowerShell plays a WAV with System.Media.SoundPlayer and speaks with System.Speech.
We tested the macOS commands end to end. Run the Linux and Windows commands once in your own shell before relying on them, because sound files and speech packages vary by distribution and Windows edition.
Two distinct sounds are the right default. If you run long or parallel sessions, tighten the rules so every sound still means something.
Match permission_prompt only if idle_prompt reminders start to feel like nagging.
Leave SubagentStop unhooked. It fires every time a subagent finishes, which is constant noise during a large task.
Expect idle_prompt to arrive a while after Claude stops; permission prompts fire right away. Use Stop for “done”.
Speak the folder name so you know which session finished: every payload includes cwd, so jq -r .cwd | xargs basename | say works.
Want no hooks at all? Set "preferredNotifChannel": "terminal_bell" for a plain bell in any terminal (docs).
(5)Troubleshooting
If the hook stays silent.
Most silent hooks come down to one of these causes.
Run the command by itself first. If afplay /System/Library/Sounds/Glass.aiff is silent in your terminal, fix the output device or volume before touching hooks.
Run /hooks inside Claude Code to see what loaded. Claude Code watches settings files and reloads hooks on its own, so you do not need to restart; a JSON syntax error is the usual cause.
In the VS Code extension, Notification hooks have been reported not to fire for in-panel prompts (#26925). The Stop hook still works there.
Over SSH, hooks run on the remote machine, so afplay plays on the server. Claude Code’s built-in desktop notification does reach your laptop in Ghostty, Kitty and iTerm2.
Inside tmux, add set -g allow-passthrough on to ~/.tmux.conf so notifications reach the outer terminal.
On Windows, use PlaySync() as in the example above: it waits for the sound to finish. Play() returns at once and PowerShell exits before you hear anything.
On Linux, paplay plays WAV and OGG. For MP3, use mpg123 or ffplay -nodisp -autoexit instead.
In Apple Terminal, /terminal-setup turns the audible bell off. Turn it back on under Settings → Profiles → Advanced if you rely on terminal_bell.
(6)Beyond a chime
When a chime is not enough: a voice layer.
A chime tells you that something happened. say tells you what Claude wrote, word for word. Neither tells you which of four sessions just stopped, or whether it stopped because tests failed or because the work is done.
Heard is a voice layer for coding agents on macOS. It connects to Claude Code and Codex through native adapters, decides what deserves airtime (questions, blockers, failures, results), and says it in a sentence or two. With several sessions running, it batches routine activity into short summaries that start with the project name. On Power you can answer back by voice or from your iPhone. The engine is open source under Apache 2.0 with a local Kokoro voice, and every new account starts with a 14-day Power trial, no card required.
Useful
“Payments session: three snapshot tests failed. Want me to update the snapshots?”
Noise
“src/payments/__tests__/checkout.test.ts, line 42, expected 1999, received 2099, at Object.toEqual…”
Ready-made
Tools that set this up for you.
Prefer not to edit JSON? These open-source projects install the hooks for you. Star counts and activity checked October 2026.
The most installed VS Code notifier: distinct sounds for done and needs-you, a minimum task length so short turns stay quiet, auto-mute while the window is focused, and remote audio so sounds play on your laptop when Claude runs over SSH or WSL. Also covers Codex.
A VS Code extension that can speak a fixed line, “Claude finished the task” or “Claude needs your input”, plus a sound and a toast, toggled from the status bar.
A Claude Code plugin that plays sounds and shows OS notifications when Claude stops, needs permission, or hits an error. Install it with /plugin install agent-ping.
Summarized spoken updates for every Claude Code and Codex session, with voice replies and an iPhone companion on Power.
Best for
Several sessions at once
Surface
macOS app
Agent support
Claude Code, Codex CLI, cloud agents via MCP
Tradeoff
macOS only; voice replies need Power.
Pick one
Which approach should you choose?
Start with the lightest option that fits how you work. You can always add speech or a voice layer later.
(1)
One session, you just want a ping
Two sound hooks
A Stop sound for done and a Notification sound for needs you. Local, free, nothing to maintain.
(2)
You want to hear what happened
A speech hook
Pipe last_assistant_message into say or spd-say, capped at a sentence or two.
(3)
You live in VS Code or work over SSH
An extension
Claude Notifier manages the hooks for you and plays sounds on your laptop even when Claude runs remotely.
(4)
Several sessions, or you want to answer back
A voice layer
Heard summarizes each session, batches routine work, and on Power lets you reply by voice or from your iPhone.
Questions
Frequently asked questions
Does Claude Code have a built-in completion sound?
Not a custom one. Claude Code sends a desktop notification in Ghostty, Kitty and iTerm2, and can ring the terminal bell elsewhere with "preferredNotifChannel": "terminal_bell". Requests for a native chime were closed as not planned (#25267, #45014), and the suggested route is preferredNotifChannel or hooks (#1288).
Can Claude Code read its responses aloud?
Not in the CLI. /voice is dictation: you speak and Claude Code types. For voice output, pipe the Stop hook’s last_assistant_message into say or spd-say, install a read-aloud tool, or use Heard for summarized narration.
Which hook fires when Claude Code finishes a task?
Stop. It fires when Claude finishes responding. Notification fires when Claude needs permission or is waiting on input while you appear to be away, so it is not a reliable completion signal by itself.
Can the Notification hook say what Claude needs?
Yes. Every Notification payload has a message field, so jq -r '.message // empty' | say reads it aloud on macOS, or pipe it to spd-say on Linux.
Do I need to restart Claude Code after editing hooks?
No. Claude Code watches its settings files and reloads hooks automatically. Run /hooks to confirm they loaded.
Why is my Notification hook silent in VS Code?
Notification hooks have been reported not to fire for permission prompts shown inside the VS Code panel (#26925). Use the Stop hook for completion, which still fires there.
How do I tell which session finished when I run several?
Every hook payload includes cwd, so a hook can speak the project folder name. Past two or three sessions, a voice layer like Heard summarizes routine work per project instead of reading raw text.