How you get "button / hotkey speak" inside Claude Code
The capture is automatic
• Claude Code: Stop hook (hooks/save-last.js) quietly writes cleaned text to last-response.txt on every final response.
• In Claude Code: /speak command or hotkey runs the speaker on captured output.
Auto-speak is opt-in via autoSpeak config (0.2.0+). Default: off. The LLM output is captured and made speakable on demand (or auto if enabled).
The "button"
Recommended: Global hotkey → runs scripts/speak.ps1 (or python speaker.py --last)
• Windows: PowerToys Keyboard Manager or AutoHotkey (e.g. Ctrl+Alt+S)
• Status line shows 🔊 last ~12s (hotkey or /speak)
• Claude: also type /speak
• In Claude Code: /speak or hotkey; in Claude: say "speak..."
This is the closest thing to a speaker button in the current terminal UIs.
Use visualizer to test config, then install as Claude Code plugin for full hotkey + status + /speak experience.
After changing config, try "speak last result with current voice" — Grok will call the real script.
Important: Nothing has been installed into any real Claude Code instance.
All testing so far has been done by directly calling the speak scripts from this Grok chat using the terminal tool.
Default engine is now edge-tts (Aria) with playsound for clean playback. OutLoud rebrand + autoSpeak landed in 0.2.0.
Reads responses aloud automatically after Stop hook (when on).
Truncate long responses (chars).
Skip code blocks in auto narration (recommended).
This console is interactive in your browser. Clicking "Ask Grok to Apply" will give me the exact text to execute right now using the terminal tool. Uses current project default (edge-tts + Aria + autospeak keys in 0.2.0).
Speaker Flows — Grok Build vs Claude Code
flowchart TB
subgraph "Claude Code (full plugin)"
CCQ[User question in Claude Code] --> CCResp[Claude finishes response]
CCResp --> StopHook[Stop Hook hooks/save-last.js clean text]
StopHook --> LastFile[(last-response.txt %APPDATA% or ~/.config)]
end
subgraph "Grok Build (direct for dev)"
GQ[User question in Grok] --> GResp[Grok outputs text]
GResp --> GTerm[Grok terminal tool or 'speak the summary']
GTerm --> DirectSpeak[scripts/speak.ps1 or speaker.py "..."]
DirectSpeak --> LastFile
end
LastFile --> Trigger{How speak is triggered}
Trigger -->|Hotkey / Button| SpeakScript
Trigger -->|/speak or 'speak last'| SpeakScript
Trigger -->|Grok ask to speak| SpeakScript
SpeakScript[speak.ps1 / speaker.py (checks config.json)]
SpeakScript --> Engine{engine?}
Engine -->|native| Native[Windows SAPI fast zero-dep]
Engine -->|edge-tts ★| Edge[edge-tts Microsoft Neural save .mp3]
Engine -->|pyttsx3| Pyttsx[native wrapper]
Engine -->|kokoro| Kokoro[Kokoro local neural (supported)]
Edge --> Playsound[playsound (clean playback) no/minimal window]
Playsound --> Audio[Audio output]
Native --> Audio
Pyttsx --> Audio
Kokoro --> Audio
style LastFile fill:#1e3a5f,color:#bae6fd
style SpeakScript fill:#1e40af,color:#bfdbfe
style Edge fill:#166534,color:#86efac
style Playsound fill:#166534,color:#86efac
Capture Layer
Stop hook (Claude) or direct invoke (Grok). Only saves cleaned text. Never triggers audio itself.
Dispatch + Playback
Reads config (default edge-tts + Aria). edge-tts uses playsound for clean MP3 playback after streaming.
On-Demand Only
autoSpeak opt-in (0.2.0). Default off. User/hotkey//speak on|off|stop or direct ask triggers (or auto-narrates when enabled).
Current primary path: edge-tts → generate mp3 → playsound (block=True) → delete temp file. Falls back gracefully.
All work is local to this folder. No changes made to any Claude Code installation.
Current focus: edge-tts (Aria) + playsound for clean playback. Hotkey + /speak on/off/stop + autoSpeak + direct Grok speak. OutLoud 0.2.0.