Skip to content
HeardTry for free

Guide · Voice output for Claude Code · 9 min read

How to make Claude Code read its progress out loud on your Mac.

Claude Code takes voice input with /voice, but the CLI does not speak to you. This guide covers which hooks fire during a run and which fire at the end, two small hooks that speak progress through macOS say, plugins that do it for you, and where Heard fits.

Hooks reference checked October 2026 · Heard and free options compared

Updated

The short answer

Use Heard for short spoken updates, or speak progress from a hook that fires mid-run.

Heard (heard.dev), the voice context layer for agents, makes Claude Code talk to you on macOS 14 or later: its app installs the Claude Code hook, so you hear a short line, not the raw text, when Claude asks a question, needs approval, fails or finishes. It does not read out each tool step. Without Heard, the Claude Code CLI takes voice input but does not speak to you. /voice is dictation: it turns your speech into a prompt and reads nothing back. To have Claude Code talk to you instead of you watching the terminal, add a hook that fires during the run and pipe its text into the macOS say command: MessageDisplay runs as each message streams to the screen, PostToolUse after each tool call succeeds, and TaskCompleted when a task on Claude’s task list is done. The claude-code-narrator plugin sets this up for you and speaks tool steps as they happen; Aloud speaks questions, approvals, failures and a short gist of each finished reply, and keeps routine tool calls silent. Both are free (MIT) and speak with a local Kokoro voice.

To have Claude Code read its final reply out loud, or just say “it’s done” at the end of a turn, use a Stop hook: pipe its last_assistant_message field into say (config below), or see the sound-when-done guide for chimes. If you use the Claude desktop app, some users report a play button that appears when you hover over a response in the Code tab and reads it aloud on demand; not everyone sees it yet (#58429).

(1)Progress vs. done

Which hook fires when.

Claude Code runs hooks on lifecycle events. The usual read-aloud recipe uses Stop, which only fires once Claude has finished responding, so you hear nothing during a long run. These are the events in the hooks reference that are most useful for speech while Claude works, plus the two that tell you it needs you or has stopped.

  • MessageDisplay: while Claude’s message text streams to the screen, in batches of whole lines. The input carries message_id, index (the batch number, from 0), final (true on the last batch) and delta (the new lines). It has no matcher, and replies that are only tool calls do not trigger it.
  • PostToolUse: after each tool call succeeds. The matcher filters on tool name, such as Bash or Edit|Write, and the input includes tool_name and tool_input. Speaking every call gets noisy fast.
  • TaskCompleted: when a task on Claude’s task list is marked completed. The input includes task_subject, the task’s title. It only fires in sessions that have the task tools (see Option 2).
  • Notification: when Claude needs you, for example a permission prompt you have not answered for about six seconds (set one up).
  • Stop: when Claude finishes responding. Use it for “done”; the sound-when-done guide covers chimes and speech.

(2)Read replies aloud

How do I make Claude Code read its responses out loud?

Add a Stop hook that pipes Claude’s final reply into the macOS say command. Every Stop hook receives a JSON payload on stdin, and its last_assistant_message field holds the text of Claude’s final response. The hooks reference recommends that field for read-aloud hooks rather than the transcript file, which may not include the last message yet when the hook fires (checked October 22, 2026). Stop fires once Claude has finished responding, so you hear the result of each turn; for updates during the run, use Option 1 below.

Where plain say wins: it is built into macOS, free, needs no account or app, and reads Claude’s own words exactly. Cap the length with head -c, because a final reply can be a long report and say reads every word, file paths and code included. If you would rather hear a sentence or two than the reply word for word, Heard (heard.dev), the voice context layer for agents, summarizes what Claude did instead of reading the raw text, and keeps several Claude Code or Codex sessions in one voice.

~/.claude/settings.json · read each final reply aloud (macOS)
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "async": true,
            "command": "jq -r '.last_assistant_message // empty' | head -c 300 | say"
          }
        ]
      }
    ]
  }
}

(3)Speak as it works

A MessageDisplay hook that reads the start of each message.

This hook speaks the first batch of every message Claude writes, capped at 200 characters, so you hear how each update starts while the run continues. It reads the batch with index 0 rather than the one marked final: in interactive sessions the final batch only carries the last lines of the message, and the reference says it is empty when the message ends on a newline.

Keep "async": true. Per the hooks reference, Claude Code holds each batch of text on screen until a MessageDisplay hook returns, and async runs a command hook in the background so speech never delays the display. The config follows the hooks reference as checked in October 2026; run /hooks afterwards and confirm it is listed under MessageDisplay. If it is not, update Claude Code.

  • Every message starts its own say, so two messages close together can talk over each other.
  • say reads text literally. The command strips * and #, but file paths and code still come through as written.
  • In claude -p runs the hook fires once per message with the whole text at index 0, so the 200-character cap matters more there.
~/.claude/settings.json · speak each message as it starts
{
  "hooks": {
    "MessageDisplay": [
      {
        "hooks": [
          {
            "type": "command",
            "async": true,
            "command": "jq -r 'select(.index == 0) | .delta | gsub(\"[*#]\"; \"\")' | head -c 200 | say"
          }
        ]
      }
    ]
  }
}

(4)Speak finished tasks

A TaskCompleted hook for a quieter signal.

If hearing every message is too much, speak only when Claude ticks off a task on its task list. On a multi-step job that gives you one short line per finished step, such as “Done: Implement user authentication”.

