Skip to main content
Glama
README.md
<p align="center">
  <h1 align="center">🧠 Digital Brain</h1>
  <p align="center">
    <strong>AI-powered personal browsing history assistant that lives locally on your machine.</strong>
  </p>
  <p align="center">
    <a href="#-quick-start">Quick Start</a> β€’
    <a href="#-features">Features</a> β€’
    <a href="#-architecture">Architecture</a> β€’
    <a href="#-cli-usage">CLI</a> β€’
    <a href="#-mcp-server">MCP</a> β€’
    <a href="#-api-reference">API</a>
  </p>
</p>

<br/>

> **What was I working on yesterday related to RAG?**  
> **Which website did I spend the most time on last week?**  
> **What was that command I copied to clear the terminal?**

Digital Brain captures your Chrome browsing activity β€” page visits, text selections, copy/paste events, page content, and time spent β€” stores it **100% locally**, and lets you search and ask questions using AI. It combines **keyword search** (SQLite FTS5) with **semantic search** (ChromaDB vectors) through a **RAG pipeline** powered by a local LLM.

<br/>

## ✨ Features

| Feature | Description |
|---------|-------------|
| 🧩 **Chrome Extension** | Captures page visits, selections, copy/paste, page content, and tab focus time |
| ⚑ **FastAPI Backend** | Receives, stores, and indexes events locally on `localhost:8420` |
| πŸ” **Full-Text Search** | SQLite FTS5 keyword search with highlighted snippets and filters |
| 🧬 **Vector Search** | ChromaDB semantic indexing for meaning-based recall |
| πŸ€– **RAG Q&A** | Ask questions in plain English β€” uses local LLM to generate answers |
| πŸ“Š **Activity Stats** | Top domains by time spent, daily breakdowns, and event timelines |
| πŸ’» **CLI Tool** | Rich terminal interface with `brain search`, `brain ask`, `brain stats` |
| πŸ”Œ **MCP Server** | Query your history from Claude Desktop, VS Code, or any MCP client |
| πŸ›‘οΈ **Privacy-First** | All data stays on your machine β€” no cloud, no tracking |

<br/>

## πŸ“ Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Chrome Browser                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Chrome Extension (Manifest V3)                                β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚  β”‚  β”‚ Content.js  β”‚  β”‚ Background.js  β”‚  β”‚   Popup UI        β”‚   β”‚  β”‚
β”‚  β”‚  β”‚ β€’ Selectionsβ”‚  β”‚ β€’ Tab tracking β”‚  β”‚ β€’ Toggle on/off   β”‚   β”‚  β”‚
β”‚  β”‚  β”‚ β€’ Copy/Pasteβ”‚  β”‚ β€’ Event queue  β”‚  β”‚ β€’ View stats      β”‚   β”‚  β”‚
β”‚  β”‚  β”‚ β€’ Page text β”‚  β”‚ β€’ Batch flush  β”‚  β”‚ β€’ Sync now        β”‚   β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚  chrome.runtime β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚ POST /api/events (batch every 30s)
                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Local Backend (Python)                             β”‚
β”‚                                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚  β”‚ FastAPI   │──▢│ Event        │──▢│ SQLite+FTS5  β”‚                β”‚
β”‚  β”‚ Server    β”‚   β”‚ Processor    β”‚   β”‚ (structured) β”‚                β”‚
β”‚  β”‚ :8420     β”‚   β”‚ dedup+domain β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                                    β”‚
β”‚       β”‚                β”‚          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚       β”‚                └─────────▢│ ChromaDB     β”‚                   β”‚
β”‚       β”‚                           β”‚ (semantic)   β”‚                   β”‚
β”‚       β–Ό                           β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚                           β”‚
β”‚  β”‚ RAG      │◀───── vector search β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚  β”‚ Pipeline  │◀───── FTS5 search β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                                                        β”‚
β”‚       β”‚                                                              β”‚
β”‚       β–Ό                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                        β”‚
β”‚  β”‚ LLM      β”‚  Ollama (local, free) or OpenRouter (cloud)            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β–²               β–²               β–²
        β”‚               β”‚               β”‚
   β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
   β”‚   CLI   β”‚    β”‚ MCP Serverβ”‚   β”‚ REST API  β”‚
   β”‚ $ brain β”‚    β”‚ Claude/   β”‚   β”‚ curl/apps β”‚
   β”‚  search β”‚    β”‚ VS Code   β”‚   β”‚           β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

