jarvis-voice
Requirements: macOS, Python 3, portaudio (via Homebrew), an ElevenLabs API key + voice ID, and a Telegram bot token/chat ID โ full walkthrough in SETUP.md.
A wake-word voice loop for talking to your own AI agent out loud, Jarvis-style. Say "Hey Neo," it answers "Peace god," and from there you talk back and forth until you say "Peace god" again to end the session.
This is the whole thing in one file: neo-voice-assistant.py. No framework, no
server โ just a while True: loop wired to three pieces:
EARS โ BRAIN โ MOUTH
mic/STT your agent TTS
(local) (via Telegram) (ElevenLabs, falls back to macOS `say`)
Why this matters
Most "voice assistant" tutorials give you a wake word and a canned response. This one routes every question to a real agent โ whatever you've already got running that listens on Telegram (a Claude Code agent, an n8n flow, a cron job with a bot token, anything) โ and speaks back whatever that agent says. The mic and the speaker are the only new surface area; your actual brain stays wherever it already lives.
How it works
- Ears โ
speech_recognitionlistens on your Mac's mic, transcribes locally in short chunks, and watches for a wake phrase ("hey neo," "hey nio," a few near-miss variants for STT noise). - Brain โ once activated, everything you say gets POSTed to a Telegram bot as
[VOICE] <your text>, then the script pollsgetUpdatesfor up to 40 seconds waiting for a bot reply in that same chat. Whatever agent is behind that bot token is the actual brain โ this script doesn't know or care what it is. - Mouth โ the reply is cleaned of markdown, capped to 800 characters, and
streamed through ElevenLabs' TTS API in your cloned (or chosen) voice. If the
ElevenLabs call fails for any reason, it falls back to macOS's built-in
sayso the loop never goes silent.
Say "peace god," "goodbye," "shut down," or "go to sleep" to end the conversation and drop back to wake-word listening. Say the wake word again mid-conversation and it just re-acknowledges you instead of restarting.
Quickstart
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp env.example .env
# fill in ELEVENLABS_API_KEY, ELEVENLABS_VOICE_ID, NEO_TELEGRAM_BOT_TOKEN, NEO_TELEGRAM_CHAT_ID
python3 neo-voice-assistant.py
The script refuses to start if any of the four env vars are missing โ it fails loud instead of silently falling back to something broken.
You'll need:
- A Mac with a working microphone (it auto-picks a "MacBook"/"Built-in" input if
one exists, otherwise the system default).
- afplay and say, both stock on macOS โ no extra install.
- An ElevenLabs account and API key, plus a voice ID (clone your own voice in
their dashboard, or use any voice from their library).
- A Telegram bot (via @BotFather) and the chat ID it
talks in, wired to whatever agent you want answering.
Make it your own
- Swap the brain. The only contract is "POST a message, poll the same chat for
a bot reply." Point
NEO_TELEGRAM_BOT_TOKEN/NEO_TELEGRAM_CHAT_IDat any bot backed by any agent โ the voice loop doesn't need to change. - Change the wake word and exit phrases. Edit the
WAKE_WORDSandEXIT_WORDSlists at the top of the file. - Swap the personality. Change what
speak("Peace god...")says on activation and what it says on sign-off โ those are the only two hardcoded lines. - Go fully local for the mouth. This version calls ElevenLabs (cloud) with a
sayfallback. If you want the whole loop to run offline, replace the body ofspeak()with a local TTS call instead of thehttpx.post(...)block โ Chatterbox (MIT-licensed voice cloning, runs well on Apple Silicon) via mlx-audio is a solid drop-in: clone a voice once, generate audio locally with no API key and no per-character cost, and keep ElevenLabs (orsay) as the fallback tier if the local model errors out. That gives you the same three-tier fallback chain โ local model, cloud API, OS built-in โ with nothing but the OSsaycommand required to always work. - Change how it listens.
listen()uses Google's free Web Speech API throughspeech_recognitionโ swap in a local Whisper model if you want STT offline too.
Files
neo-voice-assistant.pyโ the full loop: ears, brain routing, mouth.requirements.txtโSpeechRecognition,httpx,PyAudio(PyAudio needsportaudioon macOS:brew install portaudiobeforepip install).env.exampleโ the four env vars this script needs, with placeholders (copy to.env, which is gitignored).