Check one thing first. The tools reference says the task tools are on by default only on some models; on others Claude keeps no task list, so this hook never fires. Start Claude Code with CLAUDE_CODE_ENABLE_TODO_TOOLS=1 claude to turn them on. TaskCompleted also fires when an agent team teammate finishes its turn with tasks still in progress.

~/.claude/settings.json · speak each finished task
{
  "hooks": {
    "TaskCompleted": [
      {
        "hooks": [
          {
            "type": "command",
            "async": true,
            "command": "jq -r '\"Done: \" + .task_subject' | say"
          }
        ]
      }
    ]
  }
}

(5)Built in

Desktop app, voice mode and screen readers.

Claude has a few speech features of its own. None of them speaks Claude Code CLI progress on its own. Screen reader mode comes closest if you already use VoiceOver.

  • Claude desktop app: some users report a play button that appears when you hover over a response in the Code tab and reads it aloud when you click it; not everyone sees it yet (#58429). It is on demand, not automatic.
  • Voice mode: Anthropic’s help center says that in Claude Cowork and Claude Code, dictation is available but voice mode is not. Voice mode is for chats on mobile, desktop and the web.
  • Screen reader mode: claude --ax-screen-reader prints labeled lines such as claude: and tool: that VoiceOver reads in order, and rings the terminal bell when Claude finishes a reply, when a prompt needs your answer, and when a tool that ran longer than 5 seconds finishes (accessibility docs).

(6)Plugins

Tools that narrate for you.

If you would rather not write hooks, these open-source projects install them for you. Each is free under MIT and speaks with a local voice by default. Where they beat Heard is platform: claude-code-narrator also supports Linux (its author has not yet verified Linux audio), and claude-read-aloud runs on Linux and Windows and adds a speaker button inside Claude Code’s VS Code chat box, while Heard runs on macOS only. The text-to-speech comparison puts them side by side.

  • claude-code-narrator: a Claude Code plugin that speaks a short line for each tool step, the text between tool calls, the opening of the final reply and notifications, with a local Kokoro voice on macOS or Linux. The closest match to “read its progress out loud”.
  • Aloud: local Kokoro speech on macOS for Claude Code and Codex. It speaks questions, approval requests, blockers and a short gist of each completed reply, and keeps routine tool calls silent.
  • claude-read-aloud: a plugin plus a VS Code extension that puts a speaker button in Claude Code’s chat box. It reads replies on demand or automatically, with system voices or a local Kokoro voice. The in-chat button is opt-in because it patches the installed Claude Code extension.

(7)A voice layer

Heard: summaries instead of a readout.

The hooks above read Claude’s own words, and the plugins mostly do too: claude-code-narrator speaks a short line per tool step, and Aloud trims each reply to a short gist. Heard decides what is worth saying across all your sessions: it speaks questions, approvals, blockers, failures and final results in a sentence or two, and leaves out tool-by-tool progress. With several Claude Code or Codex sessions running, it keeps each session’s context separate, names the project in each update and keeps routine tool steps quiet. On Heard Power you can answer back by voice.

The engine is open source under Apache 2.0 and speaks with a local Kokoro voice. The Mac app is the managed build, needs macOS 14 or later, and installs its Claude Code hook for you. Every new account starts with 14 days of free Heard, no card required; see pricing for the plans.

  • Summaries, not a transcript read aloud.
  • Several sessions, one voice.
  • Answer back on Power.
  • macOS 14 or later; open-source engine available.
Open source engine, from source
git clone https://github.com/heardlabs/heard
cd heard
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
heard install claude-code

Quick start

Hear your first Claude Code session with Heard

  1. 01

    Install

    Download Heard on a Mac running macOS 14 or later and sign in, or build the open-source engine.

  2. 02

    Enable Claude Code

    Turn on the integration; Heard installs and manages the Claude Code hook.

  3. 03

    Run a task

    Start Claude Code as usual on a task with a few steps and listen for the spoken updates.

  4. 04

    Hear the first update

    Run a short task and listen: questions, approvals, failures and finished work are spoken. Mute updates when you need quiet.

A few more details

Questions?

Can Claude Code talk to me instead of me watching the terminal?

Not by itself. The CLI has no spoken output and /voice is dictation only. Add a hook that pipes Claude’s text into say, install a plugin such as claude-code-narrator or Aloud, or use Heard, which speaks short summaries of each session.

Can it read progress while it works, not just at the end?

Yes, with a hook that fires mid-run. MessageDisplay runs as each message streams to the screen, PostToolUse after each tool call succeeds, and TaskCompleted when a task is ticked off. Stop only fires when Claude has finished responding.

Why does the MessageDisplay hook read the first batch instead of the final one?

In interactive sessions each batch carries only the lines that are new since the last one, and the hooks reference says the final batch is empty when a message ends on a newline. The first batch always holds the opening of the message.

Will a speech hook slow Claude Code down?

Not if you set "async": true, which runs the command in the background. Without it, Claude Code waits for the hook, and for MessageDisplay that means holding text on screen until say returns.

Does Claude’s voice mode work in Claude Code?

No. Anthropic’s help center says Claude Code and Claude Cowork have dictation but not voice mode. In the desktop app’s Code tab, some users report a play button that reads a response on demand.

Does spoken progress work with several sessions at once?

Plain say hooks in several sessions can talk over each other. claude-code-narrator queues speech from all sessions through one player, and Heard keeps per-session context, names the project in each update and keeps routine tool steps quiet.

Keep going

Give your agents a voice.

Keep the context. Get on with your work.

Download for Mac

Includes 14 days of free Heard. No card needed.