
Local voice AI / 7 guides
The Local voice AI build
Connect dictation, a local language model, and speech output on your Mac, from installation to a working voice workflow.
What you’ll build
Your voice, processed on your Mac.
Use NautPin for dictation, LM Studio or Ollama for text processing, and Kokoro for speech output. Install the parts, connect their local endpoints, and test the result.
- Stack
- NautPin · Kokoro · LM Studio or Ollama
- Hardware
- Apple Silicon Mac · macOS 14+ · about 10 GB free
- You need
- Homebrew, a container runtime, and Xcode for the source build
- Format
- Written lessons, commands, and checkpoints
7 lessons, in order
- 01
Prepare your Mac
Understand the components and check what you need before installing.
- 02
Set up the container runtime
Choose Colima or Docker Desktop and confirm Docker is ready.
- 03
Run local speech output
Start Kokoro and choose a voice for text-to-speech.
- 04
Run a local language model
Expose a local chat endpoint with LM Studio or Ollama.
- 05
Install NautPin
Build the dictation app and grant the permissions it needs.
- 06
Connect and test the voice stack
Wire transcription, local text processing, and speech output together.
- 07
Keep the stack working
Diagnose connection problems and recover after a restart.
Optional: let your coding agent help with setup
Use this prompt with an agent that can work on your Mac. Review its proposed actions before it installs or changes anything.
Hand it to your agent
If you use Claude Code, Cursor, Codex, or any other agent CLI — paste the prompt below. It walks the same six phases as the manual guide, asks you to confirm before each one, and tells you what to grant permission to. Follow the lessons above if you prefer the manual setup.
Paste into your agent
You are installing the 48nauts Local Voice Stack on macOS Apple Silicon.
# Goal
A complete local voice stack on this machine:
- Kokoro TTS (Docker, port 8880)
- A local LLM via LM Studio or Ollama (OpenAI-compatible API on localhost)
- NautPin dictation app in /Applications
- All services talking over 127.0.0.1; nothing on the network
# Prerequisites — confirm with me before starting
- macOS 14+ on Apple Silicon (M1 or newer)
- Homebrew installed (https://brew.sh)
- ~10 GB free disk space
- I will grant microphone + accessibility permissions when prompted
# Execution rules
- Execute ONE phase, then summarize what changed and ASK before the next phase
- If a command fails, diagnose before retrying; do not loop on errors
- Never bypass macOS permission prompts — pause and let me click through
- Don't commit anything to my git unless I explicitly ask
# Phase 1 — Docker via Colima (free, lightweight)
brew install colima docker docker-compose just
colima start --cpu 2 --memory 4
docker info # verify daemon responsive
# Phase 2 — Kokoro TTS container
docker run -d --name kokoro --restart unless-stopped \
-p 127.0.0.1:8880:8880 \
ghcr.io/remsky/kokoro-fastapi-cpu:latest
curl -s http://127.0.0.1:8880/v1/audio/voices | jq '.voices | length'
# should return 60+
# Phase 3 — Local LLM
Ask me whether to install LM Studio (GUI) or Ollama (CLI).
- LM Studio:
Open https://lmstudio.ai, drag to /Applications
Walk me through downloading a compatible instruction-tuned model
In Developer tab, load the model + start API server on :1234
Verify: curl http://127.0.0.1:1234/v1/models
- Ollama:
brew install ollama
brew services start ollama
ollama pull gemma3:4b
Verify: curl http://127.0.0.1:11434/v1/models
# Phase 4 — NautPin
git clone https://github.com/48Nauts-Operator/NautPin.git ~/Code/NautPin
cd ~/Code/NautPin
just build
cp -R DerivedData/Build/Products/Debug/NautPin.app /Applications/
open /Applications/NautPin.app
Tell me to grant Microphone + Accessibility permissions in
System Settings → Privacy & Security, then continue.
# Phase 5 — Configure NautPin (walk me through; cannot script)
Open NautPin → Settings:
- Speech: Parakeet TDT 0.6B v3 (European multilingual)
- AI Enhancement → Providers → add Custom (OpenAI-compatible):
Base URL → http://127.0.0.1:1234/v1 (LM Studio)
OR http://127.0.0.1:11434/v1 (Ollama)
API key → any string ("local" works)
Default model → the model ID from phase 3
- AI Enhancement → Assignments: set Transcription + Note Enhancement to this provider
- Voice Output:
Kokoro server URL → http://127.0.0.1:8880
Default voice → bf_emma
Read Selected Text hotkey → ⌘⇧S (or my preference)
# Phase 6 — Smoke test
Tell me to focus a text field, press the dictation hotkey, speak a sentence,
press again. Confirm cleaned text appears at my cursor.
Then highlight text and press the Read hotkey. Confirm Emma reads it aloud.
# Done
Print a one-line summary of what was installed and where, plus the
"uninstall to roll back" commands. Link me back to
https://48nauts.com/learnings/articles/local-voice-stack for context.The prompt is intentionally cautious — it stops between phases and asks. If you want fully autonomous, add --dangerously-skip-permissions (Claude Code) and tell the agent to skip the confirmation prompts. We don't recommend it for a first run.
Optional extension: spoken replies from a coding agent
This extension needs the separate speak.sh source referenced in the original post. It is not included in this series; the seven core lessons work without it.
If you use Claude Code in the terminal and want voice replies, drop in our Stop hook.
Create ~/.claude/hooks/speak.sh with the contents of speak.sh (the separate hook source is not included here).
Make it executable:
bash
chmod +x ~/.claude/hooks/speak.shRegister the hook in ~/.claude/settings.json:
~/.claude/settings.json
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{ "type": "command", "command": "/Users/YOU/.claude/hooks/speak.sh" }
]
}
]
}
}After obtaining the hook source and configuring it, restart your coding-agent session and verify a short reply is spoken.
Mute temporarily without uninstalling:
bash
touch ~/.claude/voice-off # mute
rm ~/.claude/voice-off # unmuteOr use the slash commands /voice and /voice-off that ship with the repo.