anvil-dev-framework 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +719 -0
- package/VERSION +1 -0
- package/docs/ANVIL-REPO-IMPLEMENTATION-PLAN.md +441 -0
- package/docs/FIRST-SKILL-TUTORIAL.md +408 -0
- package/docs/INSTALLATION-RETRO-NOTES.md +458 -0
- package/docs/INSTALLATION.md +984 -0
- package/docs/anvil-hud.md +469 -0
- package/docs/anvil-init.md +255 -0
- package/docs/anvil-state.md +210 -0
- package/docs/boris-cherny-ralph-wiggum-insights.md +608 -0
- package/docs/command-reference.md +2022 -0
- package/docs/hooks-tts.md +368 -0
- package/docs/implementation-guide.md +810 -0
- package/docs/linear-github-integration.md +247 -0
- package/docs/local-issues.md +677 -0
- package/docs/patterns/README.md +419 -0
- package/docs/planning-responsibilities.md +139 -0
- package/docs/session-workflow.md +573 -0
- package/docs/simplification-plan-template.md +297 -0
- package/docs/simplification-principles.md +129 -0
- package/docs/specifications/CCS-RALPH-INTEGRATION-DESIGN.md +633 -0
- package/docs/specifications/CCS-RESEARCH-REPORT.md +169 -0
- package/docs/specifications/PLAN-ANV-verification-ralph-wiggum.md +403 -0
- package/docs/specifications/PLAN-parallel-tracks-anvil-memory-ccs.md +494 -0
- package/docs/specifications/SPEC-ANV-VRW/component-01-verify.md +208 -0
- package/docs/specifications/SPEC-ANV-VRW/component-02-stop-gate.md +226 -0
- package/docs/specifications/SPEC-ANV-VRW/component-03-posttooluse.md +209 -0
- package/docs/specifications/SPEC-ANV-VRW/component-04-ralph-wiggum.md +604 -0
- package/docs/specifications/SPEC-ANV-VRW/component-05-atomic-actions.md +311 -0
- package/docs/specifications/SPEC-ANV-VRW/component-06-verify-subagent.md +264 -0
- package/docs/specifications/SPEC-ANV-VRW/component-07-claude-md.md +363 -0
- package/docs/specifications/SPEC-ANV-VRW/index.md +182 -0
- package/docs/specifications/SPEC-ANV-anvil-memory.md +573 -0
- package/docs/specifications/SPEC-ANV-context-checkpoints.md +781 -0
- package/docs/specifications/SPEC-ANV-verification-ralph-wiggum.md +789 -0
- package/docs/sync.md +122 -0
- package/global/CLAUDE.md +140 -0
- package/global/agents/verify-app.md +164 -0
- package/global/commands/anvil-settings.md +527 -0
- package/global/commands/anvil-sync.md +121 -0
- package/global/commands/change.md +197 -0
- package/global/commands/clarify.md +252 -0
- package/global/commands/cleanup.md +292 -0
- package/global/commands/commit-push-pr.md +207 -0
- package/global/commands/decay-review.md +127 -0
- package/global/commands/discover.md +158 -0
- package/global/commands/doc-coverage.md +122 -0
- package/global/commands/evidence.md +307 -0
- package/global/commands/explore.md +121 -0
- package/global/commands/force-exit.md +135 -0
- package/global/commands/handoff.md +191 -0
- package/global/commands/healthcheck.md +302 -0
- package/global/commands/hud.md +84 -0
- package/global/commands/insights.md +319 -0
- package/global/commands/linear-setup.md +184 -0
- package/global/commands/lint-fix.md +198 -0
- package/global/commands/orient.md +510 -0
- package/global/commands/plan.md +228 -0
- package/global/commands/ralph.md +346 -0
- package/global/commands/ready.md +182 -0
- package/global/commands/release.md +305 -0
- package/global/commands/retro.md +96 -0
- package/global/commands/shard.md +166 -0
- package/global/commands/spec.md +227 -0
- package/global/commands/sprint.md +184 -0
- package/global/commands/tasks.md +228 -0
- package/global/commands/test-and-commit.md +151 -0
- package/global/commands/validate.md +132 -0
- package/global/commands/verify.md +251 -0
- package/global/commands/weekly-review.md +156 -0
- package/global/hooks/__pycache__/ralph_context_monitor.cpython-314.pyc +0 -0
- package/global/hooks/__pycache__/statusline_agent_sync.cpython-314.pyc +0 -0
- package/global/hooks/anvil_memory_observe.ts +322 -0
- package/global/hooks/anvil_memory_session.ts +166 -0
- package/global/hooks/anvil_memory_stop.ts +187 -0
- package/global/hooks/parse_transcript.py +116 -0
- package/global/hooks/post_merge_cleanup.sh +132 -0
- package/global/hooks/post_tool_format.sh +215 -0
- package/global/hooks/ralph_context_monitor.py +240 -0
- package/global/hooks/ralph_stop.sh +502 -0
- package/global/hooks/statusline.sh +1110 -0
- package/global/hooks/statusline_agent_sync.py +224 -0
- package/global/hooks/stop_gate.sh +250 -0
- package/global/lib/.claude/anvil-state.json +21 -0
- package/global/lib/__pycache__/agent_registry.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/claim_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/coderabbit_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/config_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/coordination_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/doc_coverage_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/gate_logger.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/github_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/hygiene_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/issue_models.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/issue_provider.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/linear_data_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/linear_provider.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/local_provider.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/quality_service.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/ralph_state.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/state_manager.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/transcript_parser.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/verification_runner.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/verify_iteration.cpython-314.pyc +0 -0
- package/global/lib/__pycache__/verify_subagent.cpython-314.pyc +0 -0
- package/global/lib/agent_registry.py +995 -0
- package/global/lib/anvil-state.sh +435 -0
- package/global/lib/claim_service.py +515 -0
- package/global/lib/coderabbit_service.py +314 -0
- package/global/lib/config_service.py +423 -0
- package/global/lib/coordination_service.py +331 -0
- package/global/lib/doc_coverage_service.py +1305 -0
- package/global/lib/gate_logger.py +316 -0
- package/global/lib/github_service.py +310 -0
- package/global/lib/handoff_generator.py +775 -0
- package/global/lib/hygiene_service.py +712 -0
- package/global/lib/issue_models.py +257 -0
- package/global/lib/issue_provider.py +339 -0
- package/global/lib/linear_data_service.py +210 -0
- package/global/lib/linear_provider.py +987 -0
- package/global/lib/linear_provider.py.backup +671 -0
- package/global/lib/local_provider.py +486 -0
- package/global/lib/orient_fast.py +457 -0
- package/global/lib/quality_service.py +470 -0
- package/global/lib/ralph_prompt_generator.py +563 -0
- package/global/lib/ralph_state.py +1202 -0
- package/global/lib/state_manager.py +417 -0
- package/global/lib/transcript_parser.py +597 -0
- package/global/lib/verification_runner.py +557 -0
- package/global/lib/verify_iteration.py +490 -0
- package/global/lib/verify_subagent.py +250 -0
- package/global/skills/README.md +155 -0
- package/global/skills/quality-gates/SKILL.md +252 -0
- package/global/skills/skill-template/SKILL.md +109 -0
- package/global/skills/testing-strategies/SKILL.md +337 -0
- package/global/templates/CHANGE-template.md +105 -0
- package/global/templates/HANDOFF-template.md +63 -0
- package/global/templates/PLAN-template.md +111 -0
- package/global/templates/SPEC-template.md +93 -0
- package/global/templates/ralph/PROMPT.md.template +89 -0
- package/global/templates/ralph/fix_plan.md.template +31 -0
- package/global/templates/ralph/progress.txt.template +23 -0
- package/global/tests/__pycache__/test_doc_coverage.cpython-314.pyc +0 -0
- package/global/tests/test_doc_coverage.py +520 -0
- package/global/tests/test_issue_models.py +299 -0
- package/global/tests/test_local_provider.py +323 -0
- package/global/tools/README.md +178 -0
- package/global/tools/__pycache__/anvil-hud.cpython-314.pyc +0 -0
- package/global/tools/anvil-hud.py +3622 -0
- package/global/tools/anvil-hud.py.bak +3318 -0
- package/global/tools/anvil-issue.py +432 -0
- package/global/tools/anvil-memory/CLAUDE.md +49 -0
- package/global/tools/anvil-memory/README.md +42 -0
- package/global/tools/anvil-memory/bun.lock +25 -0
- package/global/tools/anvil-memory/bunfig.toml +9 -0
- package/global/tools/anvil-memory/package.json +23 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/context-monitor.test.ts +535 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/edge-cases.test.ts +645 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/fixtures.ts +363 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/index.ts +8 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/integration.test.ts +417 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/prompt-generator.test.ts +571 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/ralph-stop.test.ts +440 -0
- package/global/tools/anvil-memory/src/__tests__/ccs/test-utils.ts +252 -0
- package/global/tools/anvil-memory/src/__tests__/commands.test.ts +657 -0
- package/global/tools/anvil-memory/src/__tests__/db.test.ts +641 -0
- package/global/tools/anvil-memory/src/__tests__/hooks.test.ts +272 -0
- package/global/tools/anvil-memory/src/__tests__/performance.test.ts +427 -0
- package/global/tools/anvil-memory/src/__tests__/test-utils.ts +113 -0
- package/global/tools/anvil-memory/src/commands/checkpoint.ts +197 -0
- package/global/tools/anvil-memory/src/commands/get.ts +115 -0
- package/global/tools/anvil-memory/src/commands/init.ts +94 -0
- package/global/tools/anvil-memory/src/commands/observe.ts +163 -0
- package/global/tools/anvil-memory/src/commands/search.ts +112 -0
- package/global/tools/anvil-memory/src/db.ts +638 -0
- package/global/tools/anvil-memory/src/index.ts +205 -0
- package/global/tools/anvil-memory/src/types.ts +122 -0
- package/global/tools/anvil-memory/tsconfig.json +29 -0
- package/global/tools/ralph-loop.sh +359 -0
- package/package.json +45 -0
- package/scripts/anvil +822 -0
- package/scripts/extract_patterns.py +222 -0
- package/scripts/init-project.sh +541 -0
- package/scripts/install.sh +229 -0
- package/scripts/postinstall.js +41 -0
- package/scripts/rollback.sh +188 -0
- package/scripts/sync.sh +623 -0
- package/scripts/test-statusline.sh +248 -0
- package/scripts/update_claude_md.py +224 -0
- package/scripts/verify.sh +255 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Hooks: Text-to-Speech (TTS) Configuration
|
|
2
|
+
|
|
3
|
+
> Audio notifications for Claude Code session events.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Anvil hooks include TTS (text-to-speech) capabilities to announce when Claude needs your input or when tasks complete. This provides an audio cue so you can multitask while Claude works.
|
|
10
|
+
|
|
11
|
+
**TTS Priority Order:**
|
|
12
|
+
|
|
13
|
+
| Priority | Engine | Platform | Latency | Cost |
|
|
14
|
+
|----------|--------|----------|---------|------|
|
|
15
|
+
| 1 | MLX Audio (Kokoro) | Apple Silicon only | ~300ms | Free (local) |
|
|
16
|
+
| 2 | ElevenLabs | All platforms | ~500ms | API costs |
|
|
17
|
+
| 3 | OpenAI TTS | All platforms | ~400ms | API costs |
|
|
18
|
+
| 4 | pyttsx3 | All platforms | ~50ms | Free (local) |
|
|
19
|
+
| 5 | macOS `say` | macOS only | ~10ms | Free (system) |
|
|
20
|
+
|
|
21
|
+
The system automatically selects the best available option based on your platform and configured API keys.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## MLX Audio (Kokoro) - Recommended for Mac
|
|
26
|
+
|
|
27
|
+
MLX Audio with the Kokoro-82M model provides high-quality, natural-sounding speech at ~300ms latency, running entirely locally on Apple Silicon Macs.
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
30
|
+
|
|
31
|
+
**1. Install espeak (required dependency):**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
brew install espeak
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**2. First run downloads the model:**
|
|
38
|
+
|
|
39
|
+
The Kokoro-82M model (~330MB) downloads automatically on first use to `~/.cache/huggingface/`.
|
|
40
|
+
|
|
41
|
+
**3. Dependencies are managed by uv:**
|
|
42
|
+
|
|
43
|
+
The script uses inline dependencies with uv, so no manual pip install is needed.
|
|
44
|
+
|
|
45
|
+
### How It Works
|
|
46
|
+
|
|
47
|
+
The `mlx_audio_tts.py` script:
|
|
48
|
+
1. Loads the Kokoro-82M model via MLX framework
|
|
49
|
+
2. Generates audio using the `af_heart` voice at 1.1x speed
|
|
50
|
+
3. Plays audio via macOS `afplay`
|
|
51
|
+
4. Falls back to macOS `say` on any error
|
|
52
|
+
|
|
53
|
+
### Configuration
|
|
54
|
+
|
|
55
|
+
Located at: `project/hooks/utils/tts/mlx_audio_tts.py`
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# Default settings
|
|
59
|
+
voice = "af_heart" # American female, warm voice
|
|
60
|
+
speed = 1.1 # Slightly faster than normal
|
|
61
|
+
lang_code = "a" # American English
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Available voices:**
|
|
65
|
+
- `af_heart` - American female (default, warm)
|
|
66
|
+
- `af_bella` - American female (clear)
|
|
67
|
+
- `af_nicole` - American female (professional)
|
|
68
|
+
- `am_adam` - American male
|
|
69
|
+
- `am_michael` - American male
|
|
70
|
+
- `bf_emma` - British female
|
|
71
|
+
- `bm_george` - British male
|
|
72
|
+
|
|
73
|
+
### Manual Testing
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Test MLX Audio directly
|
|
77
|
+
uv run project/hooks/utils/tts/mlx_audio_tts.py "Test complete"
|
|
78
|
+
|
|
79
|
+
# Test with different voice
|
|
80
|
+
uv run project/hooks/utils/tts/mlx_audio_tts.py --voice am_adam "Hello world"
|
|
81
|
+
|
|
82
|
+
# Test with different speed
|
|
83
|
+
uv run project/hooks/utils/tts/mlx_audio_tts.py --speed 1.3 "Faster speech"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Resource Usage
|
|
87
|
+
|
|
88
|
+
- **Model size**: ~330MB download (cached)
|
|
89
|
+
- **Memory**: ~4.4GB peak during generation
|
|
90
|
+
- **Latency**: ~300ms for short phrases
|
|
91
|
+
- **CPU/GPU**: Uses Metal acceleration on Apple Silicon
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## ElevenLabs (API)
|
|
96
|
+
|
|
97
|
+
High-quality cloud-based TTS with natural voices.
|
|
98
|
+
|
|
99
|
+
### Setup
|
|
100
|
+
|
|
101
|
+
1. Get API key from [ElevenLabs](https://elevenlabs.io)
|
|
102
|
+
2. Set environment variable:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
export ELEVENLABS_API_KEY="your_api_key_here"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Configuration
|
|
109
|
+
|
|
110
|
+
Located at: `project/hooks/utils/tts/elevenlabs_tts.py`
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## OpenAI TTS (API)
|
|
115
|
+
|
|
116
|
+
OpenAI's text-to-speech API.
|
|
117
|
+
|
|
118
|
+
### Setup
|
|
119
|
+
|
|
120
|
+
1. Get API key from [OpenAI](https://platform.openai.com)
|
|
121
|
+
2. Set environment variable:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
export OPENAI_API_KEY="your_api_key_here"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Configuration
|
|
128
|
+
|
|
129
|
+
Located at: `project/hooks/utils/tts/openai_tts.py`
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## pyttsx3 (Fallback)
|
|
134
|
+
|
|
135
|
+
Offline TTS using system voices. Works on all platforms but sounds robotic.
|
|
136
|
+
|
|
137
|
+
### Setup
|
|
138
|
+
|
|
139
|
+
No configuration needed. Installed automatically via uv dependencies.
|
|
140
|
+
|
|
141
|
+
### Configuration
|
|
142
|
+
|
|
143
|
+
Located at: `project/hooks/utils/tts/pyttsx3_tts.py`
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## TTS Events
|
|
148
|
+
|
|
149
|
+
TTS is triggered by multiple Claude Code hooks for different events:
|
|
150
|
+
|
|
151
|
+
### Event Reference
|
|
152
|
+
|
|
153
|
+
| Hook | Event | TTS Message | When |
|
|
154
|
+
|------|-------|-------------|------|
|
|
155
|
+
| `SessionStart` | Session begins | "Claude Code session started" | New session, resume, or clear |
|
|
156
|
+
| `Stop` | Claude finishes | "Work complete!" (varies) | Claude stops responding |
|
|
157
|
+
| `Notification` | Needs input | "Your agent needs your input" | Waiting for user |
|
|
158
|
+
| `PostToolUse` | Plan complete | "Planning complete. Ready for your review." | After `ExitPlanMode` |
|
|
159
|
+
| `PreToolUse` | Question asked | "I have a question for you." | Before `AskUserQuestion` |
|
|
160
|
+
| `PostToolUse` | Tests run | "Tests passed." / "Tests failed." | After test commands |
|
|
161
|
+
| `PostToolUse` | Build run | "Build complete." / "Build failed." | After build commands |
|
|
162
|
+
| `PostToolUse` | Lint run | "Lint passed." / "Lint issues found." | After lint commands |
|
|
163
|
+
| `PostToolUse` | Agent done | "Agent task finished." | After `Task` tool |
|
|
164
|
+
|
|
165
|
+
### Enabling TTS Events
|
|
166
|
+
|
|
167
|
+
TTS is controlled by flags in `.claude/settings.local.json`:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"hooks": {
|
|
172
|
+
"SessionStart": [{
|
|
173
|
+
"hooks": [{
|
|
174
|
+
"command": "uv run .claude/hooks/session_start.py --announce"
|
|
175
|
+
}]
|
|
176
|
+
}],
|
|
177
|
+
"PreToolUse": [{
|
|
178
|
+
"hooks": [{
|
|
179
|
+
"command": "uv run .claude/hooks/pre_tool_use.py --announce"
|
|
180
|
+
}]
|
|
181
|
+
}],
|
|
182
|
+
"PostToolUse": [{
|
|
183
|
+
"hooks": [{
|
|
184
|
+
"command": "uv run .claude/hooks/post_tool_use.py --announce"
|
|
185
|
+
}]
|
|
186
|
+
}],
|
|
187
|
+
"Notification": [{
|
|
188
|
+
"hooks": [{
|
|
189
|
+
"command": "uv run .claude/hooks/notification.py --notify"
|
|
190
|
+
}]
|
|
191
|
+
}],
|
|
192
|
+
"Stop": [{
|
|
193
|
+
"hooks": [{
|
|
194
|
+
"command": "uv run .claude/hooks/stop.py --chat --cleanup-agent"
|
|
195
|
+
}]
|
|
196
|
+
}]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Note:** The `Stop` hook always announces completion (no flag needed).
|
|
202
|
+
|
|
203
|
+
### Detected Commands
|
|
204
|
+
|
|
205
|
+
The `PostToolUse` hook detects these command patterns:
|
|
206
|
+
|
|
207
|
+
**Test commands:**
|
|
208
|
+
- `npm test`, `npm run test`
|
|
209
|
+
- `pytest`, `vitest`, `jest`
|
|
210
|
+
- `cargo test`, `go test`
|
|
211
|
+
|
|
212
|
+
**Build commands:**
|
|
213
|
+
- `npm run build`, `npm build`
|
|
214
|
+
- `cargo build`, `go build`
|
|
215
|
+
- `make build`, `tsc`
|
|
216
|
+
|
|
217
|
+
**Lint commands:**
|
|
218
|
+
- `npm run lint`, `eslint`
|
|
219
|
+
- `prettier`, `cargo clippy`
|
|
220
|
+
|
|
221
|
+
### Relevant Files
|
|
222
|
+
|
|
223
|
+
| File | Purpose |
|
|
224
|
+
|------|---------|
|
|
225
|
+
| `hooks/session_start.py` | Session start announcement |
|
|
226
|
+
| `hooks/pre_tool_use.py` | Pre-tool announcements (AskUserQuestion) |
|
|
227
|
+
| `hooks/post_tool_use.py` | Post-tool announcements (tests, builds, etc.) |
|
|
228
|
+
| `hooks/stop.py` | Completion announcement |
|
|
229
|
+
| `hooks/notification.py` | Input needed announcement |
|
|
230
|
+
| `hooks/utils/tts/mlx_audio_tts.py` | MLX Audio engine |
|
|
231
|
+
| `hooks/utils/tts/elevenlabs_tts.py` | ElevenLabs engine |
|
|
232
|
+
| `hooks/utils/tts/openai_tts.py` | OpenAI engine |
|
|
233
|
+
| `hooks/utils/tts/pyttsx3_tts.py` | pyttsx3 engine |
|
|
234
|
+
|
|
235
|
+
### TTS Selection Logic
|
|
236
|
+
|
|
237
|
+
All hooks use the same priority order:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
def get_tts_script_path():
|
|
241
|
+
# 1. MLX Audio for Apple Silicon (free, fast, local)
|
|
242
|
+
if is_apple_silicon():
|
|
243
|
+
if mlx_script.exists():
|
|
244
|
+
return mlx_script
|
|
245
|
+
|
|
246
|
+
# 2. ElevenLabs if API key set (highest quality)
|
|
247
|
+
if os.getenv('ELEVENLABS_API_KEY'):
|
|
248
|
+
return elevenlabs_script
|
|
249
|
+
|
|
250
|
+
# 3. OpenAI TTS if API key set
|
|
251
|
+
if os.getenv('OPENAI_API_KEY'):
|
|
252
|
+
return openai_script
|
|
253
|
+
|
|
254
|
+
# 4. pyttsx3 as offline fallback
|
|
255
|
+
return pyttsx3_script
|
|
256
|
+
|
|
257
|
+
# 5. If none available, use macOS `say`
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Disabling TTS
|
|
263
|
+
|
|
264
|
+
To disable TTS entirely, remove the `--notify` flag from the notification hook in `.claude/settings.local.json`:
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"hooks": {
|
|
269
|
+
"notification": [".claude/hooks/notification.py"]
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The `--notify` flag enables TTS:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"hooks": {
|
|
279
|
+
"notification": [".claude/hooks/notification.py --notify"]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Troubleshooting
|
|
287
|
+
|
|
288
|
+
### MLX Audio not working
|
|
289
|
+
|
|
290
|
+
**Symptom**: Falls back to macOS `say`
|
|
291
|
+
|
|
292
|
+
**Solutions:**
|
|
293
|
+
1. Verify Apple Silicon: `uname -m` should show `arm64`
|
|
294
|
+
2. Install espeak: `brew install espeak`
|
|
295
|
+
3. Check Python version: Requires Python 3.11-3.13 (not 3.14+)
|
|
296
|
+
4. Test directly: `uv run project/hooks/utils/tts/mlx_audio_tts.py "test"`
|
|
297
|
+
|
|
298
|
+
### Model download failed
|
|
299
|
+
|
|
300
|
+
**Symptom**: Network error during first run
|
|
301
|
+
|
|
302
|
+
**Solutions:**
|
|
303
|
+
1. Check internet connection
|
|
304
|
+
2. Clear cache: `rm -rf ~/.cache/huggingface/hub/models--prince-canuma--Kokoro-82M`
|
|
305
|
+
3. Try again
|
|
306
|
+
|
|
307
|
+
### High memory usage
|
|
308
|
+
|
|
309
|
+
**Symptom**: System slows during TTS
|
|
310
|
+
|
|
311
|
+
**Solutions:**
|
|
312
|
+
1. Expected: MLX Audio uses ~4.4GB during generation
|
|
313
|
+
2. Close other memory-intensive apps
|
|
314
|
+
3. Or use pyttsx3/macOS say (lower quality, lower memory)
|
|
315
|
+
|
|
316
|
+
### No audio output
|
|
317
|
+
|
|
318
|
+
**Symptom**: Script runs but no sound
|
|
319
|
+
|
|
320
|
+
**Solutions:**
|
|
321
|
+
1. Check system volume
|
|
322
|
+
2. Verify audio device: `afplay /System/Library/Sounds/Ping.aiff`
|
|
323
|
+
3. Check for audio routing issues (headphones, Bluetooth)
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Adding Custom TTS Engines
|
|
328
|
+
|
|
329
|
+
To add a new TTS engine:
|
|
330
|
+
|
|
331
|
+
1. Create `project/hooks/utils/tts/your_engine.py`:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
#!/usr/bin/env -S uv run --script
|
|
335
|
+
# /// script
|
|
336
|
+
# requires-python = ">=3.11"
|
|
337
|
+
# dependencies = ["your-tts-library"]
|
|
338
|
+
# ///
|
|
339
|
+
|
|
340
|
+
import sys
|
|
341
|
+
import subprocess
|
|
342
|
+
|
|
343
|
+
def speak(text: str) -> bool:
|
|
344
|
+
try:
|
|
345
|
+
# Your TTS implementation
|
|
346
|
+
return True
|
|
347
|
+
except Exception:
|
|
348
|
+
subprocess.run(['say', text], capture_output=True)
|
|
349
|
+
return False
|
|
350
|
+
|
|
351
|
+
def main():
|
|
352
|
+
text = sys.argv[1] if len(sys.argv) > 1 else "Task complete"
|
|
353
|
+
speak(text)
|
|
354
|
+
|
|
355
|
+
if __name__ == "__main__":
|
|
356
|
+
main()
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
2. Update `notification.py` to include your engine in the priority chain.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## References
|
|
364
|
+
|
|
365
|
+
- [MLX Audio GitHub](https://github.com/Blaizzy/mlx-audio)
|
|
366
|
+
- [Kokoro Model](https://huggingface.co/prince-canuma/Kokoro-82M)
|
|
367
|
+
- [ElevenLabs API](https://elevenlabs.io/docs)
|
|
368
|
+
- [OpenAI TTS API](https://platform.openai.com/docs/guides/text-to-speech)
|