A 100% private AI voice assistant that lives on your computer (works offline). Talk naturally as if Jarvis is a third person in the room β say its name anywhere in your sentence and get conversational, context-aware responses. It remembers everything, always knows the current location and time, can search the web, read your screen, control Chrome, track nutrition, and much more with support for unlimited MCPs and tools without context rot. Sensitive info is automatically redacted before anything is saved to disk.
π 100% local processing. No subscriptions. No data harvesting. Automatic redaction of sensitive info. Free offline dictation included.
π Your data stays yours - 100% local AI processing. No cloud, no subscriptions, no data harvesting. Automatic redaction of sensitive info. This is non-negotiable.
π£οΈ A third person in the room - Unlike voice assistants that only respond to rigid commands, Jarvis understands conversations. It maintains a short temporary rolling context of what's being discussed, so when you ask "Jarvis, what do you think?" it knows exactly what you're talking about. Have it chime into discussions with friends, help debug code while you talk through problems, or weigh in on decisions.
π§ Never forgets - Unlimited memory across conversations. Adapts tone naturally to the topic. Learns your preferences over time.
ποΈ Free dictation - Hold a hotkey, speak, release β your words appear in any app as text. Like WisprFlow, but free, offline, and private. No subscription, no cloud transcription.
π Extensible - MCP integration connects Jarvis to thousands of tools: smart home, GitHub, Slack, databases, and more. Smart tool selection means adding more tools won't slow things down.
π Transparent progress - We track what works (and what doesn't) with automated evals. See current accuracy β
π§ Known limitations: Jarvis is under active development. Primary development happens on macOS. Windows/Linux support may lag behind. We're building in the open, issues and contributions welcome!
- The desktop app is voice-only; typed chat runs from source in a terminal (see below, #35)
- No mobile apps (#17)
- "Stop" commands during speech sometimes get filtered as echo (#24)
- Dictation is not available on macOS 26+ (Tahoe) due to a pynput incompatibility (#172)
See it in action (example conversations)
Chiming into conversations (the magic moment):
π€ Alice: I wonder what the weather will be like tomorrow
π€ Bob: Yeah, we should check before planning the picnic
π€ Alice: Jarvis, what do you think?
π Heard: "What do you think Jarvis?"
π§ Intent (wake word): directed β "what do you think about the weather for the picnic"
β¨ Working on it: what do you think about the weather for the picnic
π§° Tool: getWeatherβ¦
π¬ Generating response...
π€ Jarvis
Tomorrow looks great for a picnic! Sunny with highs around 22Β°C...
Jarvis understood the entire conversation and gave a contextual answer β no need to repeat the question.
Browser automation via MCP:
π Heard: "Open YouTube Jarvis."
π§ Intent (wake word): directed β "open YouTube"
β¨ Working on it: open YouTube
π¬ Generating response...
π€ Jarvis
I have opened YouTube for you.
Health-aware advice:
π Heard: "Should I order pizza tonight considering my health goals Jarvis?"
π§ Intent (wake word): directed β "should I order pizza tonight considering my health goals"
β¨ Working on it: should I order pizza tonight considering my health goals
π§° Tool: fetchMealsβ¦
π¬ Generating response...
π€ Jarvis
Looking at your week β you mentioned wanting to lose 5kg by June...
Today you've had about 860 calories so far. Given your 1,800 calorie target,
you've got room for pizza! But maybe consider thin crust to save calories.
Personalised news search:
π Heard: "What are some news from today that might interest me Jarvis?"
π§ Intent (wake word): directed β "what are some news from today that might interest me"
β¨ Working on it: what are some news from today that might interest me
π§° Tool: searchMemoryβ¦
π§° Tool: webSearchβ¦
π¬ Generating response...
π€ Jarvis
Here's a quick snapshot of today's headlines...
Natural wake word placement (say "Jarvis" anywhere):
π Heard: "Give me a random topic to discuss Jarvis."
π§ Intent (wake word): directed β "give me a random topic to discuss"
β¨ Working on it: give me a random topic to discuss
π¬ Generating response...
π€ Jarvis
How about the Fermi Paradox? Given the vast number of stars...
Echo detection (Jarvis ignores its own speech):
π€ Jarvis
I have opened YouTube for you.
π Listening for follow-up (3s)...
π Heard: "I have opened YouTube for you."
π Heard (echo): "i have opened youtube for you."
π€ Returning to wake word mode
| Platform | Requirement |
|---|---|
| All | Ollama (default), or any OpenAI-compatible server you already run (LM Studio, Jan, llama.cpp, vLLM, oMLX, LocalAI, β¦) β see Configuration β LLM Provider |
Get the latest from GitHub Releases:
| Platform | Download | Run |
|---|---|---|
| Windows | Jarvis-Windows-x64.zip |
Extract β Run Jarvis.exe |
| macOS | Jarvis-macOS-arm64.zip |
Extract β Move to Applications β Right-click β Open |
| Linux | Jarvis-Linux-x64.tar.gz |
tar -xzf β Run ./Jarvis/Jarvis |
Jarvis starts listening automatically β just say "Jarvis" and talk!
- Conversational Awareness - Understands ongoing discussions. Ask "Jarvis, what do you think?" and it knows what you're talking about. Works naturally in multi-person conversations.
- Unlimited Memory - Never forgets. Searches across all your conversation history. Memory Viewer GUI included.
- Adaptive Tone - Automatically surgical for code, pragmatic for business, encouraging for wellbeing β no manual mode switching
- Smart Tool Selection - Embedding-based relevance filtering picks only the tools needed per query β add unlimited MCP tools without performance degradation
- Built-in Tools - Screenshot OCR, web search (DuckDuckGo β Brave β Wikipedia fallback chain with auto-fetch), weather, file access, nutrition tracking, location awareness, app launching ("play a Hindi song on YouTube", "open Chrome"), plus a tool-discovery escape hatch the agent uses to widen its own toolset mid-reply
- Knowledge Graph Memory - Self-organising memory that learns from conversations, auto-splits by topic, and surfaces relevant knowledge automatically
- Natural Voice - Say "Jarvis" anywhere in your sentence, interrupt with "stop", follow up without repeating the wake word
- Dictation Mode - Free, offline alternative to WisprFlow β hold a hotkey, speak, release to paste text into any app
- MCP Integration - Connect to thousands of external tools (Home Assistant, GitHub, Slack, etc.)
- Text Chat - Type instead of talk, from any terminal β including headless servers and containers with no microphone
| Hardware | VRAM | Model |
|---|---|---|
| Low-VRAM / CPU | 2GB+ | qwen3.5:0.8b |
| Most users | 8GB+ | gemma4:e2b (default) |
| Better quality | 16GB+ | gemma4:e4b |
| High-end | 24GB+ | gpt-oss:20b |
Note: VRAM requirements include the fast model (
gemma4:e2b) which is always loaded alongside the chat model for voice intent classification and other real-time work. The default chat model shares this, so no extra VRAM is needed.
The setup wizard will guide you through model selection and installation on first launch.
Most users won't need to change anything. Open βοΈ Settings from the tray menu to configure Jarvis through a graphical interface β no JSON editing required. Settings are saved to ~/.config/jarvis/config.json.
LLM Provider (Ollama or OpenAI-compatible)
By default Jarvis runs everything locally through Ollama: no API keys, nothing leaves your machine. If you already run an OpenAI-compatible server you can point Jarvis at it instead. Your data still only travels to the servers you control.
Pick the provider in the Setup Wizard's first step, or under βοΈ Settings β π LLM Provider. No JSON editing required. On the OpenAI-compatible page the wizard does the legwork for you: it auto-detects running local servers, offers a one-click preset for your app, and when you press Connect it loads the server's model list and checks the chosen model for chat, tool calling, and embeddings, so you know it works before you finish setup.
Tested local servers (all run on your own machine):
| App | Default base URL | Notes |
|---|---|---|
| LM Studio | http://localhost:1234/v1 |
Chat, tool calling, and embeddings. |
| Ollama (OpenAI API) | http://localhost:11434/v1 |
The native Ollama path is the default; the OpenAI shape works too. |
| Jan | http://localhost:1337/v1 |
Chat and tool calling. |
llama.cpp (llama-server) |
http://localhost:8080/v1 |
Tool calling depends on the model. |
| LocalAI | http://localhost:8080/v1 |
Feature support depends on the backend model. |
| vLLM | http://localhost:8000/v1 |
Tool calling depends on the model. |
| oMLX (Apple Silicon) | varies | No embeddings endpoint, so memory uses keyword search unless you route embeddings to Ollama (below). |
For reference, the underlying config keys are:
{
"llm_provider": "openai_compatible",
"llm_base_url": "http://localhost:1234/v1",
"llm_api_key": "",
"llm_chat_model": "your-served-model-name"
}llm_base_url: your server's OpenAI API base URL.llm_api_key: only if your server requires one; leave empty otherwise. On first run Jarvis moves it into your OS keychain and blanks it here β it is still in use, just no longer in plain text. Typing a new one intoconfig.jsonalways takes precedence.llm_chat_model: whatever model name your server exposes.fast_model(optional): the small, quick model used for real-time work (voice intent, tool routing, quick classifications). Leave empty for automatic:gemma4:e2bon Ollama, your chat model on an OpenAI-compatible server. Set it to pin a dedicated small model.
Embeddings (used for memory search) can run on a different backend. If your chat server has no embeddings endpoint, memory falls back to keyword search. To keep full semantic memory, route embeddings to Ollama (the wizard offers this automatically when it detects a server that cannot embed):
{
"embedding_provider": "ollama",
"embedding_model": "nomic-embed-text"
}Leave embedding_provider empty to use the same provider as chat. With no working embeddings, memory search degrades gracefully to keyword search.
Speech Recognition (Whisper)
- Multilingual (default, 99 languages):
"whisper_model": "medium" - English Only (slightly better English accuracy):
"whisper_model": "medium.en"
| Model | English | Multilingual | Download | VRAM | Speed |
|---|---|---|---|---|---|
| Tiny | tiny.en |
tiny |
~75 MB | ~1 GB | ~10x |
| Base | base.en |
base |
~140 MB | ~1 GB | ~7x |
| Small | small.en |
small |
~465 MB | ~2 GB | ~4x |
| Medium | medium.en |
medium |
~1.5 GB | ~5 GB | ~2x |
| Large V3 Turbo | - | large-v3-turbo |
~1.5 GB | ~6 GB | ~8x |
Speed is relative to the original large model. Source
If you have an NVIDIA GPU, Jarvis can use CUDA for much faster speech recognition. The Windows installer offers an optional CUDA download during setup. For development:
pip install nvidia-cublas-cu12 nvidia-cudnn-cu12CUDA is detected automatically β no configuration needed.
Whisper sometimes produces confident but false transcriptions during silence or background noise (e.g. news-show intros, music). Two thresholds filter these out before they reach the intent judge:
"whisper_min_confidence": 0.3β drops segments whoseavg_logprob-derived confidence falls below this value. Raise if you see low-confidence noise leaking through; lower if real speech is being dropped."whisper_no_speech_threshold": 0.5β drops any segment whoseno_speech_probis at or above this value, regardless ofavg_logprob. Catches the case where Whisper is confident about a hallucinated phrase but its own no-speech signal says the audio was silent. Applies to both the faster-whisper and MLX backends.
Both thresholds are exposed in the Settings window under Whisper.
Voice Interface (Advanced)
LLM Intent Judge - Jarvis uses a small LLM for intelligent voice intent classification (echo detection, query extraction, stop commands). On the default Ollama setup this is gemma4:e2b, installed automatically alongside your chosen chat model during setup. On an OpenAI-compatible provider the judge uses your served chat model instead, so there is nothing extra to install. The intent judge cannot be disabled but gracefully falls back to simpler text matching if the LLM server is unavailable.
Tool Router - When "tool_selection_strategy": "llm" (the default), Jarvis asks the fast model to pick which tools are relevant for each query, shrinking the tool catalogue the chat model sees. It's already warm and small enough not to stall the turn. Other strategies: "keyword" (fast, no LLM), "embedding" (nomic-embed-text), "all" (no filtering).
Task-list Planner - Before the agentic loop, Jarvis runs a short planning pass that decomposes multi-step queries into an ordered list of sub-tasks. For small models (gemma4:e2b class), each planned step is directly resolved to a concrete tool call without relying on the chat model to re-plan turn-by-turn. This significantly improves multi-step reliability. Config options:
{
"planner_enabled": true, // set to false to disable the planner entirely
"planner_timeout_sec": 6.0 // per-call timeout for plan and step-resolver LLM calls
}Small-Model Digest Passes (Advanced)
Small chat models (~2B, e.g. gemma4:e2b) degrade sharply as their prompt grows. Jarvis runs two cheap distil passes to keep the prompt tight:
- Memory digest β boils diary + graph recall into a short relevance-filtered note before injecting it as background context.
- Tool-result digest β boils a raw tool payload (especially webSearch UNTRUSTED WEB EXTRACT blocks) into a short attributed fact note before it reaches the main reply model.
Both digest passes auto-enable for small models (β€7B) and stay off for large models. For small models, tool-result digest also prevents large fetch_web_page payloads from blowing the context window. Override in ~/.config/jarvis/config.json:
{
"memory_digest_enabled": null, // null = auto-on for SMALL, false to force off, true to force on
"tool_result_digest_enabled": null, // null = auto-on for SMALL, false to force off, true to force on
"llm_digest_timeout_sec": 8.0 // tight ceiling shared by both passes
}Field logs show π§© Memory digest: β¦ and π§© Tool digest: β¦ lines when a pass ran, so you can see when the substrate was replaced.
Hold a hotkey to record speech, release to paste the transcription into any app. Works everywhere β your editor, browser, chat, terminal. Completely local, completely free.
| Platform | Default hotkey |
|---|---|
| Windows | Ctrl + Win |
| macOS | Ctrl + Option |
| Linux | Ctrl + Alt |
- π 100% offline β your speech never leaves your machine (unlike cloud dictation services)
- π§ Shared Whisper model β uses the same speech recognition as voice input, no extra memory
- β‘ Zero latency startup β no server round-trip, transcription starts the moment you release
- π Universal paste β works in any app that accepts
Ctrl+V/Cmd+V - π Non-intrusive β main voice listener pauses automatically during dictation
- β Hands-free mode β double-tap the hotkey to keep recording without holding; press again or hit Escape to stop
- π§Ή Filler word removal β optional LLM-powered cleanup removes "um", "uh", "like", "you know" while preserving meaning
- π Custom dictionary β define
"wrong -> right"replacements for jargon, names, and technical terms - π History window β browse, copy, or delete past dictations from the system tray
- ποΈ Easy setup β configure dictation during the setup wizard or anytime in Settings (hotkey dropdown, filler removal toggle, custom dictionary editor)
Customise the hotkey in Settings or config.json:
{
"dictation_hotkey": "ctrl+alt",
"dictation_filler_removal": true,
"dictation_custom_dictionary": [
"jarvis -> Jarvis",
"pytorch -> PyTorch"
]
}Note: macOS requires Accessibility permissions for the global hotkey. Linux requires X11 (limited Wayland support).
Type at Jarvis instead of speaking to it. Same assistant: same memory, same tools, same diary β it just reads lines instead of listening. Useful on a headless server, in a container, over SSH, or when you simply don't want to talk out loud.
git clone https://github.com/isair/jarvis.git
cd jarvis
pip install -r requirements-chat.txt
PYTHONPATH=src python -m jarvis.chat㪠Jarvis text chat
π Provider: ollama (http://localhost:11434)
π§ Chat model: gemma4:e2b
πΎ Memory: ~/.local/share/jarvis/jarvis.db
βΉοΈ Type /help for commands, /exit to leave.
π§ You βΊ what did I say about the picnic yesterday?
Ask a single question and exit (handy for scripts):
PYTHONPATH=src python -m jarvis.chat "what's the weather like?"| Command | What it does |
|---|---|
/help |
List the commands |
/reset |
Save the conversation and start a fresh one |
/exit |
Save the conversation and quit (also /quit, or Ctrl+D) |
requirements-chat.txt is the audio-free subset of requirements.txt β no
Whisper, no PortAudio, no Qt β so it installs on a machine with no sound card
and no desktop. Install the full requirements.txt instead if you want voice
and text from the same checkout.
Note: the screenshot tool needs a display, so it won't work over a plain SSH session. Everything else β memory, web search, weather, nutrition, MCP servers β works the same as it does by voice.
Text-to-Speech
Piper TTS (default) - Neural TTS that auto-downloads on first use (~60MB):
- Works out of the box - no setup required
- High-quality British English male voice (en_GB-alan-medium)
- Fast local synthesis with exact duration tracking
To use different Piper voices, download from HuggingFace and set:
{
"tts_piper_model_path": "~/.local/share/jarvis/models/piper/en_GB-alan-medium.onnx"
}Chatterbox - AI voice with emotion control (requires running from source):
{ "tts_engine": "chatterbox" }Voice cloning with Chatterbox - add a 3-10 second .wav sample:
{
"tts_engine": "chatterbox",
"tts_chatterbox_audio_prompt": "/path/to/voice.wav"
}Location Detection
Jarvis can provide location-aware responses (weather, local time, etc.) using a local GeoLite2 database β no cloud geolocation services are used.
IP detection chain (in order of preference):
- Manual IP β configure
location_ip_addressin settings - UPnP β queries your local router (no traffic leaves LAN)
- Socket heuristic β determines which interface routes externally (no data sent)
- OpenDNS DNS query β single
myip.opendns.comlookup to208.67.222.222(only external query)
If your ISP uses carrier-grade NAT (CGNAT), Jarvis automatically resolves your true public IP via the same OpenDNS DNS query. This can be disabled:
{
"location_cgnat_resolve_public_ip": false
}Setup: Register for a free MaxMind GeoLite2 account, download the City database (MMDB format), and save it to ~/.local/share/jarvis/geoip/GeoLite2-City.mmdb. The setup wizard will guide you through this.
MCP Tool Integration
Connect Jarvis to external tools via MCP servers:
{
"mcps": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/[email protected]"],
"env": { "GITHUB_TOKEN": "your-token" }
}
}
}Popular integrations:
- Home Assistant - Voice control for smart home
- Google Workspace - Gmail, Calendar, Drive, Docs
- GitHub - Issues, PRs, workflows
- Notion - Knowledge management
- Slack/Discord - Team communication
- Databases - MySQL, PostgreSQL, MongoDB
- Composio - 500+ apps in one integration
See full MCP setup guide below.
Adding servers: the dashboard's Connections tab lists curated servers you can add in one click, with the exact version already pinned. Under it, Browse the public registry searches the official MCP registry (thousands of servers) once you press Refresh. The registry is cached on your machine, so browsing it works offline and pressing Refresh is the only time Jarvis contacts it. Nothing about you is sent either way.
The registry proves the publisher owns the namespace: a GitHub account for
io.github.*, a domain for the rest. That tells you who published a server, not that it is safe β nobody reviews the code, and being listed is not an endorsement. Servers without a pinned package version cannot be added, because Jarvis refuses to launch unpinned code. There is also an Add a server manually section for anything else.
Remote servers: as well as local servers Jarvis launches for you, it can connect to hosted ones. Point it at a URL instead of a command:
{ "mcps": { "acme-crm": { "transport": "http", "url": "https://mcp.acme.com/mcp", "auth": "oauth" } } }With
"auth": "oauth"your browser opens at the provider, you approve, and the token is stored in your OS keychain. You never see it and it never touchesconfig.json. Without it, Jarvis sends a bearer token from the keychain instead. Plainhttp://is only accepted forlocalhost, since a token would otherwise cross the network in clear text.
Session persistence: each MCP server is launched once and its stdio session is kept open across tool calls. Stateful servers (e.g. browser automation, where the server owns a long-running Chrome process) work correctly. If you have a server you'd rather not keep resident, set
"idle_timeout_sec": 300on its config entry and Jarvis will free it after that long without activity. If a server's tools legitimately run long (e.g. delegating a task to an external CLI agent), set"timeout_sec": 600to raise its 120-second default call timeout.
π How Jarvis protects you from a bad MCP server
An MCP server is code you installed, and its tool descriptions are read by the model as instructions. Jarvis drives a real mouse and keyboard, so four things sit in the way.
1. Versions must be pinned. npx -y some-server@latest re-downloads whatever is published at that moment, every time Jarvis starts. Jarvis refuses those and asks for an exact version:
"args": ["-y", "[email protected]"] // npx
"args": ["some-server==1.4.2"] // uvxLocal paths, node, python and docker commands are not affected. If you really want a floating version, add "allow_unpinned": true to that server's entry. Servers you installed through the setup wizard are re-pinned automatically on upgrade, so they keep working.
2. Tools that change get withheld. Jarvis remembers what each tool looked like when you added it. If a description later changes, that tool is withheld rather than quietly handed to the model with new instructions. Review and restore it with:
python -m jarvis.mcp_trust_cli list # what changed
python -m jarvis.mcp_trust_cli accept <server> <tool> # allow it again3. Risky actions need YOLO mode. Anything consequential (a destructive MCP tool, controlling your screen) only runs while YOLO is on. Turn it on from the bar at the top of the dashboard β drag the slider to anything from 5 minutes to 8 hours β or pick a preset from the tray menu and Jarvis just gets on with things; when it lapses, it starts asking again. If you ask for something while it is off, Jarvis tells you what it was about to do and asks you to switch it on. It cannot switch it on itself β that is the point, since it reads web pages and tool descriptions that other people wrote. Set mcp_confirm in config.json to choose what counts as consequential:
| Value | Needs YOLO |
|---|---|
off |
nothing |
destructive (default) |
tools the server marks destructive or open-world |
unannotated |
the above, plus any tool that declares nothing |
all |
every MCP tool call |
4. Servers don't get your shell secrets. An MCP server is third-party code, so variables whose names say they hold a credential (*_TOKEN, *_API_KEY, *_SECRET, *_PASSWORD, β¦) are withheld from it. Proxy settings, custom CA paths and the rest still pass through. A server that genuinely needs a token gets it from its own env block in config.json, which always wins.
5. You can audit definitions. Checks every configured server for text hidden in invisible characters, descriptions imitating system prompts, references to credential files, and one server steering calls to another's tools. Runs entirely on your machine:
python -m jarvis.mcp_trust_cli auditHome Assistant - Smart home voice control
- Add MCP Server integration in Home Assistant (Settings β Devices & services)
- Expose entities you want to control (Settings β Voice assistants β Exposed entities)
- Create Long-lived Access Token (Profile β Security β Create token)
- Install proxy:
uv tool install git+https://github.com/sparfenyuk/mcp-proxy - Add to config:
{
"mcps": {
"home_assistant": {
"command": "mcp-proxy",
"args": ["http://localhost:8123/mcp_server/sse"],
"env": { "API_ACCESS_TOKEN": "YOUR_TOKEN" }
}
}
}"Jarvis, turn on the living room lights" / "set bedroom to 72Β°" / "run good night scene"
Google Workspace - Gmail, Calendar, Drive, Docs, Sheets
{
"mcps": {
"google_workspace": {
"command": "npx",
"args": ["-y", "[email protected]"],
"env": {
"GOOGLE_CLIENT_ID": "your-client-id",
"GOOGLE_CLIENT_SECRET": "your-client-secret"
}
}
}
}GitHub - Repos, issues, PRs, workflows
{
"mcps": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/[email protected]"],
"env": { "GITHUB_TOKEN": "your-token" }
}
}
}Notion, Slack, Discord, Databases
Notion:
{ "mcps": { "notion": { "command": "npx", "args": ["-y", "@notionhq/[email protected]"], "env": { "NOTION_API_KEY": "your-token" } } } }Slack:
{ "mcps": { "slack": { "command": "npx", "args": ["-y", "[email protected]"], "env": { "SLACK_BOT_TOKEN": "xoxb-...", "SLACK_USER_TOKEN": "xoxp-..." } } } }Discord:
{ "mcps": { "discord": { "command": "npx", "args": ["-y", "[email protected]"], "env": { "DISCORD_BOT_TOKEN": "your-token" } } } }Databases: bytebase/dbhub (SQL), mongodb-mcp-server (MongoDB)
Common issues
First startup takes a bit - Jarvis pre-warms the Whisper, chat, and intent-judge models before announcing "Listening!" so the first engagement feels instant. This adds a few seconds on cold start and is bounded at 60 s β if Ollama is slow, Jarvis will start listening anyway and load the models on demand.
Jarvis doesn't hear me - Check microphone permissions, speak clearly after "Jarvis"
Responses are slow - Ensure you have enough VRAM (8GB+ for default model; see System Requirements for other models)
Windows: App won't start - Extract full zip first, check Windows Defender
macOS: "App can't be opened" - Right-click β Open, or System Settings β Privacy & Security β Allow
Linux: No tray icon - sudo apt install libayatana-appindicator3-1
Jarvis keeps deflecting on questions it answered before - small models can record their own past failures into the diary, which then primes future sessions to repeat them. New writes are scrubbed automatically; to clean historical entries, open the Memory Viewer, switch to the Diary tab, and click Clean up deflection narration in the sidebar Maintenance section. Only sentences that narrate the assistant's failures are removed; the rest of each entry stays.
Running from source
git clone https://github.com/isair/jarvis.git
cd jarvis
# macOS
bash scripts/run_macos.sh
# Windows (with Micromamba)
pwsh -ExecutionPolicy Bypass -File scripts\run_windows.ps1
# Linux
bash scripts/run_linux.shRunning from source enables Chatterbox TTS (AI voice with emotion/cloning). Piper TTS works in both bundled and source modes.
Privacy hardening (stay 100% offline)
{
"web_search_enabled": false,
"wikipedia_fallback_enabled": false,
"brave_search_api_key": "",
"mcps": {},
"location_auto_detect": false,
"location_cgnat_resolve_public_ip": false,
"location_enabled": false
}Verify: sudo lsof -i -n -P | grep jarvis (should only show 127.0.0.1 to Ollama)
The Memory Viewer is served from 127.0.0.1 and loads no webfonts, scripts or
styles from any CDN, so opening your diary and knowledge graph makes no outbound
request at all. It renders identically with the machine offline.
Web search fallback chain
When DuckDuckGo is rate-limited or returns nothing fetchable, Jarvis walks a small fallback chain before giving up rather than confabulating:
- Brave Search β opt-in, requires
brave_search_api_key. Free tier: 2,000 queries/month. Get a key at api.search.brave.com. - Wikipedia β zero-config, on by default, uses the Wikipedia host
matching the language Whisper auto-detected on the utterance (so a
Turkish question gets a Turkish answer). Disable with
wikipedia_fallback_enabled: false. - Honest failure β if every provider fails, the reply tells you the search was blocked rather than making something up.
The whole chain is bounded by a ~20s wall-clock deadline so a stalled provider can't run out the voice-assistant latency budget.
- 100% offline - No cloud services required
- Auto-redaction - Emails, tokens, passwords automatically removed
- Local storage - Everything in
~/.local/share/jarvis - Keys in your OS keychain - API keys move out of
config.jsoninto Keychain, Credential Manager or Secret Service on first run, so the MCP server subprocesses Jarvis launches cannot read them. On a machine with no keychain the key stays inconfig.jsonrather than being lost.
- Personal use: Free forever
- Commercial use: Contact us
Report issues Β· Discussions Β· Sponsor













