A Windows-native, voice-first personal assistant.
- Starts on Windows login, runs silently in the background (no window).
- Waits for the wake word "Jarvis", then listens, thinks, speaks.
- No browser, no console window, no visible UI in production.
JARVIS.exe (Windows GUI subsystem, no console)
└─ AssistantEngine (single thread + wake-word background thread)
├─ Wake Word (openWakeWord local, with energy-gate fallback)
├─ STT (faster-whisper, local)
├─ AI (provider abstraction: openai | gemini | mock)
└─ TTS (edge-tts, Microsoft cloud, plays locally)
Wake-word, microphone capture, and STT are local. AI and TTS may call cloud endpoints depending on configuration.
- Windows 10 / 11
- A working microphone and speakers (the system default input/output devices are used automatically)
- Python 3.11+ (only required for development or building the EXE)
- Copy
dist\JARVIS\to a stable location, e.g.C:\Apps\JARVIS\. - Double-click
JARVIS.exe. The greeting plays through your speakers and JARVIS waits for "Jarvis". No window appears. - Press Ctrl + Shift + J at any time for an emergency shutdown.
JARVIS stores its logs and TTS cache in
%APPDATA%\JARVIS\ when running as a packaged EXE, and in ./logs/
and ./tts_cache/ when running from source.
python -m app.system.startup --installThis places a shortcut in the user's Startup folder
(shell:startup) pointing at the packaged JARVIS.exe. To remove:
python -m app.system.startup --uninstallCopy .env.example to .env and edit:
copy .env.example .envThe packaged EXE looks for .env in its working directory (the folder
that holds JARVIS.exe), or you can point it elsewhere via
JARVIS_ENV_FILE.
Key values:
| Variable | Default | Purpose |
|---|---|---|
AI_PROVIDER |
mock |
openai, gemini, or mock |
AI_MODEL |
(provider default) | e.g. gpt-4o-mini, gemini-1.5-flash |
OPENAI_API_KEY |
empty | Required when AI_PROVIDER=openai |
GEMINI_API_KEY |
empty | Required when AI_PROVIDER=gemini |
TTS_PROVIDER |
edge |
edge or mock |
TTS_VOICE |
en-US-GuyNeural |
Any edge-tts voice id |
WAKE_WORD_ENABLED |
true |
Disable to skip wake-word detection |
WAKE_WORD |
jarvis |
Keyword name (informational) |
WAKEWORD_BACKEND |
openwakeword |
openwakeword (default), energy, or porcupine |
OPENWAKEWORD_MODEL |
hey_jarvis |
Pretrained model name or path to a custom .tflite/.onnx |
OPENWAKEWORD_THRESHOLD |
0.5 |
Detection threshold (0.0 – 1.0) |
PORCUPINE_ACCESS_KEY |
empty | Optional, only used if WAKEWORD_BACKEND=porcupine |
PORCUPINE_KEYWORD_PATH |
empty | Optional .ppn file path |
STARTUP_GREETING_ENABLED |
true |
Set false for silent boot |
STARTUP_GREETING |
Good morning, Sir. |
Spoken after the startup delay |
STARTUP_GREETING_DELAY |
5 |
Seconds to wait before greeting |
HOTKEY_EXIT |
Ctrl+Shift+J |
Emergency-stop hotkey |
LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING, ERROR |
JARVIS supports three providers:
mock— offline canned answers, useful for testing the pipeline without an API key.openai— requiresOPENAI_API_KEY. Uses the OpenAI Chat Completions API.gemini— requiresGEMINI_API_KEY. Uses the Google Generative AI SDK.
Set AI_PROVIDER to the one you want. JARVIS does not silently
fall back if a key is missing — the failure surfaces so the user can
fix configuration.
The default backend is openWakeWord — fully local, no API key,
no signup. JARVIS listens for "hey jarvis" by default using a
pretrained model that ships with the openwakeword package.
Two backends are available; pick one via WAKEWORD_BACKEND:
openwakeword(default) — fully local. Usesopenwakewordwithonnxruntimeas the inference backend. The package ships several pretrained models —hey_jarvis,alexa,hey_mycroft,hey_rhasspy,timer,weather— setOPENWAKEWORD_MODELto any of them, or to a path to a custom.tflite/.onnxmodel. No internet, no API key, no account required.energy— simple energy-gate fallback. Detects a short burst of loud audio as a proxy for the wake word. Fully local, no dependencies beyond NumPy and sounddevice. Used automatically if the openWakeWord model fails to load.porcupine(legacy) — the previous default. Requirespvporcupineand a Picovoice access key from https://console.picovoice.ai/. SetPORCUPINE_ACCESS_KEYin.env. New users should not need this — openWakeWord covers the same use case without signup.
OPENWAKEWORD_THRESHOLD(default0.5) controls the model's decision threshold. Higher = fewer false positives, lower = more sensitive. If JARVIS keeps firing on background noise, raise it to0.6–0.7. If it never fires when you say "hey jarvis", lower it to0.3–0.4.- Microphone frames are processed locally for wake-word detection — no audio is uploaded for this step.
openWakeWord already ships a pretrained hey_jarvis model, so
no training is required out of the box. If you find its accuracy
unsatisfactory on your voice/mic, you can train a custom model by
following the openWakeWord training notebook,
export the resulting .tflite (or .onnx), and set
OPENWAKEWORD_MODEL=C:\path\to\your_model.tflite.
Uses faster-whisper locally.
- Model:
base(int8, CPU). Loaded once on first use and held in memory; not reloaded per command. - Audio format: 16 kHz, mono, int16.
- No raw microphone recordings are stored on disk.
To change the model size, edit _build_stt in app/main.py.
Uses edge-tts (Microsoft cloud) and plays through the local sounddevice player.
- This is a network service, not offline. First-use synthesis needs internet.
- Synthesised MP3 files are deleted immediately after playback so the TTS cache does not grow.
- JARVIS disables wake-word detection while it is speaking, so its own voice cannot trigger a new wake event (self-trigger guard).
To switch voice, set TTS_VOICE in .env (e.g.
en-US-JennyNeural, en-GB-RyanNeural).
JARVIS can start automatically on Windows login via a shortcut in the Startup folder.
python -m app.system.startup --install :: install
python -m app.system.startup --status :: check
python -m app.system.startup --uninstall :: removeThe shortcut points at the packaged JARVIS.exe, not at Python
or run_dev.bat. The shortcut is created with WindowStyle = 7
(hidden) so JARVIS launches with no visible UI.
Ctrl + Shift + J — releases the microphone, stops TTS playback, unregisters the global hotkey, and exits the process cleanly. This hotkey is essential because the production EXE has no visible window.
Run from source:
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
:: edit .env
python -m app.main :: dev mode, console visible
python -m app.main --check :: initialise everything then exit
python -m app.main --dev :: explicit dev modeRun a quick end-to-end test against real audio:
python smoke_live.pyRun the automated test suite:
pytest -qbuild.batProduces dist\JARVIS\JARVIS.exe (PyInstaller, --noconsole,
one-folder). The folder is self-contained — end users do not need
Python installed.
After building, you can install the auto-start shortcut:
python -m app.system.startup --install- Microphone unavailable — Windows may have denied mic access to
Python / the EXE. Check
Settings → Privacy → Microphoneand ensure desktop apps have permission. Also confirm your mic is the system default input. - Speaker unavailable — confirm the system default output device is connected and not muted. JARVIS uses the system default.
- Wake word unavailable — confirm
WAKE_WORD_ENABLED=truein.env. The default backend isopenwakeword(no API key needed) using thehey_jarvispretrained model. If the model fails to load, the energy-gate fallback is used automatically — speak the wake word louder and closer to the mic. Tune sensitivity withOPENWAKEWORD_THRESHOLD. For the legacy Porcupine backend, setWAKEWORD_BACKEND=porcupine,pip install pvporcupine, and setPORCUPINE_ACCESS_KEY. - API key missing / invalid — startup will surface the
configuration error in
logs/jarvis.log. Set the correct key in.envfor the provider you chose inAI_PROVIDER. - Network unavailable — TTS (edge-tts) requires internet. Commands still work locally for STT and wake-word, but spoken replies will fail.
- TTS failure — check
logs/jarvis.logfor the underlying exception. JARVIS logs the error and continues; no spoken reply is delivered for that command. - Startup shortcut issue — re-run
python -m app.system.startup --install. Inspect the shortcut properties to confirmTargetis the packagedJARVIS.exe, notpython.exeorrun_dev.bat.
.envis git-ignored. API keys are not committed.- A secret-scrubbing log filter redacts obvious
key=valuepairs in log output, so API keys are not leaked via logs. - Wake-word detection is local. STT runs locally (faster-whisper).
- AI and TTS calls may use cloud services depending on configuration.
- No raw microphone recordings are stored permanently.
Personal project. Use at your own risk.