[Feature Request] Native text-to-speech output for Claude Code responses

Resolved 💬 4 comments Opened Apr 8, 2026 by ghitafilali Closed May 28, 2026

Description

Claude Code has /voice for speech-to-text input, but there's no native way to
have responses read aloud. This was previously requested in #2189 (auto-closed
due to inactivity, not resolved).

Use case

Claude Code's output is detailed and thorough — which is great — but it's often
too long and generated too fast for me to keep up with by reading. I'm a slow
reader and don't have the patience to scroll through walls of text after every
response. The information is valuable, I just can't absorb it visually at that
pace.

I'm used to listening to audiobooks at 2x speed. If Claude Code could read its
responses aloud with configurable playback speed, I could effortlessly absorb
all that detail while continuing to work. I'd actually want the verbose output
instead of skimming past it.

Important: I don't need voice input. I love typing my instructions — I'm
usually surrounded by people when I work, so speaking to Claude Code isn't
practical. What I need is the opposite direction: text input, audio output.
Just let me type my request, put on my headphones, and listen to what Claude
did and why — without having to read a novel every time.

Session-level requirements (critical)

A native implementation must support per-session control, not just per-project.
This is the key gap that community tools cannot solve on their own today.

My actual workflow:

  • I often run **multiple Claude Code terminal sessions in the same project

directory** (main work + a parallel verification session, for example)

  • For some sessions I want narration (the main work I'm focused on)
  • For others I explicitly don't want narration (verification sessions I

just want to watch pass/fail, quick lookup sessions, background tasks)

Community TTS tools (claude-speak, claudevoice-macos, claude-code-tts, etc.)
all hit the same architectural wall: Claude Code writes JSONL logs at the
project level (~/.claude/projects/<encoded-path>/), and there's no stable,
shell-visible way to tell which JSONL file belongs to which terminal session.
This forces these tools into per-project state (a single pause flag, one
monitor per project dir), which means toggling narration off for a verification
session also mutes the main work session I care about.

A native implementation has the information the community tools don't, and
should use it:

  • Per-session TTS state (on/off, voice, speed) independent of other sessions

in the same project dir

  • A /speak slash command that affects only the current session
  • Ideally: a way to set narration preferences at claude launch time, e.g.

claude --speak or claude --no-speak, so I can decide per-terminal without
typing a command after the session starts

Proposed implementation

Core narration

  • A /speak toggle (and/or a --speak / --no-speak launch flag) that reads

responses aloud for this session only

  • Configurable reading speed (1x, 1.5x, 2x, configurable down to 0.5x) —

critical for users who consume audio faster than text, like audiobook
listeners

  • Use system TTS by default (say on macOS, espeak on Linux, SAPI on Windows),

with configurable voice

  • Option for streaming TTS (read as tokens arrive, not wait for full response)
  • Configurable via settings.json (default voice, default speed, default on/off)
  • Session state overrides global defaults
  • Sensible text cleaning for audio: strip code blocks, file paths, and raw

markdown syntax so the spoken version sounds natural (community tools already
do this well — the patterns are well-established)

Read-on-demand (separate from auto-narration)

  • A keyboard shortcut to read the latest assistant message on demand,

following the same pattern as the existing /voice dictation shortcut.
/voice is already bound to voice:pushToTalk in the Chat context in
~/.claude/keybindings.json (default: Space, rebindable to modifier
combos like meta+k). A TTS read-last action should work the same way:
a named action like speak:readLast in the Chat context, with a sensible
default shortcut that doesn't conflict with voice:pushToTalk.

  • This should work even when auto-narration is off — i.e. if I've left

narration disabled for a session but want to hear one specific response, I
press the shortcut and it speaks the most recent assistant message

  • Rebindable via ~/.claude/keybindings.json using the same schema as

existing Claude Code keybindings

  • A companion slash command (e.g. /speak last) for users who prefer commands

over shortcuts

Playback controls

All of these should be exposed as named actions in the Chat context, with
default keybindings that can be overridden in ~/.claude/keybindings.json
the same mechanism already used for voice:pushToTalk.

  • Pause / resume (speak:togglePlayback) — pause current narration and

resume later

  • Skip to next / previous response (speak:nextMessage,

speak:previousMessage) — jump between assistant messages in the session
history

  • Seek within the current response (speak:seekForward,

speak:seekBackward) — move forward/backward inside the currently-playing
message. Think of it like a podcast player: you can scrub to a specific
point, jump back 10 seconds, or jump to a specific paragraph/section. This
matters for long responses — if I zone out or miss something, I need to go
back without replaying the whole thing

  • A visual progress indicator while narration is playing (current position

within the response, total length) so I can see how much is left and where
I am

  • All controls should be session-scoped and survive pause/resume
  • All keybindings should default to values that don't conflict with

voice:pushToTalk or other existing Chat-context bindings

Why native matters

Community MCP plugins exist (VoiceMode, mcp-voice-hooks, claude-code-tts,
claude-speak, claudevoice-macos, talkito) but they all hit the same problems:

  • Per-session control is not solvable from outside Claude Code. None of

them can reliably scope narration to a single terminal because Claude Code
doesn't expose a stable session identifier in a way external tools can hook
into. The best they can do is per-project state, which breaks for the
multi-session-in-same-repo case.

  • On-demand reading of the latest message is not solvable cleanly either

for the same reason — external tools can't tell which JSONL file belongs to
the terminal you're actively looking at.

  • Seek controls are impossible from outside. External tools stream text

to a TTS service and play audio. They have no hook for "rewind 10 seconds
in the currently-playing response" because they don't control the playback
pipeline end to end.

  • Extra setup, extra dependencies — pip installs, shell scripts, PID files,

hook-file merges. A native integration would work out of the box.

  • Version fragility — tools that watch internal JSONL formats or settings.json

hook shapes break when Claude Code updates its internals.

A native integration would:

  • Make verbose output accessible: Users who can't keep up reading would

finally benefit from Claude Code's detailed explanations

  • Lower the barrier: works out of the box, like /voice does for input
  • Complete the interaction loop: text input + audio output is a valid and

practical interaction mode, especially in shared/open office environments

  • Enable multitasking: listen to explanations through headphones while

reviewing the actual code changes

  • Actually support real workflows: per-session control and on-demand

reading make narration compatible with how people actually run Claude Code
(multiple terminals, same repo, varied attention levels per session)

The core problem

Claude Code gives excellent detail in its responses, but the only way to
consume it is by reading. For users who process audio faster than text — or who
simply can't read as fast as Claude generates — all that useful context goes to
waste. TTS output with speed control, on-demand triggering, and seek controls
would turn a frustration into a superpower.

The /voice feature assumes people want to talk to Claude. But some of us
want Claude to talk to us — while we keep typing. These are independent needs.

And crucially: the narration has to work per session, support on-demand
triggering
, and provide seek controls — or it can't coexist with real
multi-terminal workflows and long-form responses.

Prior art

  • #2189 (auto-closed, community interest existed)
  • /voice already proves Anthropic values voice interaction
  • Multiple community plugins confirm demand — and confirm that the per-session

constraint, on-demand reading, and seek controls can only be solved natively:

monitor, per-project state, free (Microsoft Neural voices)

notifications, macOS-only

MCP, browser TTS

OpenAI TTS

  • talkito — multi-channel TTS wrapper

None of these solve the multi-session-same-project case, none provide true
on-demand reading of the current terminal's last message, and none expose
seek controls — the necessary primitives aren't available to them.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