Text-to-speech CLI, MCP server, and Claude Code plugin (ElevenLabs, AWS Polly, OpenAI)
Project description
punt-tts
Voice for your AI coding assistant.
When Claude Code finishes a task, hits an error, or needs your approval --- you hear it. No need to watch the terminal. Keep working; your assistant will tell you what happened.
Platforms: macOS, Linux
Quick Start
curl -fsSL https://raw.githubusercontent.com/punt-labs/tts/2d8922f/install.sh | sh
Restart Claude Code, then:
/notify y # hear when tasks complete or need input
/recap # spoken summary of what just happened
Manual install (if you already have uv)
uv tool install punt-tts
tts install
tts doctor
Verify before running
curl -fsSL https://raw.githubusercontent.com/punt-labs/tts/2d8922f/install.sh -o install.sh
shasum -a 256 install.sh
cat install.sh
sh install.sh
Features
- Notification layer --- spoken summaries when tasks finish, chimes when Claude needs input
- Session vibe ---
/vibesets the mood for all speech. Auto-mode reads session signals (test results, lint, git ops) and adapts the voice. Manual mode lets you set it yourself. ElevenLabs expressive tags ([weary],[excited],[sighs]) color every utterance. - Five providers --- ElevenLabs, OpenAI, AWS Polly, macOS
say, and Linuxespeak-ng. The full experience (natural voice, expressive tags,/vibe) requires ElevenLabs. - Opt-in only --- no audio until you enable it, no surprises
- Voice or chime ---
/speak nswitches to audio tones, no TTS API calls - Graceful absence --- if punt-tts isn't installed, Claude Code works exactly as before
- MCP-native --- runs as a Claude Code plugin with slash commands and hooks
What It Looks Like
Enable notifications
> /notify y
Notifications: enabled (voice)
You will hear spoken summaries when tasks complete and chimes when Claude needs input.
Get a recap
> /recap
Speaking: "I refactored the authentication module into three files, added
comprehensive tests for the token refresh flow, and fixed a race condition
in the session middleware. All 47 tests pass."
Set the vibe
> /vibe banging my head against the wall
Vibe: banging my head against the wall → [frustrated] [sighs] [manual]
Auto-mode (default) reads session signals and adapts automatically --- after a string of test failures the voice sounds [weary], after a successful release it sounds [excited].
Switch to chime-only
> /speak n
Speak: off (chime only)
Notifications will use audio tones instead of voice.
Commands
| Command | Purpose |
|---|---|
/notify y |
Speak on task completion and permission prompts |
/notify c |
Continuous --- also speak milestone updates during long tasks |
/notify n |
Off |
/speak y |
Notifications are spoken (default when /notify is on) |
/speak n |
Notifications are a chime --- no words |
/recap |
Spoken summary of Claude's last response |
/say "text" |
Speak arbitrary text aloud |
/vibe <mood> |
Set session mood --- voice adapts to match |
/vibe auto |
Auto-detect mood from session signals (default) |
/vibe off |
Disable vibe --- neutral voice |
/voice on | /voice off |
Enable/disable voice mode |
Providers
The full experience --- natural voice with expressive tags that respond to /vibe --- requires ElevenLabs. The other providers are fallbacks for environments where ElevenLabs isn't available.
| Provider | API Key | Default Voice | Best For |
|---|---|---|---|
| ElevenLabs | ELEVENLABS_API_KEY |
matilda | Recommended. Natural voice, expressive tags via /vibe |
| OpenAI | OPENAI_API_KEY |
nova | Fallback. Fast notifications, low latency |
| AWS Polly | AWS credentials | joanna | Fallback. Cost-effective, no API key needed |
| macOS say | — | fred | Fallback. Zero-config on macOS, offline |
| espeak-ng | — | en | Fallback. Zero-config on Linux, offline |
Auto-detection order: ElevenLabs > OpenAI > say (macOS) / espeak (Linux) > Polly.
CLI
punt-tts is also a standalone TTS tool, independent of Claude Code.
tts synthesize "Hello world" # Synthesize with default provider
tts synthesize "Hello" --provider elevenlabs # Use specific provider
tts doctor # Check setup
tts install # Install Claude Code plugin (marketplace)
tts uninstall # Remove plugin and clean up
tts install-desktop # Register MCP server with Claude Desktop
tts serve # Start MCP server (stdio)
Environment Variables
| Variable | Description | Default |
|---|---|---|
TTS_PROVIDER |
Force a specific provider | auto-detect |
TTS_MODEL |
Model override | provider default |
TTS_OUTPUT_DIR |
Output directory | ~/tts-output |
Roadmap
Shipped
- Notification layer:
/notify,/speak,/recap, Stop + Notification hooks - Multi-provider TTS engine: ElevenLabs, AWS Polly, OpenAI
- Claude Code plugin: marketplace install, MCP server, slash commands
- CLI: synthesize, batch, pair, pair-batch, doctor
- Ephemeral output mode (
.tts/in cwd) - Two-channel display:
♪panel summaries with voice/provider context - Playful stop hook phrases: randomized vocalization-themed messages ("Speaking my thoughts...", "Saying my piece...")
- Natural notification phrasing: randomized phrases for permission and idle prompts
- Audio playback serialization via
flock--- concurrent utterances queue instead of overlapping - ElevenLabs streaming API for lower time-to-first-audio
- Dev/prod namespace isolation for plugin testing (
claude --plugin-dir .) /vibewith auto, manual, and off modes --- ElevenLabs expressive tags color every utterance- Auto-vibe signal accumulator: test pass/fail, lint, git ops feed mood detection
set_configMCP tool for atomic config mutations (replaces file-tool pattern)- System fallback providers: macOS
sayand Linuxespeak-ngfor zero-config offline speech
Coming Soon
| Feature | What It Does |
|---|---|
| Per-session voices | Each Claude Code session gets its own voice from a pool --- no more five matildas talking at once. /voice to audition and pick. |
Documentation
Development
uv sync --all-extras # Install dependencies
uv run ruff check src/ tests/ # Lint
uv run ruff format --check src/ tests/ # Format
uv run mypy src/ tests/ # Type check (mypy)
uv run pyright src/ tests/ # Type check (pyright)
uv run pytest tests/ -v # Test
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file punt_tts-0.9.0.tar.gz.
File metadata
- Download URL: punt_tts-0.9.0.tar.gz
- Upload date:
- Size: 41.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3e6d0988138adde011b9d5b17379318e76f12fdacbee388b24af74d3070684d
|
|
| MD5 |
3b8b207ce2f5e2d57c36c01f9e166d0e
|
|
| BLAKE2b-256 |
1e8b075e359e521116806fe0f2b38ac46f385fc20403e2e8c8ff372ab7f217bb
|
Provenance
The following attestation bundles were made for punt_tts-0.9.0.tar.gz:
Publisher:
release.yml on punt-labs/tts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
punt_tts-0.9.0.tar.gz -
Subject digest:
c3e6d0988138adde011b9d5b17379318e76f12fdacbee388b24af74d3070684d - Sigstore transparency entry: 1006019137
- Sigstore integration time:
-
Permalink:
punt-labs/tts@9206ea296af296c1efb7090885fcbbffcf02d310 -
Branch / Tag:
refs/tags/v0.9.0 - Owner: https://github.com/punt-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9206ea296af296c1efb7090885fcbbffcf02d310 -
Trigger Event:
push
-
Statement type:
File details
Details for the file punt_tts-0.9.0-py3-none-any.whl.
File metadata
- Download URL: punt_tts-0.9.0-py3-none-any.whl
- Upload date:
- Size: 54.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
987aafba4282205f5ef2e0316e7f0e72df95b9d1d4930bf22c128173115e029d
|
|
| MD5 |
c81cf9dee04b87afc1282f418b65fd32
|
|
| BLAKE2b-256 |
2a59599d70041b12ff5f1ea83e83822bb1e59691d8e17a167d43560f8911aea6
|
Provenance
The following attestation bundles were made for punt_tts-0.9.0-py3-none-any.whl:
Publisher:
release.yml on punt-labs/tts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
punt_tts-0.9.0-py3-none-any.whl -
Subject digest:
987aafba4282205f5ef2e0316e7f0e72df95b9d1d4930bf22c128173115e029d - Sigstore transparency entry: 1006019141
- Sigstore integration time:
-
Permalink:
punt-labs/tts@9206ea296af296c1efb7090885fcbbffcf02d310 -
Branch / Tag:
refs/tags/v0.9.0 - Owner: https://github.com/punt-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9206ea296af296c1efb7090885fcbbffcf02d310 -
Trigger Event:
push
-
Statement type: