Skip to main content
Glama
README.md
# brain

**Your local second brain for Claude, ChatGPT and any AI agent.**

brain is an [MCP](https://modelcontextprotocol.io) server that runs on your computer (macOS, Linux or Windows) and gives your AI agents a shared memory: your notes, your projects, what they know about you and the web pages you saved, with semantic search. Connect it once to Claude, ChatGPT, Cursor or whatever agent you use, and they all read and write the same knowledge base. Everything stays on your computer; agents in the cloud (Claude.ai, Manus on the web…) can reach it through an optional private URL.

It ships with a web dashboard so you never have to touch the terminal: turn services on and off, fill in your profile, import the memory other chatbots have about you, connect agents, explore the connection graph and search what you saved.

```bash
curl -fsSL https://raw.githubusercontent.com/Lautaro005/brain/main/install.sh | bash      # macOS and Linux
```
```powershell
irm https://raw.githubusercontent.com/Lautaro005/brain/main/install.ps1 | iex               # Windows (PowerShell)
```

Then type `brain` and the dashboard opens.

**Website:** https://lautaro005.github.io/brain/ · **Docs:** https://lautaro005.github.io/brain/docs/ · **Changelog:** https://lautaro005.github.io/brain/changelog/

---

## Contents

- [What you can do](#what-you-can-do)
- [Installation](#installation)
- [Getting started](#getting-started)
- [The dashboard](#the-dashboard)
- [Connecting agents](#connecting-agents)
- [How it works](#how-it-works)
- [Connections](#connections)
- [Fact check](#fact-check)
- [MCP tools](#mcp-tools)
- [The `brain` command](#the-brain-command)
- [Data, privacy and security](#data-privacy-and-security)
- [Troubleshooting](#troubleshooting)
- [Uninstalling](#uninstalling)
- [Development](#development)
- [License](#license)
- [Security](#security)

---

## What you can do

- **Let your agents know you.** Write a profile (who you are, what you do, how you like to work) and import the memory ChatGPT, Claude or Gemini already have about you. Every connected agent reads it when it starts and saves anything new it learns with `add_memory`.
- **One knowledge base, shared by every agent.** Markdown notes organized into projects and skills. What Claude writes today, ChatGPT can read tomorrow.
- **Save the web.** Give brain a URL and it downloads the page, extracts the text (including sites built with JavaScript), indexes it and makes it available to semantic search: you search by meaning, not exact words.
- **Chat with your memory.** A local Ollama model that already knows your profile and memory. Ask it things, or have it save, add or edit notes for you. Chats are kept in Chroma, and you can pop the chat out into a floating window that stays on top of your other apps.
- **See how everything connects.** An interactive graph shows your profile, memories, projects, skills, sources and tags, and how they relate. When the chat or an agent wants to link or unlink notes, you first see an image of the change and approve it.
- **Check facts, with the evidence in view.** Fact check splits a text into claims, looks in your memory first and on the web only if needed, reads every page, looks for counter-evidence and gives a verdict by rules, with quotes, dates and limitations.
- **Undo anything.** Every write goes into a version history. If an agent deletes or overwrites something, you get it back.
- **Bring your apps along.** Plug other MCP servers into brain (GitHub, Notion, Gmail…, or hundreds of apps through Composio): their tools show up in every agent you connected, and whatever they fetch is saved to your memory automatically.
- **Private by design.** Embeddings are computed on your machine with [Ollama](https://ollama.com), and your data never leaves your computer (the only request brain makes on its own is checking GitHub for a new version; Fact check searches the web only when you run it).

## Installation

**Requirements:** macOS, Linux or Windows, and git. The installer takes care of the rest.

| System | Command | File |
|---|---|---|
| macOS | `curl -fsSL https://raw.githubusercontent.com/Lautaro005/brain/main/install.sh \| bash` | |
| Linux | same command | `brain-install-linux.sh` in each [release](https://github.com/Lautaro005/brain/releases/latest) (`bash brain-install-linux.sh`) |
| Windows | `irm https://raw.githubusercontent.com/Lautaro005/brain/main/install.ps1 \| iex` (PowerShell) | `brain-setup.exe` in each [release](https://github.com/Lautaro005/brain/releases/latest) |

Missing git? macOS: `xcode-select --install`. Linux: your distro's package manager (`sudo apt install git`). Windows: the installer tries `winget`, or get it from [git-scm.com](https://git-scm.com/download/win). `brain-setup.exe` isn't code-signed yet, so Windows SmartScreen may ask you to confirm (*More info → Run anyway*).

Every commit to `main` runs the tests and both installers on macOS, Linux and Windows in GitHub Actions, and every release attaches the Windows `.exe` and the Linux installer.

The installer:

1. Installs [uv](https://docs.astral.sh/uv/) if you don't have it (it manages Python and the dependencies without touching the system Python).
2. Downloads brain into `~/.brain`.
3. Installs the dependencies and the headless Chromium used to scrape JavaScript sites.
4. Installs [Ollama](https://ollama.com) if needed (Homebrew on macOS, `winget` on Windows, the official script on Linux when `sudo` doesn't ask for a password; otherwise it tells you the command), and pulls the `nomic-embed-text` embedding model (~270 MB). Without Homebrew, it tells you where to download Ollama. The chat model (`llama3.2`, ~2 GB) is **optional** and not pulled automatically: it powers the Chat tab, source summaries (`abstract`) and entity extraction for the graph. Get it with `ollama pull llama3.2` or the *Download llama3.2* button in the Chat tab; without it those three features are skipped and everything else works. Use another model with `BRAIN_SUMMARY_MODEL=<model>`, or turn summaries and entities off with `BRAIN_SUMMARY_MODEL=off`.
5. Creates the `brain` command in `~/.local/bin` (`%USERPROFILE%\.local\bin\brain.cmd` on Windows) and adds it to your `PATH` if it wasn't there.

On Linux, Chromium needs some system libraries; if they're missing the installer prints the one command to add them (`sudo uv run playwright install-deps chromium`).

Running it again updates the install. To install somewhere else, set `BRAIN_HOME=~/some/folder` before `bash`.

<details>
<summary>Manual installation</summary>

```bash
git clone https://github.com/Lautaro005/brain ~/.brain && cd ~/.brain
uv sync
uv run playwright install chromium
ollama pull nomic-embed-text
./brain.sh
```
</details>

## Getting started

1. **Open the dashboard:** `brain`. It opens at `http://127.0.0.1:8765` and starts Ollama and the Chroma server if they aren't running. Keep it open while you use your agents; Ctrl+C closes it.
2. **Connect your agents:** **Connect agent** tab → *Connect* on Claude Desktop, ChatGPT or whichever you use.
3. **Tell it who you are:** **Profile** tab → fill in "About you" and import your memory from another chatbot.
4. **Try it:** in Claude, ask *"what do you know about me according to brain?"* or *"save this URL to brain: …"*.

## The dashboard

| Tab | What it's for |
|---|---|
| **Dashboard** | Switches to turn **Chroma**, **Ollama** and the **MCP Inspector** (a UI to try the tools by hand) on and off. Vault metrics, activity charts for the last 30 days, sources by domain, operations, system health and recent changes. |
| **Chat** | Talk to a local Ollama model with your profile, all your memories, the `BRAIN.md` index and related bits of past chats as context. It gets the same tools your agents get (read, search, write, `add_memory`, `save_url`, your connections…), so it can look things up and make changes. Every tool call is listed in the answer, and you can expand each one to see its arguments and result; every write lands in the version history. Models that can't take native tools (common with GGUF models pulled from Hugging Face) get the tools as text instead, so they can act on the vault too. Pick the model from the ones installed in Ollama (or download `llama3.2` in one click) when you start a chat; it then stays with that chat. A circle next to the send button fills up as the chat uses the model's context window. Rename a chat with the pencil next to its title. Type `/` for commands: **`/organize`** tidies up the vault and its graph with a built-in skill (adapted from [file-organizer](https://github.com/davila7/claude-code-templates/blob/main/cli-tool/components/skills/productivity/file-organizer/SKILL.md)): it asks how you want it organized, proposes a plan and changes only what you approve; **`/add-mcp`** sets up a connector from a URL or instructions (you approve it with one click before anything runs); **`/factcheck`** verifies a claim with [Fact check](#fact-check); `/compact` summarizes the conversation the way Claude Code does (main request, every instruction you gave, decisions, exact data and paths, changes made with tools, pending work and what it was doing), in parts if it doesn't fit, so the model keeps going from the summary; add instructions after it (`/compact focus on the dates`). When a chat reaches 85% of the context window it compacts by itself before answering, and right after compacting brain preloads the new context in Ollama so the next answer doesn't wait; `/reflect` brings Reflect's suggestions into the chat; `/new` starts a new chat. Below the commands, under **Your skills**, come the skills saved in your vault's `skills/` (usually written by your agents): `/<skill>` loads it into the chat. The chat always gets a fixed guide to how brain works, so it can tell you where things are, and clear working rules: understand the request, use just the tools it needs, never repeat the same call, and always end with an answer. Answers can include HTML (tables, collapsible sections, simple diagrams), sanitized so no script, form or outside image gets through. When the model writes an `html` (or `svg`) code block, it's shown as a rendered **preview** once the answer is done, with a *Preview / Code* toggle in its top-right corner and *Copy*; the preview runs in an isolated frame with no scripts or internet resources unless you click *Run scripts*. To link or unlink notes it calls `propose_graph_change`: you see an image of the graph with the change marked and approve, reject or undo it. Chats are saved in Chroma (`chats` collection) with a searchable list; **Float** opens the chat in an always-on-top window (Document Picture-in-Picture in Chrome, Edge and Arc; a regular pop-up elsewhere). |
| **Profile** | Your details (name, headline, about me) and your memory. Below *About you*, **What brain knows about you** is a summary of your memory that rewrites itself whenever a memory changes, and goes into `profile.md` so every agent reads it. The importer takes 3 steps: pick the chatbot, copy a prompt that asks it for all its memory in a fixed format, and paste the answer (or upload a `.txt`, `.md` or `.json`). You get a preview before importing and can drop anything you don't want. **Reflect** reviews your memory and suggests fixes (duplicates, contradictions, notes without entities) without changing anything. |
| **Connect agent** | Connect and disconnect brain from Claude Desktop, ChatGPT, OpenMausBot, DeepSeek Harness, Claude Code, Codex, Cursor, VS Code, Windsurf and Gemini CLI in one click, Manus Studio with the values for its form (under *Any other MCP client*), **remote access by URL** for agents in the cloud, plus manual setup for anything else. **My connections** lists the agents brain configured, plus any app that used brain (detected from the MCP handshake, so apps where you added brain with an "Add MCP server" form show up the first time they use it) and apps you note by hand. |
| **Connections** | Other MCP servers brain uses on your behalf: add them as a local command or a URL (or through Composio), switch each one on or off, choose whether its results are saved to memory, refresh its tools. Servers that need a login (OAuth) show **Sign in**: it opens the service's own sign-in page and brain keeps the token. Connections an agent proposed (`/add-mcp` in the chat) wait here for you to approve them. |
| **Graph** | Interactive map of the vault: profile, memory, projects, skills, sources, folders, tags and entities. Click a node to see its content and connections. Controls to zoom in, zoom out and **re-center** (also the `0` key or double-clicking the background). Graph changes proposed by an agent wait at the top, with their image, to be approved or rejected. |
| **Knowledge** | Save a URL (optionally forcing JavaScript rendering), hybrid search (semantic score, or a *keyword* tag for exact matches), a button to rebuild the keyword index, and the list of saved sources with how old their content is and when they were last checked. **Refresh** re-downloads one source or all of them; if a refresh fails, the last good copy is kept and the error is shown. |
| **Fact check** | Verify claims: brain searches your memory first and the web only if that's not enough (and says so), reads every page, groups sources that aren't independent, looks for counter-evidence and gives a verdict by rules (supported, likely supported, mixed, inconclusive, likely false, false, not verifiable) with quotes, dates and limitations. Preferences are set once: level, freshness, primary sources, counter-evidence, claim types, high-risk topics, regions, languages, source types, search engine (DuckDuckGo, SearXNG, Brave, or a search tool from your Connections such as OpenSEO or Composio), blocked domains, and whether the chat and all your agents check facts that aren't in brain on their own. Copy the report, save a source to brain or block a domain with one click. |
| **Logs** | Live output of every service the dashboard manages. |

The bottom of the sidebar has the theme (system, light or dark), the language (**English / Español**), an **i** button that lists the services (Chroma, Ollama, MCP Inspector) and their state, and **Settings** (the gear), a full view where you can:

- see the installed **version** and **check for updates**: brain asks GitHub for the latest release when the dashboard opens, every 3 hours while it's open, and when you click the button. If there's a newer one, Settings shows it with a link to the release notes and the gear turns green; the green **Update and restart** button next to *Check for updates* closes brain, updates it and reopens it (the page reloads by itself), or run `brain update`;
- reorder the **sidebar** and hide the views you don't use (a hidden view is still reachable by its URL, e.g. `#logs`);
- pick the **default chat model**, used when the chat opens and on every new chat;
- set the chat's **context window**: each model's maximum with a cap for all (16k by default), everything each model supports, or a value per model, with a table of the detected models and what they support;
- make a **backup** of everything local (vault, history, settings, connections and what's indexed in Chroma, embeddings included) and **restore** it; credentials are left out unless you tick the box, and restoring first saves a backup of the current state;
- set up an **automatic backup** (*Automatic backup…*): the folder (any folder, e.g. an external drive or a synced folder, with a folder picker), how often (every X hours, every day or once a week, at a set time), the file name (`{date}`, `{time}`, `{version}`, `{n}`), how many to keep, whether to include credentials and whether to skip it when nothing changed. It runs while brain is open, and catches up when you open it if one was missed;
- write a **system prompt** for the chat: how you want it to answer (tone, format, language, focus), added to brain's own instructions; the chat's fixed app context is shown below it, read-only;
- turn on **system notifications** for uploads, changes and deletions in your vault, whether an agent, the chat or you made them;
- **note format**: fill in `type`, `created` and `updated` on older notes in one click (new writes get them automatically);
- give each graph node type (Brain, Profile, Memory, Projects, Skills, Sources, Notes, Folders, Tags, Entities) its own color, or go back to black and white.

The button next to the logo collapses the sidebar into a narrow rail of icons.

When you close the dashboard, it only stops what it started. If Ollama was already running (for example the menu-bar app), it shows up as **External** and is left alone.

## Connecting agents

Each agent keeps its list of MCP servers in its own file. When you click *Connect*, brain adds its entry without touching the rest of the file, and saves a backup first (`<file>.bak-brain`).

| Agent | Where it's configured | Notes |
|---|---|---|
| **Claude Desktop** (chat and Cowork) | `~/Library/Application Support/Claude/claude_desktop_config.json` | Claude rewrites this file when it quits, so it's edited with the app closed. If it's open, the dashboard offers to quit it, connect and reopen it. |
| **ChatGPT** (desktop app) | `~/.codex/config.toml` | Works in **Codex** and **ChatGPT Work** modes; regular ChatGPT chat doesn't use local servers. Afterwards: *Settings → MCP servers → Restart*. Shares its config with Codex CLI. |
| **Claude Code** | `~/.claude.json` (via `claude mcp add -s user`) | Available in all your projects. |
| **Codex CLI** | `~/.codex/config.toml` | Same config as ChatGPT. |
| **Cursor** | `~/.cursor/mcp.json` | |
| **VS Code** (Copilot, agent mode) | `~/Library/Application Support/Code/User/mcp.json` | |
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json` | |
| **Gemini CLI** | `~/.gemini/settings.json` | |
| **OpenMausBot** | `~/.openmausbot/config.json` | Reads its MCP servers when it opens, so it's edited with the app closed; the dashboard offers to quit, connect and reopen it. |
| **DeepSeek Harness** (desktop app and `dsh` CLI) | `~/.dsh/cordis.patch.yml` | brain adds its own block (an `@deepseek-ai/dsh-mcp-client` row, stdio) and removes only that block; dsh reloads it without restarting. Tools show up as `mcp__brain__…`. |
| **Manus Studio** | its own form | Manus adds local servers with its *Run a command* form; copy the command and arguments from *Any other MCP client*; its card switches to *Detected* once Manus uses brain. Manus on the web can use [remote access](#remote-access-by-url). |
| **Anything else** | | The dashboard gives you ready-to-copy config as JSON, TOML, a command, or field by field. |

Paths are the macOS ones; on Windows they're under `%APPDATA%` and on Linux under `~/.config`. All the local agents launch the same server (`uv run --directory ~/.brain python server.py`) with absolute paths, so they work from any folder.

### Remote access by URL

For agents that run in the cloud or on another computer (Manus on the web, Claude.ai custom connectors, ChatGPT developer mode…), **Connect agent → By URL** publishes brain's MCP server through a [Cloudflare tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/). Off by default.

- brain runs `server.py --http` on `127.0.0.1:8770` and `cloudflared` publishes it; no ports are opened on your router. The first time, *Install cloudflared* downloads it from Cloudflare's GitHub release and checks the published SHA256 (or brain uses the one you installed with brew, winget or apt).
- The URL is `https://…/<token>/mcp`; without the token every request gets `404`. Apps that prefer a header can use `…/mcp` with `Authorization: Bearer <token>`. **Generate a new URL** cuts off the old one right away, and **Read-only** leaves only the tools that read and search.
- Without a Cloudflare account the URL is a `*.trycloudflare.com` address that changes each time it starts. For a fixed one, create a tunnel in your account pointing to `http://localhost:8770` and paste its hostname and token under *Fixed URL with your Cloudflare account*.
- Through the URL, `save_url` and `read_url` only fetch public addresses, never your computer or local network.
- **It stays up until you turn it off or close brain.** While it's on, brain keeps the computer from going to sleep by itself (the screen can still turn off; untick *Keep the computer from sleeping* to allow it). If the computer sleeps anyway (closing the lid), a watchdog checks the tunnel on wake: `cloudflared` reconnects with the same URL, and if it can't, or the tunnel no longer exists on Cloudflare's side, brain reopens it by itself. A quick tunnel then gets a new `*.trycloudflare.com` URL and the card tells you; a named tunnel keeps its URL. **Reconnect** does the same by hand.

### Apps with an "Add MCP server" form

Many apps have a dialog with two options, **Run a command** and **Connect to a URL**. Choose **Run a command**. If the app only takes a URL, use [remote access](#remote-access-by-url): pointing it at the dashboard's address returns `403`, because the dashboard only accepts requests from its own page.

| Field | Value |
|---|---|
| Server name | `brain` |
| Executable command | the absolute path to `uv`, e.g. `/Users/you/.local/bin/uv` (`which uv` prints it) |
| Arguments (one per line) | `run`<br>`--directory`<br>`/Users/you/.brain`<br>`python`<br>`server.py` |
| Environment | empty |

The **Connect agent** tab shows these values already filled in for your machine, each with a copy button. Once the app uses brain for the first time, it appears under **My connections** on its own.

## Connections

brain is also an MCP **client**. In the **Connections** tab you add other MCP servers, and brain re-exposes their tools to every agent you connected, prefixed with the connection's name (`github__create_issue`, `composio__GMAIL_FETCH_EMAILS`) so they never clash with brain's own tools.

- **Local command** (recommended): an MCP server that runs on your Mac, e.g. `npx -y @modelcontextprotocol/server-github` with `GITHUB_TOKEN=…`. The token stays on your machine.
- **URL**: a remote MCP server, with optional headers (`Authorization: Bearer …`).
- **Composio** (optional). **Composio stores your accounts' OAuth tokens in its own cloud**; brain keeps the key, the configuration and everything it fetches locally. Two kinds of key work:
  - **Consumer key** (`ck_…`, the usual one from [dashboard.composio.dev](https://dashboard.composio.dev)): paste it and click *Save and connect*. brain connects to `https://connect.composio.dev/mcp` with the `x-consumer-api-key` header, and the apps you already linked in Composio come with it. No user ID needed.
  - **Project key** (`ak_…`): fill in the user ID, click *Choose apps*, pick the auth configs, and brain creates the MCP server through Composio's developer API (`x-api-key`).
  - *Disconnect* removes the Composio connection and wipes the key from `.env`.

Every connection has two switches: **Active** (turn it off and its tools disappear from your agents right away) and **Save to memory**. With the second one on, each result is written to `vault/knowledge/connections/<connection>/…md` (or `knowledge/composio/<app>/…`), with the tool name, arguments and time in its frontmatter, and indexed in Chroma: what you fetched from GitHub or Gmail becomes searchable with `search_knowledge` and shows up in the graph.

Secrets (env values, headers, the Composio API key) live in `~/.brain/.env` with `600` permissions, outside the vault and never committed. The connection list lives in `~/.brain/data/connections.json`.

## Fact check

The **Fact check** view verifies claims with a process you can see, instead of a "true/false" button:

1. The local chat model splits the text into checkable claims and marks opinions, predictions and vague statements as *not verifiable*.
2. Each claim is searched in brain first. If nothing relevant is saved, it's old, your notes disagree, there's no primary source or it's a current topic, brain searches the web (if you allow it) and tells you it did.
3. It runs a neutral query, an evidence query, a **counter-evidence** query and a primary-source query; opens and reads every page (a page it can't open is marked *not fully inspected* and doesn't count); types each source (official, academic, fact-checker, news, reference, social, other) by what it is; and groups pages from the same site or with copied text into one line of evidence.
4. The model says whether each source supports, contradicts or supports with limits, and must quote the exact sentence; a quote that isn't in the page doesn't count.
5. The verdict comes from fixed rules over independent lines of evidence: never "supported" with a single secondary source, and conflicting evidence is shown as a conflict.

Preferences (level, freshness, primary sources, counter-evidence, claim types, high-risk topics with extra rigor, regions, languages, source types, search engine, blocked domains) are set once in the view. Nothing is saved to your vault unless you click **Save to brain**. It also works from the chat (`/factcheck`) and for agents (`fact_check`, which always applies your preferences). Turn on *Let the chat and all your agents check facts that aren't in brain* and every connected agent gets that instruction, and `search_knowledge` suggests `fact_check` when it finds nothing. For health, law, finance or safety it reminds you it's informational, not professional advice.

## How it works

```mermaid
flowchart LR
    subgraph Agents
        A1[Claude Desktop]
        A2[ChatGPT]
        A3[Claude Code / Cursor / …]
    end
    subgraph brain["brain (your Mac)"]
        S1[server.py<br/>one process per agent]
        V[(vault/<br/>Markdown)]
        H[(data/history.sqlite3<br/>versions)]
        C[(Chroma<br/>shared HTTP server)]
        O[Ollama<br/>nomic-embed-text]
        P[Playwright<br/>headless Chromium]
        D[Dashboard<br/>127.0.0.1:8765]
    end
    A1 & A2 & A3 -- MCP over stdio --> S1
    S1 --> V
    S1 --> H
    S1 -- embeddings --> O
    S1 -- chunks --> C
    S1 -- JS sites --> P
    S1 -- MCP client --> X[Your connections<br/>GitHub · Notion · Composio…]
    D --> V & H & C
    D -. starts/stops .-> C & O
```

**Pieces:**

- **MCP server (`server.py`).** Each agent launches its own process and talks to it over stdio (MCP's standard for local servers). It exposes the [tools](#mcp-tools) and tells the model to read `BRAIN.md`, your profile and your memory first. With remote access on, the dashboard also runs one copy over streamable HTTP (`server.py --http`, `127.0.0.1:8770`) behind a Cloudflare tunnel.
- **Vault (`~/.brain/vault/`).** Markdown files with YAML frontmatter:
  - `BRAIN.md`: a short index the agent reads first.
  - `profile.md`: your profile.
  - `memory/`: one file per category ("Work", "Preferences"…) with one fact per bullet.
  - `projects/` and `skills/`: your notes and reusable instructions.
  - `knowledge/sources/`: the full text of every saved URL.
  - Every note carries `type` (Project, SubProject, File, Memory, Skill, Source…; inside `projects/`, a project's main note is a Project, a subfolder's main note a SubProject and everything else a File, and the graph links each part to its project), `created` and `updated`, filled in by brain on every write: a small profile of the [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md), so any AI can tell what a note is and how current it is. `FORMAT.md` at the root of the vault explains every type and field to your agents. Links can be `[text](path.md)` or `[[name]]`.
- **History (`data/history.sqlite3`).** Every write stores the file's previous and new content. A cross-process file lock makes writes atomic, so Claude, ChatGPT and the dashboard can write at the same time without clobbering each other.
- **Chroma.** The vector database behind semantic search. It runs as a single HTTP server on `127.0.0.1:8055`, so every process shares it without fighting over the disk.
- **Ollama.** Computes embeddings on your machine with `nomic-embed-text`, using the prefixes the model expects (`search_document:` when indexing, `search_query:` when searching).

**What happens when you save a URL (`save_url`):**

1. [trafilatura](https://trafilatura.readthedocs.io) downloads the page and extracts clean text.
2. If it gets fewer than 30 words (typical of JavaScript-built sites) or the download fails, it renders the page in headless Chromium with Playwright and extracts again.
3. It splits the text into chunks of up to ~500 words (50-word overlap) that follow its structure: a heading stays with its first paragraph, lists, tables and code blocks aren't cut, and a chunk that starts mid-section carries the section title, which also goes into the chunk's metadata.
4. It embeds each chunk with Ollama and stores it in Chroma, with metadata pointing back to the source `.md`. The same chunks go into a keyword index (SQLite FTS5, `data/search.sqlite3`), which catches proper names, IDs and exact numbers that embeddings miss.
5. If a chat model is installed in Ollama, it adds a short `abstract` (pages over 800 words) and the `entities` it names (people, places, organizations, projects) to the frontmatter. Both are optional: without the model the page is saved the same way.
6. It writes `knowledge/sources/<slug>.md` with the full text, its chunk ids, `type: Source`, `title`, `resource` (the URL) and, when the page shows them, `author` and `published`. Saving the same URL again updates it instead of duplicating it.

**Search (`search_knowledge`)** runs the semantic search and the keyword search, and merges both lists with reciprocal rank fusion. If Chroma or Ollama is down, keyword search keeps working and the answer says so.

**Memory over time:** each fact carries the date it was saved (an HTML comment at the end of the bullet, invisible when reading). When a fact changes, `add_memory(new, supersede=old)` moves the old one to a `## Historial` section with the date it stopped being true, so agents only see what's current and the past isn't lost.

**Entities in the graph:** notes in `knowledge/` and `memory/` get an `entities` list. Two notes that name the same person or project end up connected through a shared entity node, even if nobody linked them.

**Reflect** (Profile tab) reviews what's stored and suggests fixes: facts duplicated across categories, facts that probably contradict each other, and recent notes without entities. It never writes anything; each suggestion shows the tool call that would apply it.

**How memory import works:** the dashboard's prompt asks the chatbot for its memory grouped as `## Category` / `- fact`. The parser also accepts plain lists, bold labels, numbered lists and JSON. It deduplicates, strips date prefixes, and when a memory mentions one of your projects by name, links them in the graph.

## MCP tools

| Tool | What it does |
|---|---|
| `list_vault(prefix?)` | Lists vault files with their description |
| `read_file(path)` | Reads a file |
| `write_file(path, content)` | Creates or replaces a file |
| `append_file(path, content)` | Appends to a file |
| `str_replace_file(path, old, new)` | Targeted replace (`old` must appear exactly once) |
| `set_frontmatter(path, fields)` | Changes metadata (description, tags, related…) without touching the content; `null` removes a field |
| `delete_file(path)` | Deletes a file (recoverable) |
| `file_history(path)` | A file's versions |
| `restore_file(path, version_id)` | Restores a file to an earlier version (also brings back deleted files) |
| `move_file(src, dst)` | Moves or renames a note (recoverable). Not for `BRAIN.md`, `profile.md`, `memory/` or `knowledge/sources/` |
| `vault_overview()` | What's messy in the vault: loose notes, notes with no links or no description, tag variants, similar names |
| `propose_graph_change(changes, reason?)` | Proposes adding or removing `related` links between notes. It changes nothing: you see an image of the graph with the changes marked and approve or reject it |
| `inspect_graph_region(nodes)` | Read-only: the neighbors of some notes and why they're linked |
| `add_memory(fact, category?, supersede?)` | Saves a fact about you to your memory, without duplicates and with the date it was saved. If it replaces an older fact (you moved, changed jobs…), pass the old one in `supersede`: it isn't deleted, it moves to a `## Historial` section of the same file, dated |
| `memory_history(category?)` | Facts that were superseded in a memory category |
| `list_skills()` / `get_skill(name)` | Skills: reusable instructions in `skills/` |
| `distill_skill(topic)` | Gathers everything brain has on a topic (search hits, memories, sources) so the agent can write a skill from it with `write_file`. It doesn't write the skill itself |
| `save_url(url, render_js?)` | Scrapes, indexes and saves a URL (long pages also get a short `abstract`) |
| `search_knowledge(query, top_k?)` | Hybrid search over what you saved: semantic + exact keyword (names, IDs, dates), merged with reciprocal rank fusion |
| `reindex_keyword_search()` | Rebuilds the keyword index from the `.md` files in `knowledge/` (for sources saved before hybrid search existed) |
| `list_sources()` | Every saved URL, with its `abstract`, when its content was downloaded and when it was last checked |
| `refresh_sources(path?)` | Re-downloads one saved source (or all); keeps the last good copy if it fails |
| `read_url(url, max_chars?)` | Reads a web page without saving it (e.g. an MCP server's docs) |
| `fact_check(text, search_web?)` | Verifies claims: brain first, the web if needed, a verdict by rules with sources and quotes. Saves nothing |
| `propose_connection(name, url? \| command?, args?, env?, headers?, note?)` | Proposes adding an MCP server to Connections. It doesn't add it: you approve it with one click |
| `list_connections()` | Your connections, whether they're active, and their tools |
| `refresh_connectors()` | Re-discovers the tools of every active connection |
| `<connection>__<tool>` | Any tool from an active connection, proxied (and captured to memory if enabled) |

Every write validates the note's YAML frontmatter. If an agent writes a value that breaks it (typically an unquoted `:` in a description), brain quotes it automatically; if it can't be repaired, the write is rejected with a clear error, so metadata never silently disappears from the graph.

## The `brain` command

```text
brain                 opens the dashboard and starts Ollama and Chroma
brain --port 8766     dashboard on another port
brain --no-autostart  don't start Ollama/Chroma automatically
brain --no-browser    don't open the browser
brain update          updates to the latest version (Settings → Update and restart does it from the dashboard)
brain path            shows where it's installed
brain uninstall       removes the command (keeps your data)
brain help            help
```

## Data, privacy and security

- **Everything is local.** Your data lives in `~/.brain/vault/` and `~/.brain/data/`. Both folders are in `.gitignore`, so they're never uploaded anywhere, not even if you fork the repo.
- **No external services by default.** Embeddings are computed with Ollama on your machine. brain only goes online when you save or refresh a URL, use a connection that talks to a remote service, checks GitHub for a new version (it only reads the latest release number), runs a Fact check that needs the web (the claims go as queries to the search engine you chose, and the result pages are opened; never pages on your machine or local network), or keeps the Cloudflare tunnel open if you turn on remote access. Composio, if you use it, keeps your app tokens in its cloud.
- **The dashboard only accepts requests from your own machine.** It listens on `127.0.0.1`, rejects requests with any other `Host` (DNS-rebinding protection), and its actions require a custom header browsers won't send from other pages. No website you have open can start processes or write to your vault.
- **Remote access is opt-in and locked with a token.** The URL carries a secret token (regenerate it any time), can be set to read-only, and the server behind it listens only on `127.0.0.1`. The token is in `~/.brain/data/remote.json` (`600`).
- **Agents can't leave the vault.** The tools reject paths with `..`, absolute paths, hidden files and symlinks that point outside.
- **Secrets stay out of the vault and the repo.** Connection tokens and API keys are in `~/.brain/.env`, and OAuth sign-ins in `~/.brain/data/oauth.json` (both permissions `600`, gitignored); the dashboard never shows them back, and backups leave them out unless you ask.
- **Agents can propose, not install.** An agent (or the chat's `/add-mcp`) can only *propose* a new connection; nothing runs until you click *Add* and see the exact command or URL. The same goes for graph changes: nothing changes until you approve the image.
- **Everything can be undone.** Any write can be reverted with `file_history` + `restore_file`, and Settings → Backup keeps full copies you can restore.

The website's [privacy policy](https://lautaro005.github.io/brain/privacy/) covers the site too (its chat assistant is provided by [DokBot](https://www.dokbot.app)).

To start from scratch: close the dashboard and your agents, and delete `~/.brain/vault` and `~/.brain/data`. They're recreated empty on the next start.

## Troubleshooting

| Problem | Fix |
|---|---|
| "Ollama isn't running" | Turn on the Ollama switch in the Dashboard, or open the Ollama app. |
| Search finds nothing for a name you know is saved | Sources saved before v0.02.5 aren't in the keyword index yet: click *Rebuild keyword index* in the Knowledge tab (or ask an agent to run `reindex_keyword_search`). |
| Sources have no `abstract` / the graph has no entities | Those need a chat model in Ollama: `ollama pull llama3.2`. Then run **Reflect** in the Profile tab to see which notes are missing entities. |
| "The Chroma server isn't running" | Open the dashboard (`brain`); it starts Chroma. Agents need it for `save_url` and `search_knowledge`. |
| Composio returns `401 Invalid API key` | Check the key type: a consumer key (`ck_…`) only works with *Save and connect*, not with *Choose apps* (that's for project keys `ak_…`). If it's a fresh key, try regenerating it in Composio's dashboard. |
| An app returns `403` when connecting | You used "Connect to a URL". Use **Run a command** with the values from [Apps with an "Add MCP server" form](#apps-with-an-add-mcp-server-form). |
| brain doesn't show up in Claude Desktop | Connect it from **Connect agent** and restart Claude. Check **My connections**. |
| brain doesn't show up in ChatGPT | Use **Codex** or **ChatGPT Work** mode and go to *Settings → MCP servers → Restart*. Regular chat doesn't use local servers. |
| The chat says there's no chat model | Click *Download llama3.2* in the Chat tab, or run `ollama pull llama3.2` (any chat model works; models with tool support can also edit your vault). |
| The chat answers but can't save or edit anything | Open the actions under the answer to see what failed. Very small models sometimes don't follow the tool format; try a larger one (for example `llama3.2`, `qwen2.5` or `mistral`). |
| "Couldn't extract text from that URL" | The site may be paywalled or require a login. Try *Force JS rendering*. |
| `brain: command not found` | Open a new terminal. If it persists, add `export PATH="$HOME/.local/bin:$PATH"` to your `~/.zshrc`. |
| Port 8765 is taken | `brain --port 8766` |

## Uninstalling

1. In the dashboard, **Connect agent** → disconnect your agents (or remove the `brain` entry from their config).
2. `brain uninstall` removes the command.
3. `rm -rf ~/.brain` deletes the app **and your data**.

## Development

- [`CLAUDE.md`](CLAUDE.md): technical guide for agents working on the repo (architecture, conventions and gotchas).
- [`CHANGES.md`](CHANGES.md): the log of every change and decision. New changes are appended at the end.
- [`BUILD.md`](BUILD.md): the original spec.
- [`docs/`](docs/): the website, published with GitHub Pages.

```bash
git clone https://github.com/Lautaro005/brain && cd brain
uv sync && ./brain.sh
```

The dashboard UI is available in English and Spanish; the internal docs (`CLAUDE.md`, `CHANGES.md`, `BUILD.md`) are in Spanish.

## License

[MIT with the Commons Clause](LICENSE) © 2026 Lautaro Silva.

You can use, study, modify and share brain for free, including at work. The Commons Clause adds one restriction: you may not **sell** it, meaning you can't charge third parties for a product or service (hosting, support or consulting included) whose value comes entirely or substantially from brain. It applies to every version of brain.

Both parts are in [`LICENSE`](LICENSE): the Commons Clause condition first, then the MIT text. GitHub only auto-detects standard license templates, and MIT + Commons Clause isn't one, so the sidebar shows "View license" instead of a license name. That is expected: the only way to get an "MIT" label would be to drop the condition, and plain MIT would allow selling it.

## Security

To report a vulnerability, see [`SECURITY.md`](SECURITY.md). Please don't open a public issue for it.

TDQS

A3.6/5.0

Scored across 28 tools

Disambiguation4/5

Most tools target clearly distinct resources: file editing (append/str_replace/set_frontmatter/write), sources, memory, connections, graph and skills are well separated. The only mild overlaps are among the four write/edit tools and between list_vault and vault_overview, but descriptions make the boundaries clear enough.

Naming Consistency4/5

Names follow a consistent snake_case verb_noun pattern (append_file, save_url, add_memory, propose_connection). A few are noun-based rather than verb-based (file_history, memory_history, fact_check, vault_overview), but the convention is still predictable and readable.

Tool Count3/5

28 tools is on the heavy side, though the server covers several genuinely distinct sub-domains (files, sources, memory, skills, connections, graph, fact-check). It is borderline rather than bloated, but consolidating the write/edit variants could trim it.

Completeness4/5

File lifecycle is thoroughly covered (read/write/append/replace/frontmatter/delete/move/history/restore), plus sources, memory, connections and graph. Minor gaps remain: no direct memory read/list or full-text search over plain vault notes, though read_file and search_knowledge partially cover these.

Maintenance

ActivityMaintained
ResponsivenessNo issues