Metadata-Version: 2.4
Name: mastermode
Version: 0.3.3
Summary: MasterMode — your personal AI advisor with semantic memory, web search, and graph-based life model.
Author: Shivam Kumar
License: MIT
Project-URL: Homepage, https://github.com/shivampkumar/mastermode
Project-URL: Repository, https://github.com/shivampkumar/mastermode
Project-URL: Issues, https://github.com/shivampkumar/mastermode/issues
Keywords: ai,assistant,personal-knowledge-graph,memory,local-first,mcp,rag,life-os
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Utilities
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.9.0
Requires-Dist: rich>=13.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: jinja2>=3.1
Requires-Dist: pyvis>=0.3.2
Requires-Dist: python-dateutil>=2.9
Requires-Dist: pydantic>=2.0
Requires-Dist: pymupdf>=1.24.0
Requires-Dist: python-docx>=1.1.0
Requires-Dist: Pillow>=10.0
Requires-Dist: python-telegram-bot>=21.0
Requires-Dist: apscheduler>=3.10
Requires-Dist: anthropic>=0.39.0
Requires-Dist: google-genai>=1.0.0
Requires-Dist: google-api-python-client>=2.0.0
Requires-Dist: google-auth-oauthlib>=1.0.0
Requires-Dist: google-auth-httplib2>=0.2.0
Requires-Dist: requests>=2.31.0
Requires-Dist: sqlite-vec>=0.1.6
Requires-Dist: numpy>=1.26
Requires-Dist: httpx>=0.27
Requires-Dist: ddgs>=9.0
Requires-Dist: readability-lxml>=0.8.1
Requires-Dist: html2text>=2024.2.0
Requires-Dist: beautifulsoup4>=4.12
Requires-Dist: defusedxml>=0.7
Requires-Dist: litellm>=1.50
Requires-Dist: rank-bm25>=0.2.2
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.27
Requires-Dist: mcp>=1.2
Provides-Extra: pdf
Requires-Dist: weasyprint>=62.0; extra == "pdf"
Provides-Extra: local
Requires-Dist: sentence-transformers>=2.7; extra == "local"
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: eval
Requires-Dist: datasets>=2.0; extra == "eval"
Requires-Dist: huggingface_hub>=0.20; extra == "eval"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Dynamic: license-file

# MasterMode

![MasterMode demo: capture → recall → dedup → Saturday review](demo/mastermode.gif)

**A personal AI advisor that doesn't rot over time.**

Most personal-AI tools fail the same way: graph corruption. After three weeks
your "Palo" entity, your "Palo.ai" entity, and your "[merged] Palo" tombstone
are three different things. Your assistant cheerfully tells you about all of
them. mem0 doesn't fix this. Zep doesn't fix this. Obsidian leaves it to you.

MasterMode treats graph hygiene as a first-class problem.

```
$ mastermode dedup scan
[0.911][ASK] Organization: 'Palo'    vs  Organization: 'Palo ai'  → SAME (Shivam founded both)
[0.911][ASK] Skill:        'Java'    vs  Skill:        'JavaScript' → DISTINCT (different languages)
[0.914][ASK] Skill:        'SQL'     vs  Skill:        'PostgreSQL' → DISTINCT (lang vs RDBMS)
```

Naive cosine would have wrongly merged Java and JavaScript. The LLM gate
caught it. That's the kind of small thing that compounds.

## Why this is not yet-another-personal-chatbot

Every personal-AI you've tried has *some* of these. None has all six:

| | mem0 | Zep | OpenClaw | Letta | Obsidian | **MasterMode** |
|---|:-:|:-:|:-:|:-:|:-:|:-:|
| LLM-gated dedup with adjudicator | ❌ | ❌ | ❌ | ❌ | ❌ | **✅** |
| Provenance + audit-logged reversible merges | ❌ | partial | ❌ | ❌ | manual | **✅** |
| Multi-agent reasoning with citations | ❌ | ❌ | partial | ❌ | ❌ | **✅** |
| Local-first embeddings (no key needed) | partial | ❌ | partial | ❌ | with plugin | **✅** |
| 100+ LLM providers via one env var | partial | ❌ | partial | partial | with plugin | **✅** (LiteLLM) |
| Drop-anywhere capture (CLI, HTTP, voice memo, Shortcuts) | ❌ | ❌ | partial | ❌ | manual | **✅** |