<br/>

## πŸš€ Quick Start

### Prerequisites

- **Python 3.10+**
- **Google Chrome** (latest)
- **Ollama** (optional β€” for AI-powered answers)

### 1. Clone & Install

```bash
git clone https://github.com/ArpitaSethi-12/digital-brain.git
cd digital-brain
pip install -e .
```

### 2. Start the Backend

```bash
python -m backend.main
```

```
Digital Brain backend is ready  🧠
Server running at http://localhost:8420
```

### 3. Install the Chrome Extension

1. Open `chrome://extensions/` in Chrome
2. Enable **Developer mode** (top-right toggle)
3. Click **Load unpacked** β†’ select the `extension/` directory
4. The 🧠 icon appears in your toolbar

### 4. (Optional) Install Ollama for AI Answers

```bash
# Install Ollama from https://ollama.com
ollama serve
ollama pull llama3.2
```

Without Ollama, Digital Brain still works β€” it returns retrieved results instead of generated answers.

### 5. Start Browsing!

Open any website. The extension captures your activity in the background. Then query it:

```bash
brain search "python tutorial"
brain ask "What was I reading about yesterday?"
brain stats
```

<br/>

## πŸ’» CLI Usage

Digital Brain ships with a CLI built on [Typer](https://typer.tiangolo.com/) + [Rich](https://rich.readthedocs.io/):

### Search

```bash
# Basic search
brain search "RAG pipeline"

# Filter by event type
brain search "terminal command" --type copy

# Filter by domain
brain search "react hooks" --domain github.com

# Filter by time window
brain search "python" --last 7d        # last 7 days
brain search "docker" --last 24h       # last 24 hours
brain search "AI paper" --last 2w      # last 2 weeks
```

### Ask (RAG Q&A)

```bash
brain ask "What was I working on yesterday related to RAG?"
brain ask "What command did I copy to clear the terminal?" --type copy
brain ask "Which website did I spend the most time on?" --last 7d
brain ask "Summarize what I read about transformers" --no-llm  # skip LLM
```

### Stats & Activity

```bash
brain stats                    # top domains + weekly activity
brain stats --period month     # monthly breakdown
brain activity                 # today's timeline
brain activity --date yesterday
brain activity --date 2026-06-01
```

### System

```bash
brain status     # backend health + LLM availability
brain reindex    # rebuild vector index from SQLite
```

<br/>

## πŸ”Œ MCP Server

Digital Brain includes an **MCP (Model Context Protocol) server** that lets AI assistants query your browsing history directly.

### How It Works

```
You:    "What was I working on yesterday related to RAG?"
Claude: β†’ calls search_history("RAG", last="1d")
        β†’ Digital Brain searches local SQLite + ChromaDB
Claude: "Yesterday you visited 3 pages about RAG pipelines..."
```

### Available Tools

| Tool | Description |
|------|-------------|
| `search_history` | Keyword search with type/domain/time filters |
| `ask_brain` | RAG-powered natural language Q&A |
| `get_stats` | Top domains and activity breakdown |
| `get_activity` | Day's chronological timeline |
| `get_timeline` | Detailed event feed with full content |
| `check_status` | Backend health + LLM status |

### Setup with Claude Desktop

1. Start the backend: `python -m backend.main`

2. Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "digital-brain": {
      "command": "python3",
      "args": ["/absolute/path/to/digital-brain/mcp_server.py"]
    }
  }
}
```

3. Restart Claude Desktop β€” the 🧠 tools appear automatically.

### Setup with VS Code

Add to `.vscode/settings.json`:

```json
{
  "mcp": {
    "servers": {
      "digital-brain": {
        "command": "python3",
        "args": ["/absolute/path/to/digital-brain/mcp_server.py"]
      }
    }
  }
}
```

### Test with MCP Inspector

```bash
npx -y @modelcontextprotocol/inspector python3 mcp_server.py
```

<br/>

## πŸ“‘ API Reference

The backend exposes a REST API at `http://localhost:8420`:

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/health` | Backend health status |
| `POST` | `/api/events` | Ingest event batch from extension |
| `GET` | `/api/search?q=...` | Full-text search with filters |
| `POST` | `/api/ask` | RAG question answering |
| `GET` | `/api/ask?q=...` | RAG via query string |
| `GET` | `/api/stats/domains` | Top domains by time spent |
| `GET` | `/api/stats/activity?period=week` | Daily event breakdown |
| `GET` | `/api/stats/timeline?date=2026-06-01` | Event timeline for a date |
| `POST` | `/api/index/rebuild` | Rebuild vector index |
| `GET` | `/api/llm/status` | Check LLM availability |

### Example: Ask a Question

```bash
curl -X POST http://localhost:8420/api/ask \
  -H "Content-Type: application/json" \
  -d '{"question": "What did I copy about clearing the terminal?"}'
