Speak Claude Code responses aloud.
I have ADHD. Long terminal output from AI coding assistants is attention-hostile -- information-dense but hard to sustain focus on. So I built a plugin that reads Claude Code responses aloud. Audio changes the dynamic: you can listen to the explanation while reviewing the code diff on screen, or step away from your desk entirely.
Zero setup. One install command. Works offline.
git clone https://github.com/HyperfocuSam/claude-voice ~/.claude/plugins/claude-voiceThat's it. Voice mode uses macOS say by default -- no API keys, no dependencies.
/voice on # Enable auto-speak (speaks when conversation ends)
/voice off # Disable auto-speak
/voice status # Check current state and provider
/speak # One-shot: speak the last response
/speak "any text" # Speak specific text
When a Claude Code conversation ends, the Stop hook:
- Checks if voice mode is enabled (
~/.claude-voice/enabledflag file) - Reads the session transcript for the last assistant message
- Converts markdown to natural speech text (code blocks, tables, URLs all handled)
- Launches TTS in the background -- never blocks Claude Code from exiting
The text adapter turns this:
## Getting Started
- Install with `pip install requests`
- Check `/Users/sam/projects/my-app/config/settings.yaml`Into this:
"Section: Getting Started. First: Install with pip install requests. Next: Check config/settings.yaml."
Code blocks become "I've included a code block here." Tables become "Here's a table with 3 rows." File paths get shortened. It sounds natural, not robotic.
| Provider | Setup | Quality | Latency | Offline |
|---|---|---|---|---|
say |
None (macOS default) | Basic | Instant | Yes |
openai |
OPENAI_API_KEY |
High | 2-5s | No |
minimax |
MINIMAX_API_KEY |
Highest | 3-10s | No |
Works out of the box on any Mac. No API keys, no internet required.
# List available voices
say -v ?
# Test a voice
say -v Samantha "Hello from Claude Code"High-quality neural voices. Set your API key and switch provider:
export OPENAI_API_KEY="sk-..."Available voices: alloy, echo, fable, onyx, nova, shimmer
Highest quality with timber blending -- mix multiple voice profiles for a custom sound.
export MINIMAX_API_KEY="..."Supports emotion control: happy, sad, calm, surprised, and more.
The say provider is macOS-only. On Linux or Windows, use a cloud provider (OpenAI or MiniMax). Audio playback uses xdg-open/paplay on Linux and start on Windows.
Create ~/.claude-voice/config.yaml to customize:
provider: openai
max_chars: 3000
openai:
model: tts-1-hd
voice: nova
speed: 1.1See config/defaults.yaml for all options.
No config file needed for defaults. Environment variables work too: set CLAUDE_VOICE_PROVIDER=openai to switch providers without a config file.
Claude's markdown sounds terrible read literally. The adapter handles it:
| Markdown | Speech |
|---|---|
```python ... ``` |
"I've included a Python code block here." |
`inline code` |
Just the text, no backticks |
## Header |
"Section: Header." |
- bullet items |
"First: ... Next: ... Also: ..." |
[link](url) |
Just the link text |
| Pipe tables | "Here's a table with N rows." |
/long/nested/file/path |
file/path (last 2 components) |
**bold** / *italic* |
Plain text |
Truncates at a sentence boundary before 5000 characters.
The TTS engine works standalone outside the plugin:
# macOS say (default)
python3 scripts/speak.py "Hello world"
# OpenAI
python3 scripts/speak.py "Hello world" --provider openai --voice nova
# MiniMax with emotion
python3 scripts/speak.py "Hello world" --provider minimax --emotion happy
# Save to file without playing
python3 scripts/speak.py "Hello world" -o output.mp3 --no-play- Python 3.10+
- macOS for
sayprovider (Linux/Windows use cloud providers) requestsfor cloud providers (pip install requests)PyYAMLoptional -- falls back to env vars if missing
PRs welcome. Some ideas:
- New providers -- ElevenLabs, Google Cloud TTS, Azure Speech
- Better text adaptation -- more markdown patterns, smarter truncation
- Linux audio -- better playback detection and fallbacks
- Streaming -- speak as Claude types instead of waiting for the full response
Built by Sam Wong because developer tools should work for every kind of brain.