We're [explicitly different](SECURITY.md) from OpenClaw on the dimensions that
caused [its 2026 security crisis](https://www.bloomberg.com/news/articles/2026-02-04/openclaw-s-an-ai-sensation-but-its-security-a-work-in-progress):
no skills marketplace, no plugin loading, no public-internet default, audit
log on every merge, provenance on every fact.

## What it does

- **Builds a structured graph** of your life — people, projects, goals,
  mood, events, journal — from conversation, voice memos, websites, .txt
  drops, anything.
- **Recalls semantically** via local embeddings (`bge-small-en-v1.5`).
  No API key needed for retrieval.
- **De-duplicates over time** via a two-pass scan (embedding cosine + name
  similarity) gated by an LLM adjudicator. Reversible. Audit-logged.
- **Reasons cross-domain** via a planner → researcher → reasoner → critic
  loop (`mastermode ask`). Cites every claim back to its source.
- **Captures from anywhere**: `mastermode capture "..."`, voice-memo dropbox
  watcher, iOS/macOS Shortcut blueprints, HTTP `POST /api/capture`.
- **Browses the web**: built-in `web_search` + `web_fetch` tools using
  DuckDuckGo by default; Tavily/Brave optional; Obscura headless browser
  for JS-heavy pages.
- **Saturday weekly review** ritual: cold relationships, goal velocity,
  mood trend, top-3 grounded actions.

## Honest benchmarks

`mastermode bench longmem` hits LongMemEval-S (ICLR 2025). Published
numbers, not claims. Run yourself:

```bash
mastermode bench longmem --split longmemeval_s_cleaned --limit 60 --stratified --out report.json
```

### Current results (450 stratified questions, Gemini 2.5 Flash chat)

Same chat agent run through two judges:

| Category | n | Gemini Flash judge | **GPT-4o judge** |
|---|---|---|---|
| single-session-user | 70 | 80% | **84%** |
| single-session-preference | 30 | 60% | **70%** |
| knowledge-update | 78 | 63% | 63% |
| multi-session | 133 | 45% | 41% |
| single-session-assistant | 56 | 36% | 41% |
| temporal-reasoning | 83 | 39% | 29% |
| **OVERALL** | **450** | **52%** | **51%** |

GPT-4o judge is the apples-to-apples comparison vs published leaderboards.
Net Δ -1pp — judges disagree on individual phrasings but converge on the
overall picture. Our published number is **51% (GPT-4o judge)** for
direct leaderboard comparison.

Reproducible — `mastermode bench longmem --split longmemeval_s_cleaned --limit 500 --stratified`.
~67 min wall clock on a Mac mini, Gemini Flash chat + judge.

### Quick read vs full sweep

```bash
# Quick read (~7 min, ±3-5% noise): same stratification, smaller sample.
mastermode bench longmem --split longmemeval_s_cleaned --limit 60 --stratified

# Full sweep (~70 min): the headline number above.
mastermode bench longmem --split longmemeval_s_cleaned --limit 500 --stratified
```

### Judge choice

By default chat and judge are the same LLM (cheap default = Gemini Flash).
For apples-to-apples with published leaderboards that use GPT-4o:

```bash
export LIFEOS_JUDGE_PROVIDER=litellm
export LIFEOS_JUDGE_MODEL=openai/gpt-4o
# (chat still uses whatever LIFEOS_LLM_PROVIDER you have)
mastermode bench longmem --limit 60 --stratified
```

Chat provider/model and judge provider/model are printed at start of
every run so you can verify.

### What changed during testing

| Change | Why | Δ on 60q |
|---|---|---|
| Embed assistant turns, not just user | Failed every "what did you tell me about X" question | +20pp on single-session-assistant, +40pp on multi-session |
| Render session window around top hits | Counting tasks failed because each turn lost session scope | (combined with above) |
| Robust judge JSON parser | Judge was rejecting correct answers when its own JSON was malformed | Caught 2 false-negatives on n=60 |
| Tightened chat prompt: don't ask clarifying questions when prefs known | Bot was punting "suggest a hotel" to "what's your budget" | +10pp on temporal-reasoning, mixed on multi-session |

These were real product improvements found by running the bench, not
benchmark-overfitting. Embedding assistant turns directly fixes user
questions like "what did you suggest about my visa last week".

### For comparison

Other open-source systems' published numbers on the same benchmark
(all use GPT-4o judge):

| System | LongMemEval-S | Notes |
|---|---|---|
| OMEGA | 95.4% | open-source |
| EverMind | 83.0% | hosted |
| SuperLocalMemory Mode A | 74.8% | fully local |
| Zep | 63.8% | hosted |
| **MasterMode** | **51.3%** | **Gemini Flash chat, free tier** ← us |
| mem0 | 49.0% | open-source, 47K stars |

We edge out [mem0's published 49%](https://vectorize.io/articles/best-ai-agent-memory-systems)
using **Gemini Flash chat with the same GPT-4o judge**. We're not in the
top tier — that's reserved for systems running heavier chat agents
(usually GPT-4o for chat itself, which is ~30× our cost per turn).

The headline numbers come from `bench_results_500_gpt4o.json` in this
repo. Reproducible:

```bash
export OPENAI_API_KEY=sk-...
LIFEOS_JUDGE_PROVIDER=litellm LIFEOS_JUDGE_MODEL=openai/gpt-4o \
  mastermode bench longmem --limit 500 --stratified --out my_run.json
```

We also have features they don't (LLM-gated dedup, audit-logged merges,
multi-agent reasoning, capture-anywhere, web tools). Memory benchmark
score is one axis; product trust is another.

---

## Try it without installing

A hosted demo is loaded with a synthetic graph for "Alex Rivera" —
a climber with a sister's wedding coming up, a dad who hasn't been
called in six weeks, a U-Haul loop, and the rest. Click in, chat,
watch the dedup adjudicator merge Mom/Mother while rejecting
Java/JavaScript, run the Saturday review.

> **[▶ Open the demo](https://mastermode.vibeops.tech)**

Or run it locally — it's faster and the graph is yours:

```bash
git clone https://github.com/shivampkumar/mastermode.git
cd mastermode
pip install -e ".[local]"
export GOOGLE_API_KEY=...   # free key from https://aistudio.google.com/apikey
make demo-serve              # seeds Alex's graph + serves on :8100
# open http://127.0.0.1:8100
```

Demo mode (`MASTERMODE_DEMO_MODE=true`) blocks destructive endpoints
(DELETE / PUT / PATCH except an allowlist of `/api/chat`,
`/api/capture`, and `/api/demo/reset`). Public deploys stay browseable
but unbreakable.

### Self-deploy

The repo ships a `Dockerfile` and `render.yaml` blueprint. Most
one-click-deploy platforms auto-detect one of them.

**Docker (anywhere):**

```bash
docker build -t mastermode-demo .
docker run -d -p 8000:8000 -e GOOGLE_API_KEY=sk-... mastermode-demo
```

**Render** (`render.yaml` blueprint, free tier):

1. Fork this repo.
2. Sign in at [render.com](https://render.com), connect GitHub.
3. Dashboard → **New +** → **Blueprint** → pick your fork.
4. Set `GOOGLE_API_KEY` as a secret. Click **Apply**.
5. ~5 min build, live at `https://<your-name>.onrender.com`.

Free tier uses Gemini for both chat and embeddings (no torch, no
sentence-transformers). The cross-encoder reranker auto-disables —
falls back to BM25+semantic RRF fusion.

## 60-Second Setup

### Prerequisites
- Python 3.11+
- One of: Google AI API key (free), Anthropic API key, or Ollama installed locally
- (Optional) A Telegram account if you want the bot

### Install + interactive wizard

```bash
# One line — no clone, no venv to manage:
pip install mastermode          # or: uv tool install mastermode
#   add the local-embeddings extra for the offline default:
pip install "mastermode[local]"

mastermode setup        # interactive: picks LLM, embedding provider, optional Telegram
source ~/.lifeos/mastermode.env
mastermode capture "Started learning Rust today, working through the book."
```

Prefer to hack on it? Clone and install editable:

```bash
git clone https://github.com/shivampkumar/mastermode.git
cd mastermode
python -m venv .venv && source .venv/bin/activate
pip install -e .
```

That's it. Capture works. The graph is being built.

> The legacy `lifeos` CLI still exists as an alias — both `mastermode` and
> `lifeos` invoke the same entrypoint.

### Choose your LLM (manual alternative to the wizard)

**Option A: Gemini (free, recommended)**
```bash
# Get a free API key from https://aistudio.google.com/apikey
export GOOGLE_API_KEY=your-key
export LIFEOS_LLM_PROVIDER=gemini
```

**Option B: Claude**
```bash
export ANTHROPIC_API_KEY=your-key
export LIFEOS_LLM_PROVIDER=claude
```

**Option C: Local with Ollama (zero cost, fully private)**
```bash
ollama pull qwen3.5:9b
export LIFEOS_LLM_PROVIDER=ollama
```

**Option D: Anything else, via LiteLLM (OpenAI / Vertex / Azure / Bedrock / Cohere / Mistral / Groq / llama.cpp / vLLM / NVIDIA NIM …)**
```bash
export LIFEOS_LLM_PROVIDER=litellm
export LITELLM_MODEL=openai/gpt-4o-mini       # or vertex_ai/gemini-2.5-pro,
                                              # azure/gpt-4-turbo, bedrock/claude-...,
                                              # ollama/qwen2.5:14b, openai/local-llamacpp
# For self-hosted OpenAI-compatible endpoints (llama.cpp server, vLLM):
# export LITELLM_API_BASE=http://localhost:8080/v1
# Then set whichever provider's API key env var LiteLLM expects.
```
LiteLLM gives you ~100 providers behind one env var. The native Gemini
and Claude paths stay because they're tuned for tool-use latency; switch
to `litellm` when you want anything else.

### Embeddings (semantic search backbone)

Defaults to a local `bge-small-en-v1.5` model — no API key, runs offline.
Override with `EMBEDDING_PROVIDER=gemini` (768-dim) or `openai` (1536-dim).

```bash
pip install sentence-transformers       # for local default
mastermode embed backfill                # vectorize your existing graph
mastermode embed status                  # coverage stats
mastermode embed search "my cofounder" --kind entity
```

### Web search & fetch (optional)

Two chat tools: `web_search` and `web_fetch`. Default search is DuckDuckGo (no
key); upgrade to Tavily or Brave for better quality:

```bash
export TAVILY_API_KEY=your-key          # or BRAVE_SEARCH_KEY
```

Default fetch uses `httpx + readability`. For JS-heavy sites, point at the
Obscura headless browser:

```bash
export OBSCURA_BIN=/path/to/obscura     # https://github.com/h4ckf0r0day/obscura
```

### Set up Telegram bot

1. Open Telegram, search for [@BotFather](https://t.me/BotFather)
2. Send `/newbot`, give it a name (e.g., "MasterMode")
3. Copy the token

```bash
export TELEGRAM_BOT_TOKEN=your-token
mastermode bot
```

Send `/start` to your bot — it replies with your chat ID. To turn on the
**proactive side** (daily briefing, open-loop nudges, weekly review — the part
that actually keeps you coming back), set that ID and restart:

```bash
export TELEGRAM_CHAT_ID=the-id-/start-gave-you
mastermode bot
```

Without `TELEGRAM_CHAT_ID` the bot still answers you, but it can't reach out
first — no daily pings.

### Optional: Web dashboard

```bash
# In a separate terminal
mastermode serve --port 8100

# Frontend
cd frontend && npm install && npm run dev
# Open http://localhost:5173
```

### Connect to Claude Desktop / Cursor / any MCP client

MasterMode is an MCP server: your life graph becomes persistent memory for
every AI you already use. The client LLM does the talking; MasterMode does
the remembering. No API key needed — the server only touches the local
SQLite graph.

```bash
mastermode mcp            # stdio, for desktop clients
mastermode mcp --http     # Streamable HTTP on 127.0.0.1:8765
```

Claude Desktop (`claude_desktop_config.json`) or Claude Code (`.mcp.json`):

```json
{
  "mcpServers": {
    "mastermode": {"command": "mastermode", "args": ["mcp"]}
  }
}
```

Exposed tools: `recall` (RAG context for any personal question),
`semantic_search`, `search_entities`, `get_entity`, `search_everything`,
`life_context`, `remember_entity`, `remember_relationship`,
`update_entity`, `forget_entity`, `forget_relationship`,
`add_journal_entry`, open-loop tracking, `graph_stats`. Channel- and
LLM-dependent tools (email, reminders, deep research) are deliberately
not exposed — the MCP surface is pure memory.

### Optional: Gmail + Google Calendar

```bash
# 1. Create OAuth credentials at https://console.cloud.google.com
# 2. Enable Gmail API + Calendar API
# 3. Download client secret JSON
cp ~/Downloads/client_secret_*.json ~/.lifeos/google_credentials.json
mastermode google-auth
```

---

## What can it do?

### Talk to it naturally
Send any message — it responds with full life context and learns from everything you say.

> "I had coffee with Arjun today, he's thinking about leaving Google"
>
> *Creates Person: Arjun, Organization: Google, relationship: friend. Silently.*

> "I'm feeling stressed about the move this Saturday"
>
> *Records mood (negative, intensity 3). References your furniture move event and upcoming U-Haul need.*

> "Schedule a meeting with Jay tomorrow at 3pm"
>
> *Creates a Google Calendar event.*

> "Remind me in 2 hours to call the landlord"
>
> *Sets a timed reminder. You'll get a Telegram notification in 2 hours.*

### Capture from anywhere

```bash
# Drop free text — entities + relationships extracted automatically.
# Pre-extraction dedup uses your existing graph as a hint set, so saying
# "Jay" links to the existing Jay Neo instead of creating a variant.
mastermode capture "I caught up with Jay Neo about Palo's fundraising. New investor: Maria Chen at Sequoia."
```

Or hit the HTTP endpoint from any device — iOS Shortcut, mac Services menu, voice memo folder watcher, Slack forwarder, etc.:

```bash
curl -X POST http://localhost:8100/api/capture \
  -H 'Content-Type: application/json' \
  -d '{"text":"Lunch with Rohan, mentioned a new AI startup", "source":"iOS"}'
```

### Bring your history (zero cold-start)

Already spent a year talking to ChatGPT or Claude? Import it and the advisor
knows you on day one — no blank graph, no weeks of patient logging.

```bash
# ChatGPT: Settings → Data controls → Export → emailed zip.
mastermode import-chatgpt ~/Downloads/chatgpt-export.zip

# Claude.ai: Settings → Account → Export data → emailed zip.
mastermode import-claude ~/Downloads/claude-export.zip

# See what's in there first, write nothing:
mastermode import-chatgpt ~/Downloads/chatgpt-export.zip --dry-run

# Free + offline — just store messages for semantic recall, skip the
# LLM entity-extraction pass:
mastermode import-claude ~/Downloads/claude-export.zip --no-extract

# Only the 200 most recent conversations:
mastermode import-claude ~/Downloads/claude-export.zip --max 200
```

Both importers share one pipeline: every message is stored and embedded for
recall; your own messages are mined for entities and relationships through the
same dedup pipeline as live capture. Re-importing the same export is safe —
messages dedupe on a stable id. Follow with `mastermode dedup scan` to merge
any near-duplicates.

### Feed it your data
```bash
# Interactive Q&A — walks you through questions about yourself
mastermode ingest

# Ingest specific category
mastermode ingest --category work
mastermode ingest --category relationships

# Extract from documents (resume, portfolio, etc.)
mastermode extract -f ~/resume.pdf
mastermode extract -d ~/portfolio-website

# Extract from raw text
mastermode extract -t "I'm a software engineer at Google, previously at Meta..."

# Smart mode — skips boilerplate, extracts only personal facts
mastermode ingest --smart --dir ~/my-website
```

The more you feed it, the better it knows you.

### Graph hygiene (find + merge duplicates)

Every personal graph rots over time as variants creep in ("Palo" + "Palo ai", "Arjun" + "Arjun K"). MasterMode hunts them with embedding similarity, then puts each candidate pair through an LLM gate — naive cosine alone would wrongly merge "Java" + "JavaScript".

```bash
mastermode dedup scan                    # find candidates, get LLM verdicts
mastermode dedup merge <loser> <winner>  # apply (rels migrate, audit logged, reversible)
mastermode dedup distinct <a> <b>        # mark NOT same — never propose again
```

### Saturday weekly review

The chief-of-staff moment, grounded in your real data:

```bash
mastermode review
```

```
Weekly review — 2026-05-09
"Key goals like moving and fundraising are stalled, several relationships gone cold."

Pulse: 0 captures · 0 journal · 6 new entities
Goal velocity: Get a U-Haul: 0 this week (0 last)
Gone cold: Father — 44 days · Swati — 42 days · Nishi — 42 days

Top 3 suggested actions
 1. Reach out to your Father — 44 days since last mention
 2. Initiate progress on 'Get a U-Haul' — zero check-ins
 3. Address open loop 'have to configure yourself'
```

Auto-delivered to Telegram every Saturday at 9am.

### Proactive features (runs automatically)
- **Daily briefing** — calendar, inbox, birthdays, open loops, goals, mood
- **Saturday weekly review** — mood trend, cold relationships, goal velocity, top 3 suggested actions
- **Smart nudges** (every 15 min) — meeting prep with attendee context, deadline alerts, relationship decay
- **Life context synthesis** (nightly) — evolving "state of your life" that makes every conversation deeply personal
- **Open loop tracking** — captures "I need to..." from conversations, surfaces unresolved items
- **Curiosity questions** — asks about people/things it doesn't know well
- **Mood tracking** — auto-detects from conversation, tracks patterns over time

### Telegram commands

| Command | What it does |
|---------|-------------|
| `/start` | Welcome + graph stats |
| `/briefing` | Daily briefing (calendar, inbox, goals, mood, birthdays) |
| `/review` | Saturday weekly review on demand |
| `/people` | Your people with relationships |
| `/journal [text]` | Add or view journal entries |
| `/goals` | Goals and habits with streak counts |
| `/checkin <name>` | Check in on a goal/habit |
| `/remind` | Upcoming reminders (7 days) |
| `/loops` | Open loops (things to follow up on) |
| `/context` | Regenerate life context synthesis |
| `/reflect` | AI-powered weekly reflection (narrative) |
| `/mood` | Mood pattern summary |
| `/calendar` | Upcoming Google Calendar events |
| `/inbox` | Unread Gmail summary |
| `/graph` | Knowledge graph stats |

Plus: voice messages (auto-transcribed via Gemini), text-to-email with confirmation, calendar event creation.

### Web dashboard
- **Home** — stats, quick prompts, open loops, recent activity
- **Graph** — interactive force-directed knowledge graph visualization
- **What I Know** — browsable, searchable, editable entity grid
- **People** — filtered view of all people in your life
- **Journal** — entries with mood tags and entity links
- **Timeline** — chronological view of dated entities
- **AI Chat** — same brain as Telegram, in the browser

### CLI (40+ commands)

```bash
mastermode setup                 # Interactive first-run wizard
mastermode capture "..."         # Drop a thought, get it ingested
mastermode review                # Weekly review with suggested actions
mastermode embed backfill        # Build/refresh semantic search index
mastermode embed search "..."    # Semantic search across the graph
mastermode dedup scan            # Find duplicate candidates
mastermode dedup merge a b       # Fold loser into winner
mastermode ingest                # Interactive Q&A to populate your graph
mastermode extract -f resume.pdf # Extract entities from documents
mastermode people list           # Your people CRM
mastermode graph stats           # Entity/relationship counts
mastermode calendar              # Upcoming events
mastermode inbox                 # Unread emails
mastermode bot                   # Start Telegram bot
mastermode serve                 # Start API server
```

---

## Configuration

`mastermode setup` writes both `~/.lifeos/config.toml` and a sourceable
`~/.lifeos/mastermode.env`. To configure manually, set these env vars:

```bash
# LLM provider (pick one)
LIFEOS_LLM_PROVIDER=gemini          # gemini (default), claude, or ollama
GOOGLE_API_KEY=your-key             # for Gemini
# ANTHROPIC_API_KEY=your-key        # for Claude
# OLLAMA_MODEL=qwen3.5:9b           # for Ollama (default model)

# Embeddings — semantic search & dedup backbone
EMBEDDING_PROVIDER=local            # local (default, bge-small-en-v1.5),
                                    # gemini, or openai
# OPENAI_API_KEY=your-key           # only if EMBEDDING_PROVIDER=openai

# Telegram bot (optional)
TELEGRAM_BOT_TOKEN=your-token
TELEGRAM_CHAT_ID=your-chat-id       # enables proactive messages (get from /start)
LIFEOS_BRIEFING_TIME=08:00          # daily briefing time

# Web tools (all optional; defaults work without keys)
TAVILY_API_KEY=...                  # higher-quality search (1K/mo free)
BRAVE_SEARCH_KEY=...                # alternative (2K/mo free)
WEB_SEARCH_PROVIDER=tavily          # ddg | tavily | brave (auto-detected)
OBSCURA_BIN=/path/to/obscura        # https://github.com/h4ckf0r0day/obscura — use for JS-heavy sites

# Other
LIFEOS_LLM_MODEL=                   # override LLM model name
OLLAMA_BASE_URL=http://localhost:11434
```

### Data storage

Everything lives in `~/.lifeos/`:
- `lifeos.db` — SQLite database. Holds entities, relationships, journal,
  conversations, moods, and (since v0.2) sqlite-vec virtual tables for the
  semantic-search index, plus `audit_log`, `dedup_proposals`, and
  `distinct_pairs` for the graph-hygiene workflow.
- `config.toml` — written by `mastermode setup`
- `mastermode.env` — sourceable env file with secrets (mode 0600)
- `google_credentials.json` — OAuth credentials
- `google_token.json` — OAuth token (auto-refreshed)
- `filters.json` — email/calendar blacklists
- `life_state.json` — synthesized life context

Your data never leaves your machine unless you explicitly use a cloud LLM provider. With Ollama + the default local embeddings model, everything is 100% local.

---

## Architecture

```
┌──────────────────────────────────────────────────────────────┐
│                    Core Engine (Python)                       │
│                                                               │
│  Knowledge Graph ─── SQLite + sqlite-vec                      │
│  │                   entities · relationships · journal       │
│  │                   conversations · moods · audit_log        │
│  │                   vec_entities/journal/conversations/docs  │
│  │                                                            │
│  Embeddings ──────── Local bge-small (default)                │
│  │                   Gemini / OpenAI optional                 │
│  │                                                            │
│  Retrieval / RAG ─── Per-turn context retrieval               │
│  │                   semantic_search tool                     │
│  │                                                            │
│  AI Layer ────────── Multi-provider LLM                       │
│  │                   (Gemini / Claude / Ollama)               │
│  │                   19 tool functions                        │
│  │                                                            │
│  Web Tools ───────── DuckDuckGo / Tavily / Brave search       │
│  │                   httpx + readability fetch                │
│  │                   Obscura subprocess (optional)            │
│  │                                                            │
│  Graph Hygiene ───── Embedding dedup scan                     │
│  │                   LLM adjudicator                          │
│  │                   merge_entities + audit log               │
│  │                                                            │
│  Life Context ────── Nightly synthesis, open loop tracking,   │
│  │                   Saturday weekly review                   │
│  │                                                            │
│  Proactive ───────── Nudges, briefings, reminders, curiosity  │
└──────────┬──────────────────┬─────────────────┬──────────────┘
           │                  │                 │
    ┌──────▼──────┐    ┌──────▼─────┐    ┌──────▼─────┐
    │  Telegram   │    │  Web API   │    │    CLI     │
    │    Bot      │    │ (FastAPI)  │    │  (Typer)   │
    └─────────────┘    └────────────┘    └────────────┘
```

### AI Tools (what the LLM can do)

| Tool | Action |
|------|--------|
| `create_entity` | Add people, skills, goals, etc. to your graph |
| `update_entity` | Fix/update existing entities |
| `delete_entity` | Remove wrong information |
| `create_relationship` | Connect entities |
| `delete_relationship` | Remove connections |
| `search_knowledge` | Keyword search the graph |
| `semantic_search` | Embedding-based search across entities, journal, and past messages |
| `search_everything` | Deep cross-source search |
| `get_entity_detail` | Deep lookup on an entity |
| `set_reminder` | Timed reminders via Telegram |
| `create_calendar_event` | Create Google Calendar events |
| `send_email` / `confirm_send_email` | Draft + send Gmail (with confirmation) |
| `add_open_loop` / `resolve_open_loop` | Track / close to-dos |
| `create_decision` | Track a decision with options and pros/cons |
| `web_search` | Search the public web (DDG / Tavily / Brave) |
| `web_fetch` | Read a URL — main content as Markdown (Obscura optional for JS sites) |
| `draft_post` | Draft a Twitter/LinkedIn post in your voice |

---

## Self-Hosted vs. Managed

### Self-hosted (open source)
You run everything. Your data stays on your machine. Full control.

```bash
git clone, pip install, mastermode setup, mastermode bot
```

Best for: developers, privacy-conscious users, people who want to customize.

### Managed (coming soon)
We run the infrastructure. You just connect your Telegram + API keys.

Best for: non-technical users who want the experience without the setup.

Interested? [Join the waitlist →](https://github.com/shivampkumar/mastermode/issues)

---

## Tech Stack

| Layer | Technology |
|-------|-----------|
| Database | SQLite (WAL mode) + sqlite-vec virtual tables for embeddings |
| Embeddings | sentence-transformers `bge-small-en-v1.5` (default), Gemini, OpenAI |
| Backend | Python 3.11+, FastAPI, Typer |
| AI | Gemini / Claude / Ollama via unified LLMClient |
| Bot | python-telegram-bot v21 (async), apscheduler |
| Frontend | React 19, Vite, react-force-graph-2d |
| Integrations | Google Calendar API, Gmail API |
| Web search | DuckDuckGo (`ddgs`), Tavily, Brave |
| Web fetch | httpx + readability + html2text (default), Obscura (optional, JS rendering) |
| Document parsing | PyMuPDF, python-docx, Pillow |

---

## Privacy

- All data stored locally in `~/.lifeos/` (SQLite + vec0 virtual tables)
- Default embeddings model runs locally — no network call to vectorize
- With Ollama + local embeddings: zero data leaves your machine
- With Gemini/Claude: only conversation text is sent to LLM APIs (no bulk data export)
- Google integration uses OAuth2 with minimal scopes
- Email sending requires explicit confirmation
- Dedup merges write to `audit_log` and are reversible
- No telemetry, no analytics, no tracking

---

## Contributing

MasterMode is built by [Shivam Kumar](https://shivampkumar.com) as an open-source project.

Issues, PRs, and feature requests welcome at [github.com/shivampkumar/mastermode](https://github.com/shivampkumar/mastermode).

---

## License

MIT