```

**Response:**
```json
{
  "answer": "You copied the command 'clear && printf ...' from Stack Overflow.",
  "sources": [
    {
      "event_type": "copy",
      "domain": "stackoverflow.com",
      "content": "clear && printf '\\e[3J'"
    }
  ],
  "llm_used": true,
  "retrieval_count": 3
}
```

### Example: Search History

```bash
curl "http://localhost:8420/api/search?q=RAG&event_type=page_visit&limit=5"
```

<br/>

## πŸ“ Project Structure

```
digital-brain/
β”œβ”€β”€ extension/                  # Chrome Extension (Manifest V3)
β”‚   β”œβ”€β”€ manifest.json           # Permissions & config
β”‚   β”œβ”€β”€ background.js           # Service worker β€” event batching, tab tracking
β”‚   β”œβ”€β”€ content.js              # Content script β€” selections, copy/paste, page text
β”‚   β”œβ”€β”€ popup.html/js/css       # Extension popup UI
β”‚   └── icons/                  # Extension icons
β”‚
β”œβ”€β”€ backend/                    # Python FastAPI Backend
β”‚   β”œβ”€β”€ main.py                 # App entry point with CORS & lifespan
β”‚   β”œβ”€β”€ config.py               # Environment-based configuration
β”‚   β”œβ”€β”€ models.py               # 13 Pydantic models (API contract)
β”‚   β”œβ”€β”€ database.py             # SQLite + FTS5 (schema, CRUD, search)
β”‚   β”œβ”€β”€ routers/
β”‚   β”‚   β”œβ”€β”€ events.py           # POST /api/events
β”‚   β”‚   β”œβ”€β”€ search.py           # GET /api/search
β”‚   β”‚   β”œβ”€β”€ stats.py            # GET /api/stats/*
β”‚   β”‚   └── ask.py              # POST /api/ask + index rebuild
β”‚   └── services/
β”‚       β”œβ”€β”€ event_processor.py  # Validate, dedup, extract domains
β”‚       β”œβ”€β”€ vector_store.py     # ChromaDB operations
β”‚       β”œβ”€β”€ rag.py              # RAG pipeline (vector + FTS β†’ LLM)
β”‚       β”œβ”€β”€ llm.py              # Ollama / OpenRouter client
β”‚       └── indexer.py          # Vector index rebuild
β”‚
β”œβ”€β”€ cli/
β”‚   └── brain.py                # Typer + Rich CLI (6 commands)
β”‚
β”œβ”€β”€ mcp_server.py               # MCP server (6 tools for AI assistants)
β”‚
β”œβ”€β”€ data/                       # Local storage (auto-created, gitignored)
β”‚   β”œβ”€β”€ brain.db                # SQLite database + FTS5 index
β”‚   └── chroma/                 # ChromaDB vector store
β”‚
β”œβ”€β”€ .env.example                # Environment variable template
β”œβ”€β”€ pyproject.toml              # Project config & dependencies
└── README.md
```

<br/>

## βš™οΈ Configuration

Copy the example and customize:

```bash
cp .env.example .env
```

| Variable | Default | Description |
|----------|---------|-------------|
| `BRAIN_HOST` | `127.0.0.1` | Backend host |
| `BRAIN_PORT` | `8420` | Backend port |
| `BRAIN_DATA_DIR` | `./data` | Storage directory |
| `BRAIN_LLM_PROVIDER` | `ollama` | `ollama` or `openrouter` |
| `OLLAMA_BASE_URL` | `http://localhost:11434` | Ollama server URL |
| `OLLAMA_MODEL` | `llama3.2` | Ollama model name |
| `OPENROUTER_API_KEY` | β€” | OpenRouter API key (optional) |
| `BRAIN_RAG_TOP_K` | `8` | Number of results for RAG context |

