Add voice feedback to your Claude Code sessions! This project provides ready-to-use hooks that integrate PingVoice TTS (Text-to-Speech) into Claude Code, giving you audio notifications for session events and task completions.
- Session Greeting - Hear a personalized welcome when you start a Claude Code session
- Input Notifications - Get audio alerts when Claude needs your input
- Subagent Completion - Know when background tasks finish without watching the terminal
- Task Summaries - Claude announces what it accomplished after completing work (via output style)
Audio plays through your browser via the PingVoice Dashboard - no local TTS engine required!
- Claude Code installed and configured
- uv - Python package manager (handles dependencies automatically)
- A PingVoice account with an API key
Copy the entire .claude directory from this repository to your project root:
cp -r .claude /path/to/your/project/Or to set it up globally for all projects, copy to your home directory:
cp -r .claude ~/Create a .env file in the same location as the .claude directory:
# Required - Get your API key from the PingVoice Dashboard
PINGVOICE_API_KEY=your_api_key_here
# Optional - Override if your PingVoice API is hosted elsewhere
# PINGVOICE_API_URL=http://localhost/api/ttsThe hooks and output style use _USER_NAME_ as a placeholder. Replace it with your actual name:
Files to update:
| File | Find | Replace with |
|---|---|---|
.claude/hooks/session_start.py |
_USER_NAME_ |
Your name |
.claude/hooks/notification.py |
_USER_NAME_ |
Your name |
.claude/output-styles/tts-summary.md |
_USER_NAME_ |
Your name |
Quick replace with sed (replace YourName with your actual name):
# From your project root
find .claude -type f \( -name "*.py" -o -name "*.md" \) -exec sed -i 's/_USER_NAME_/YourName/g' {} +Launch Claude Code in your project directory. You should hear a greeting!
claudeClaude Code Event (e.g., session start)
↓
Hook triggers (defined in settings.json)
↓
Python script sends message to PingVoice API
↓
API queues the audio (responds with 202 Accepted)
↓
Audio plays in your browser via WebSocket
The system uses a fire-and-forget design - scripts send the TTS request and exit immediately, so they never block Claude Code.
.claude/
├── settings.json # Hook registration and permissions
├── hooks/
│ ├── session_start.py # Greeting when session begins
│ ├── notification.py # Alert when input is needed
│ ├── subagent_stop.py # Announcement when subagent completes
│ └── utils/
│ └── api_tts.py # Core TTS API client
└── output-styles/
└── tts-summary.md # Makes Claude announce task completions
The main configuration file that:
- Registers hooks with Claude Code's hook system
- Sets permissions to allow
uv runcommands - Activates the output style for task completion announcements
{
"permissions": {
"allow": ["Bash(uv run:*)"]
},
"hooks": {
"SessionStart": [...],
"Notification": [...],
"SubagentStop": [...]
},
"outputStyle": "TTS Summary"
}| Variable | Required | Default | Description |
|---|---|---|---|
PINGVOICE_API_KEY |
Yes | - | Your API authentication token |
PINGVOICE_API_URL |
No | http://localhost/api/tts |
TTS API endpoint URL |
Edit the message strings in the hook scripts:
- Session greeting:
.claude/hooks/session_start.py(line 20) - Input notification:
.claude/hooks/notification.py(line 20) - Subagent completion:
.claude/hooks/subagent_stop.py(line 20)
- Create a new Python script in
.claude/hooks/ - Follow the pattern of existing scripts (consume stdin, call api_tts.py)
- Register the hook in
.claude/settings.json
Available hook events:
SessionStart- When a session beginsNotification- When user input is neededSubagentStop- When a subagent task completesStop- When Claude stops generatingPreToolUse/PostToolUse- Before/after tool executionUserPromptSubmit- When user submits a prompt
- Disable specific hooks: Remove the corresponding entry from
settings.json - Disable task summaries: Remove
"outputStyle": "TTS Summary"fromsettings.json - Disable all TTS: Remove the entire
.claudedirectory
- Check your API key - Ensure
PINGVOICE_API_KEYis set correctly in.env - Open the PingVoice Dashboard - Audio plays in the browser, make sure the dashboard tab is open
- Check the API URL - If self-hosting, verify
PINGVOICE_API_URLis correct - Test manually:
uv run .claude/hooks/utils/api_tts.py "Test message"
Create a .env file in your project root (same level as .claude/):
PINGVOICE_API_KEY=your_api_key_herePingVoice has a rate limit of 10 requests per minute. If you're hitting this limit, consider:
- Disabling some hooks (e.g.,
SubagentStopif using many subagents) - Spacing out your Claude Code sessions
- Ensure
.claude/settings.jsonexists and has the hook configuration - Check that
"permissions": { "allow": ["Bash(uv run:*)"] }is present - Verify uv is installed:
uv --version
The output style requires Claude to execute a Bash command. If summaries aren't working:
- Verify the output style is active: check
"outputStyle": "TTS Summary"in settings.json - Make sure you replaced
_USER_NAME_in.claude/output-styles/tts-summary.md
MIT License - Feel free to modify and share!