The Rate Limiting Step
A chemical reaction's overall rate is bounded by its slowest step. Every sequential pipeline has the same constraint. As LLMs and agent harnesses improved, the rate-limiting step in many knowledge work pipelines became the human.
People have been working to reduce or eliminate this human bottleneck in a few distinct ways, but when I continued to notice persistent gaps I implemented some solutions of my own.
| Problem | What's being done |
|---|---|
| Prompting by typing is slow | Speech-to-text (Whisper, WhisperFlow) — humans speak ~3x faster than they type |
| Human approval gates interrupt execution | Auto-execution (micro) + loop engineering (macro) — remove per-action checkpoints. Set goals, let the agent run |
The gap nobody's filled: you want to stay in the loop, but reading agent output turn by turn is slow. Most solutions just remove the human. This one keeps them in it.
Most solutions attack this by reducing human involvement: loops, auto-execution, multi-agent setups. That works if you just want the task done. But if you're trying to learn something, debug something, or follow what the model is actually doing, you need to stay in the loop, so I set out to make that loop a little faster.
I built two small tools to address that gap. Both work by leaning into what human physiology is already good at: scanning familiar patterns quickly, and processing speech passively.
Giving Claude a Voice
Sometimes I'm not at the keyboard when a long task finishes. I set up an MCP server that gives Claude a speak() tool backed by macOS's built-in say command. It reads things back on request, or narrates long tasks while you step away from the screen.
88 lines, one dependency. I used the native macOS voice on purpose for the v1. Zero setup, zero cost, ships on every Mac. Kokoro is a potential v2 upgrade when I get tired of listening to a British robot.
I built it around an explicit tool call, not auto-readback. I don't want every tool call narrated. I want the signal without watching the terminal.
▸Technical details
~88 lines, one dependency: mcp[cli]. Runs via uv as a local MCP server.
Three tools: speak(text, voice?), stop(), list_voices(). speak() kills current audio, starts a new non-blocking Popen(["say", "-v", voice, text]), returns immediately. threading.Lock guards the process handle so concurrent calls don't race.
Default voice: Daniel (British). Configurable via $VOICEMODE_VOICE.
Config in ~/.claude/settings.json:
{ "mcpServers": { "voicemode": { "command": "uv", "args": ["run", "--project", "/path/to/voicemode-mcp", "voicemode-mcp"] } } }
Upgrade path: v2 is Kokoro-82M — local neural TTS, MIT license, ~300ms latency. v3 adds mlx-whisper for STT and gets to ~1–3s fully offline on M4.
Structured Digest
Claude's output is a mix of tool calls, code, prose, and status messages. Reading all of it after every turn is slow, and most of it doesn't matter.
The actual fix is two steps: reduce first, then format. A system prompt or slash command can tell the model to suppress verbose tool previews and skip code-processing status noise — pulling signal out at the source. What's left gets restructured by a Stop hook into a short digest:
──────────────────────────────────────────────────
[tools] Read ×2, Bash ×1, Edit ×1
[code] 2 block(s) — python, bash
[prose] APPlied BIonic FORMatting to PRose PArts
[next] Run The TEst SUite to VErify
──────────────────────────────────────────────────
Which tools ran, what code was touched, a compressed version of the prose, and the next action. The format does the work — the digest is structured so your eye goes straight to what matters. The prose also gets bionic-rendered (first ~40% of each word bolded). Controlled studies don't support speed claims for that. I keep it because it makes the digest visually distinct from raw terminal output — that's probably all it's doing.
The hook runs after each turn, not during — Claude Code streams directly to the terminal and there's no way to intercept mid-stream. The digest appends below. Fine. It's meant to compress, not replace.
Two things still to finish before it's fully wired in: locating the session transcript reliably and verifying the JSONL schema. The structure is done.
▸Technical details
Python, ~100 lines, no external dependencies. Fires as a Claude Code Stop hook. Runs as a local subprocess — no API calls, zero tokens.
System prompt or slash command handles upstream filtering: tell the model to suppress verbose tool previews, keep outputs tight. The hook processes whatever comes through.
Core transform: bionic_word() bolds the first 40% of letter characters in each word, skips words under 3 chars. bionic_prose() applies it line by line. ANSI formatting — works in any terminal.
Transcript parsing reads ~/.claude/projects/**/*.jsonl, takes the most recently modified file, finds the last assistant message, splits on code fences to separate prose from code blocks.
Two TODOs:
find_transcript()— verify the session transcript path; check ifCLAUDE_SESSION_IDis available in the hook environmentparse_last_response()— verify actual JSONL schema
Wire-up in .claude/settings.json:
{ "hooks": { "Stop": [{ "matcher": "", "hooks": [{"type": "command", "command": "python3 /path/to/bionic_hook.py"}] }] } }
Neither of these are polished, but I was able to implement each in under 30 minutes and they have noticeably improved some workflows. I'm particularly bullish on new formats for human-computer interaction that are more compatible with human physiology. We didn't evolve to sit at 90 degree angles, hunched over at flickering blue screens inside all day, but I feel the urge to experiment and build now more than ever. I'm excited to see what happens between now and full brain-computer takeover!
[repo link]