<br/>

## 🧬 How RAG Works

```
User: "What command did I copy to clear the terminal?"
 β”‚
 β”œβ”€β”€β–Ά ChromaDB Semantic Search
 β”‚    Finds events with similar meaning
 β”‚    (e.g., "bash clear screen" matches "terminal command")
 β”‚
 β”œβ”€β”€β–Ά SQLite FTS5 Keyword Search
 β”‚    Finds events containing exact words
 β”‚    (e.g., "clear" AND "terminal")
 β”‚
 β”œβ”€β”€β–Ά Merge & Deduplicate
 β”‚    Combines both result sets by event ID
 β”‚
 β”œβ”€β”€β–Ά Format Context Block
 β”‚    Prepares retrieved events as LLM context
 β”‚
 └──▢ LLM Generation (Ollama)
      Generates natural language answer
      grounded in your actual browsing data

Result: "You copied 'clear && printf \\e[3J' from stackoverflow.com on June 8th."
```

<br/>

## πŸ›‘οΈ Privacy

Digital Brain is **privacy-first by design**:

- βœ… All data stored locally in `data/` directory
- βœ… Chrome extension only communicates with `localhost:8420`
- βœ… MCP server runs locally via stdio β€” no network requests
- βœ… LLM runs locally via Ollama β€” your data never leaves your machine
- βœ… No analytics, no telemetry, no cloud sync
- ⚠️ OpenRouter is optional and only used if you explicitly set `OPENROUTER_API_KEY`

<br/>

## πŸ› οΈ Tech Stack

| Layer | Technology |
|-------|-----------|
| Data Capture | Chrome Extension (Manifest V3) |
| Backend | Python 3.10+ Β· FastAPI Β· Uvicorn |
| Structured DB | SQLite 3 + FTS5 |
| Vector DB | ChromaDB (all-MiniLM-L6-v2 embeddings) |
| Local LLM | Ollama (llama3.2) |
| Cloud LLM | OpenRouter (optional) |
| CLI | Typer + Rich |
| MCP | FastMCP (mcp SDK) |
| Validation | Pydantic v2 |
| HTTP Client | httpx (async) |

<br/>

## πŸ“Š Project Stats

| Metric | Value |
|--------|-------|
| Total Lines of Code | ~3,800 |
| Python Files | 18 |
| JavaScript Files | 3 |
| API Endpoints | 10 |
| CLI Commands | 6 |
| MCP Tools | 6 |
| Pydantic Models | 13 |
| Event Types Captured | 6 |
| Dependencies | 10 |

<br/>

## πŸ—ΊοΈ Roadmap

- [ ] 🌐 Web chat UI with streaming responses
- [ ] πŸ“… Smarter date parsing ("yesterday", "last week") in RAG
- [ ] πŸ”’ Optional encryption at rest for `data/`
- [ ] πŸ”Œ MCP Registry listing
- [ ] πŸ“± Firefox extension
- [ ] 🧠 Multi-turn conversation memory
- [ ] πŸ“¦ PyPI package (`pip install digital-brain`)

<br/>

## 🀝 Contributing

Contributions are welcome! Here's how:

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

<br/>

## πŸ“„ License

This project is licensed under the MIT License β€” see the [LICENSE](LICENSE) file for details.

---

<p align="center">
  Built with ❀️ as a BTech Major Project
</p>

TDQS

A4/5.0

Scored across 6 tools

Disambiguation4/5

Most tools are distinct, but get_activity and get_timeline have overlapping purposes (both show timeline, get_timeline just more detailed). Also, ask_brain and search_history both retrieve history but through different interfaces (Q&A vs keyword search), which could cause ambiguity. Overall, boundaries are clear for most tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using snake_case: ask_brain, check_status, get_activity, get_stats, get_timeline, search_history. The pattern is uniform and predictable.

Tool Count5/5

With 6 tools, the set is well-scoped for a browsing history assistant. Each tool serves a distinct need (Q&A, health check, daily overview, statistics, detailed timeline, keyword search) without redundancy or bloat.

Completeness4/5

The tool surface covers the main browsing history interactions: query, search, timeline, stats, health. However, there is no dedicated tool to retrieve all events of a specific type without a date or search query, which is a minor gap. Otherwise, the set feels complete for a read-only assistant.

Maintenance

ActivityInactive
ResponsivenessNo issues