Give your Claude a voice

This teaches Claude Code to speak a short summary out loud when it finishes a task, so you can walk away and still hear what happened, plus any question it has for you.

  1. Open Claude Code on your computer (the terminal app, or the Code tab in the Claude desktop app). The regular Claude chat can't do this.
  2. Tap Copy the prompt below, paste it into Claude Code and send it.
  3. Claude sets it up, tests it with you, and tells you how to undo it. After that, restart Claude Code once.

It uses your computer's built-in voice, so nothing is downloaded or paid for. Say "mute" to Claude anytime to turn it off.

Please give yourself a voice on this computer, so you can talk to me out loud when you finish working. I often start you on a task and walk away, so I want to hear what happened without coming back to the screen.

Only do this if you are Claude Code (the terminal app, or the Code tab in the Claude desktop app), because it uses Claude Code "hooks". If you're the plain Claude chat app or website, tell me this needs Claude Code, and stop.

WHAT I WANT IN THE END
1. At the end of every reply, you write a final line like:
   [say: The build worked. Do you want me to upload it now?]
   That text is spoken aloud through my speakers: the result in one short sentence, plus the one question or action you need from me, if there is one. About 30 words max, plain speech, no file paths, version numbers or code.
2. If a reply has no [say: ...] line, just say "Claude's done."
3. When you're stuck waiting for my permission or input, say "Claude needs you."
4. Before you do something physical I should know about (a sound, a motor, a device resetting), you can announce it first by starting that command with: claude-voice say "..." &&
5. I can switch it with: claude-voice on | off | read   ("read" = read your whole final message aloud, for when my eyes are tired). Default is on.
6. Nothing else gets spoken. Don't read my own messages back to me.

HOW TO BUILD IT (you're the engineer; adapt it to this computer)
1. Find out the operating system. Use the voice that's already built in, so nothing needs downloading:
   - Mac: the `say` command.
   - Windows: PowerShell with System.Speech (Add-Type -AssemblyName System.Speech; SpeechSynthesizer).
   - Linux: `spd-say` or `espeak-ng`. They sound robotic, so offer me Piper (piper-tts, free and local) as a nicer voice once the basic version works.
2. Write one small script called `claude-voice`, in a folder on my PATH (for example ~/.local/bin), in whatever language suits this OS (Python if it's installed, otherwise PowerShell on Windows or shell on Mac/Linux). It needs:
   - `claude-voice hook`: called by Claude Code hooks. It reads the hook's JSON from stdin.
       * Stop event (hook_event_name == "Stop"): take the text of your final message from the `last_assistant_message` field. If that field is missing, read the last assistant text from the file in `transcript_path` (JSON lines). Find the LAST [say: ...] in it and speak that; if there isn't one, speak "Claude's done". In "read" mode speak the whole message instead, with code blocks, markdown symbols and links cleaned out and capped at about 1500 characters.
       * Notification event: speak "Claude needs you."
       * It must return right away: start the speaking as a detached background process, so it never holds up Claude Code or hits the hook timeout.
       * Newest message wins: if something is still being spoken, stop it before starting the new one (keep the speaker's process ID in a small file).
       * Keep a log of everything spoken in a text file next to the mode file, so problems can be checked.
   - `claude-voice say "text"`: speak now and WAIT until it's finished (this one blocks on purpose, so I hear the warning before the action happens).
   - `claude-voice on|off|read|status`: store the mode in a small file (for example ~/.local/share/claude-voice/mode). "off" means silent, including for the hook.
   - It must never crash Claude Code: catch every error and exit 0.
3. Make a backup copy of ~/.claude/settings.json first (if it exists). Then ADD these two hooks to it, merging with anything already there, never replacing the file:
   "hooks": {
     "Stop":         [ { "hooks": [ { "type": "command", "command": "<full path to claude-voice> hook", "timeout": 10 } ] } ],
     "Notification": [ { "hooks": [ { "type": "command", "command": "<full path to claude-voice> hook", "timeout": 10 } ] } ]
   }
   Use the full path, and on Windows the right way to launch the script (for example powershell -NoProfile -ExecutionPolicy Bypass -File ...).
4. Make a backup of ~/.claude/CLAUDE.md (create the file if it doesn't exist), then add a section to it so every future session of you follows the rule. Something like:
   "# You have a voice on this computer
   End EVERY final message with a [say: ...] line. It is spoken aloud through the speakers: a condensed spoken version of the reply, the result in one short sentence, then the one question or action you need from me, if any. About 30 words max, plain speech, no paths, versions or code.
   Mid-turn warning before something physical happens: start that command with claude-voice say "..." && (it waits until the words are spoken). Writing [say: ...] in the middle of a turn does NOT get spoken; only the final message counts.
   Don't read my messages aloud unless I ask. "read to me" = claude-voice read; "stop reading" = claude-voice on; "mute" = claude-voice off."
5. Test it for real before telling me it's done:
   - Run `claude-voice say "Hello, I can talk now."` and ask me whether I heard it.
   - Pipe a fake Stop event into it, e.g. echo '{"hook_event_name":"Stop","last_assistant_message":"All set. [say: This is a test of the end of turn voice.]"}' | claude-voice hook
   - Hooks only load when Claude Code starts, so tell me to restart Claude Code once, and to send any message afterwards to hear the real thing.
6. Finish by telling me in plain words: what you installed, where the backups are, and how to undo it all (restore the two backups and delete the script). Then end your message with your first [say: ...] line.