I usually have four or five Claude Code sessions running in tmux, one per client site. The slow part of my day isn't the agents. It's me noticing that one of them finished, or has been sitting on a permission prompt for ten minutes while I looked at something else.
So I gave them a voice.
Reading the whole reply is unbearable
Claude Code runs a Stop hook after every turn, and the hook gets the final message on stdin. Piping that straight into text-to-speech works for about five minutes. Then it reads you a file path, a diff summary and a bulleted list, and you rip it out.
What you want to hear is one or two sentences: what got done, or what it needs from you.
Summarize first, then speak
My first try asked the model to end every reply with a line starting SPOKEN: and the hook read just that line. It worked, but the line showed up on screen in every reply, and I couldn't hide it.
Now the hook sends the reply to a small, cheap model and speaks what comes back. A few details mattered more than I expected:
- Long replies keep their beginning and their end. The question for me is almost always in the last paragraph.
- Small models embellish short inputs. A one-line reply sometimes came back with steps that never happened, so short replies need care.
- If the summary call fails, fall back to the first few hundred characters with code blocks, links and paths stripped out.
Several sessions at once
With five sessions, two of them sometimes finish at the same moment and talk over each other, and a generic "Claude needs your permission" doesn't say which one.
- Every message starts with the tmux window name, so I hear "Kissimmee. Claude needs your permission."
- A machine-wide lock queues speech, so sessions take turns instead of overlapping.
- Each session only speaks its newest event. A slow summary of an old turn gets dropped instead of interrupting the current one.
- Headless runs stay silent. Scheduled jobs shouldn't start talking in an empty room.
The voice
The built-in macOS voices were the weakest part. I tried a few open models locally on Apple Silicon. Kokoro, an 82 million parameter model, sounded far better than the system voices and renders a sentence in about a third of a second when kept warm in a small local server. A 4 billion parameter model sounded a little more natural but took over three seconds per summary, which is too slow for a notification.
What I'd tell someone trying this
Most of the value came from two decisions, not from the voice: what's worth interrupting me for, and saying which session it came from. A plain system voice would have been fine once those were right.