mybrain
by robertsfeir
README.md
# MyBrain
**A personal knowledge base with semantic search.**
Capture thoughts, ideas, notes, and decisions as you work. Ask Claude about them later in plain English -- MyBrain finds matches by meaning, not just keywords. Everything is stored in your own PostgreSQL database with pgvector embeddings.
Works with **Claude Desktop** (including CoWork mode) and the **Claude Code CLI** over MCP.
> β‘ **Easiest install**: download [`mybrain.mcpb`](https://github.com/robertsfeir/mybrain/releases/latest) and drag it into Claude Desktop. See [Install in Claude Desktop](#install-in-claude-desktop-mcpb-recommended) below. For Claude Code CLI, see [Install via Claude Code CLI](#install-via-claude-code-cli).
> π **New here?** Start with the **[User Guide](guides/user-guide.md)** β a friendly tour of how MyBrain captures, scores, fades, and removes memories. Want the deep specs (schema, scoring math, conflict thresholds, the full tool surface)? See the **[Technical Reference](guides/technical-reference.md)**.
---
## Tool Rename (v2.0)
mybrain v2.0 implements the 8-tool atelier-brain protocol. The four legacy
tools (`capture_thought`, `search_thoughts`, `browse_thoughts`, `brain_stats`)
have been **replaced** by the protocol tool surface. v1 tool names no longer
exist on the server.
| Tool | What it does |
|---|---|
| `agent_capture` | Store a thought with schema-enforced metadata; dedup + conflict detection + supersedes |
| `agent_search` | Semantic search with three-axis scoring (recency + importance + relevance) |
| `atelier_browse` | Paginated thought listing with status / type / agent / scope filters |
| `atelier_stats` | Brain health check, counts by type / status / agent / human |
| `atelier_relation` | Link two thoughts via a typed relation (`supersedes`, `supports`, `contradicts`, β¦) |
| `atelier_trace` | Traverse the relation graph from a thought (backward / forward / both) |
| `atelier_hydrate` | Ingest JSONL telemetry from a Claude Code project sessions directory |
| `atelier_hydrate_status` | Poll completion state of a previous `atelier_hydrate` call |
### Migration steps
1. **Update tool names in your Claude Code / Cursor configs.** Any custom
prompts or scripts that referenced `capture_thought` / `search_thoughts` /
`browse_thoughts` / `brain_stats` need to be updated to the new tool names
above. Old names will return "tool not found".
2. **Apply the v1-to-merged migration to existing databases.** v2 introduces
new columns (`captured_by`, `origin_pipeline`, `origin_context`,
`trigger_when`), new enum values (`handoff`, `pattern`, `seed`, plus
atelier-pipeline source agents and phases), and the `thought_relations`
table. The migration is purely additive and idempotent β re-running it on
an already-migrated database is a no-op.
```bash
psql $DATABASE_URL -f migrations/001-mybrain-v1-to-merged.sql
```
Fresh installs do not need to run this manually β `lib/db.mjs`'s
`runMigrations(pool)` applies it automatically at server startup.
---
## What You Get
Eight MCP tools Claude can call on your behalf (the 8-tool atelier-brain protocol β see [Tool Rename (v2.0)](#tool-rename-v20) above for the v1 β v2 mapping):
| Tool | What it does |
|---|---|
| `agent_capture` | Save a thought with schema-enforced metadata; runs dedup + conflict detection on `decision`/`preference` types. Optional `relations[]` parameter creates inline edges to existing thoughts in the same transaction β collapses the common "capture + relate" pattern to one MCP call |
| `agent_search` | Semantic search with three-axis scoring (relevance + importance + recency); refreshes recency on hits |
| `atelier_browse` | Paginated listing filtered by status, type, agent, scope, or human |
| `atelier_stats` | Brain health + counts by type / status / agent / human |
| `atelier_relation` | Link two thoughts via a typed relation (`supersedes`, `supports`, `contradicts`, `evolves_from`, `triggered_by`, `synthesized_from`) |
| `atelier_trace` | Walk the relation graph from a thought (backward / forward / both) |
| `atelier_hydrate` | Ingest JSONL telemetry from a Claude Code project sessions directory |
| `atelier_hydrate_status` | Poll the completion state of a previous `atelier_hydrate` call |
**Per-call cost:** SQL-only tools (`atelier_browse`, `atelier_stats`, `atelier_relation`, `atelier_trace`, `atelier_hydrate_status`) are free. `agent_capture` and `agent_search` each make one embedding call (free with local Ollama; ~$0.0001 with OpenRouter `text-embedding-3-small`). `agent_capture` may also make one chat call when a `decision`/`preference` lands in the conflict-candidate zone (0.7β0.9 similarity) and `conflict_llm_enabled` is true. `atelier_hydrate` cost scales with the number of telemetry files ingested.
Deeper docs:
- **[User Guide](guides/user-guide.md)** β friendly walkthrough of how MyBrain captures, scores, fades, and removes memories
- **[Technical Reference](guides/technical-reference.md)** β schema, scoring math, conflict thresholds, consolidation algorithm, REST API, full tool reference
Two skills that ship with the plugin:
- **`/mybrain-setup`** -- interactive setup wizard (Bundled, Docker, Native, or RDS)
- **`/mybrain-overview`** -- explains architecture, tools, and usage
---
## Install in Claude Desktop (.mcpb, recommended)
This is the easiest path for Claude Desktop and CoWork users. The MCP server runs locally as a stdio process; sensitive credentials (DB URL, API key) are stored in your macOS Keychain (or the Windows Credential Manager).
### 1. Download the .mcpb bundle
Grab `mybrain.mcpb` from the [latest GitHub Release](https://github.com/robertsfeir/mybrain/releases/latest). It's a single self-contained zip β manifest + server code + bundled `node_modules` β about 5 MB.
You will need **Node.js 18+** installed on your machine for the bundled server to run (`brew install node` on macOS).
### 2. Install into Claude Desktop
Either:
- **Drag** `mybrain.mcpb` from Finder into the Claude Desktop window, or
- **Settings β Extensions β Advanced settings β Extension Developer β Install Extensionβ¦** and pick the file.
An install dialog appears asking for two values:
- **PostgreSQL connection URL** β `postgres://user:pass@host:5432/dbname` (the database must have `pgvector` and `ltree` extensions)
- **OpenRouter API key** *(optional)* β leave blank if you've configured a different provider in `brain-config.json`
Click Install. Both values land in your OS keychain.
### 3. Verify
Open **Customize β Connectors β Desktop** β `mybrain` should appear, with the 8 brain tools listed. In a chat, ask "How many thoughts do I have?" β Claude calls `atelier_stats` and answers.
> Don't have a database yet? See [Deployment Modes](#deployment-modes) below for four ways to stand one up (Bundled, Docker, Native, RDS). Or use the CLI install path's `/mybrain-setup` wizard, which scaffolds a fresh database for you, then come back here to install the `.mcpb`.
---
## Install via Claude Code CLI
Use this path if you primarily work in the Claude Code CLI rather than Claude Desktop. The plugin marketplace installs the skills (including `/mybrain-setup`, which scaffolds a database for you) and registers the MCP server via `claude mcp add`.
### 1. Add the marketplace and install the plugin
```bash
claude plugin marketplace add robertsfeir/mybrain
claude plugin install mybrain@mybrain
```
### 2. Run the setup wizard
Inside any Claude Code session, run:
```
/mybrain-setup
```
The wizard installs MyBrain **per-project** (local MCP scope) -- the brain is registered for this user, in this project, and nowhere else. `--scope user` and `--scope project` registrations are deprecated and explicitly removed by the new flow's pre-flight step (see [Per-project install (v2.2.0+)](#per-project-install-v220) below).
Claude will then ask **where this repo's brain database should live**. Four backends are available:
- **Bundled** -- *(recommended)* PostgreSQL, Ollama, and the MCP server all run inside a single container. No API key. One port. One volume.
- **Docker** -- multi-container: PostgreSQL + (optional Ollama via compose profile) + MCP server. Choose OpenRouter (cloud) or Ollama (local) for embeddings.
- **Native** -- no Docker. Ollama on the host, any reachable PostgreSQL, MCP server as a local process.
- **RDS** -- connect to a shared PostgreSQL on AWS RDS or any reachable remote Postgres. OpenRouter for embeddings. `BRAIN_SCOPE` (ltree) keeps each repo's thoughts isolated when several repos share the same DB.
The wizard handles the rest: scaffolding files, registering the MCP server with `claude mcp add` (local scope), starting containers (Bundled/Docker), and verifying everything works.
#### Per-project install (v2.2.1+)
As of v2.2.1, the plugin no longer auto-registers an MCP server. The plugin is a delivery vehicle for skills, templates, and server source -- every working brain registration is an explicit `claude mcp add` driven by `/mybrain-setup`, with **local scope only**.
Three deprecated registration paths were eliminated across v2.2.0 and v2.2.1:
- `--scope user` (deprecated in v2.2.0) -- made one `mybrain` registration visible across every project on the machine. Caused the brain to fail to start when two repos raced for the same container/port; caused thoughts to be attributed to the wrong project because the shared registration carried one repo's `BRAIN_SCOPE`.
- `--scope project` (deprecated in v2.2.0) -- wrote the registration to `.mcp.json` and shipped it to teammates / other clones via git, leaking machine-local URLs and ports.
- **Plugin auto-registration via shipped `.mcp.json`** (deprecated in v2.2.1) -- the plugin shipped a `.mcp.json` at its root that Claude Code's plugin loader auto-registered as `plugin:mybrain:mybrain` with a hard-coded `BRAIN_SCOPE: "personal"`. Same cross-project leak as `--scope user`, but harder to spot because it didn't show up under any user-visible scope flag. **This was the primary cause of "thoughts in the wrong project" symptoms.** v2.2.1 deletes the file from the plugin source.
`/mybrain-setup` now begins with a **Step 0 pre-flight** that runs `claude mcp list` and offers to remove any of the three deprecated registrations before continuing. If you decline, the install stops -- it won't create a colliding local-scope entry alongside an existing one. Removing a deprecated registration affects every other project on the machine that was relying on it; each will need to re-run `/mybrain-setup` once. **Brain data (databases, containers, volumes) is untouched** -- only the Claude Code registration is removed.
If you installed v2.2.0 or earlier, your plugin cache likely still contains the `.mcp.json` and is auto-registering `plugin:mybrain:mybrain` regardless of any other steps you take. Upgrade the plugin (`claude plugin update mybrain@mybrain`) or uninstall + reinstall, then restart Claude Code, before running `/mybrain-setup`. The Step 0 pre-flight will detect `plugin:mybrain:mybrain` and walk you through this.
Multiple repos can still share one *database* by selecting **RDS** (or pointing several Native installs at the same Postgres) -- `BRAIN_SCOPE` (set per-repo in the `claude mcp add -e` invocation) keeps thoughts isolated.
### 3. (Optional) Get an OpenRouter API key
**You only need a key in Docker/RDS modes that use OpenRouter.** Bundled and Native modes use local Ollama and don't need one.
1. Sign up at <https://openrouter.ai>
2. Create a key at <https://openrouter.ai/keys>
3. Load a few dollars of credits. The default model (`openai/text-embedding-3-small`, 1536-dim) costs fractions of a cent per call -- $5 of credits goes a long way.
### 4. Restart Claude Code and try it
```
Remember this: I just set up MyBrain.
How many thoughts do I have?
```
If Claude responds with a thought count, you're done.
---
## Install Manually (Clone and Register)
Use this path if you don't want to go through the marketplace, or you need to customize the server.
```bash
git clone https://github.com/robertsfeir/mybrain.git
cd mybrain
npm install
```
Apply the schema (`{{EMBED_DIM}}` is substituted at scaffold time, default `1536`):
```bash
sed 's/{{EMBED_DIM}}/1536/g' templates/schema.sql | psql "$DATABASE_URL" -f -
```
Then register the MCP server with Claude Code (Native or RDS-style stdio registration). **Use the default local scope** -- do not pass `--scope user` or `--scope project`:
```bash
claude mcp add mybrain --transport stdio \
-e DATABASE_URL="postgresql://user:password@host:5432/mybrain?ssl=true&sslmode=no-verify" \
-e EMBEDDING_PROVIDER="ollama" \
-e OLLAMA_HOST="http://localhost:11434" \
-e OLLAMA_MODEL="gte-qwen2-1.5b-instruct" \
-e BRAIN_SCOPE="personal" \
-- node /absolute/path/to/mybrain/server.mjs
```
Swap `EMBEDDING_PROVIDER=openrouter` and `OPENROUTER_API_KEY=sk-or-...` if you'd rather use the cloud embedding model.
---
## Deployment Modes
### Bundled mode (recommended)
```
Claude Code --HTTP--> mybrain container (:8787)
ββ PostgreSQL + pgvector
ββ Ollama (gte-qwen2-1.5b-instruct, 1536-dim)
ββ MCP server
```
- Everything runs in one container -- no API key, no external services
- Exposes only the MCP HTTP port; data + models persisted in named Docker volumes
- First boot pulls the embedding model (~1.7 GB); subsequent starts are <10s
- Best for personal use on a single machine
### Docker mode
```
Claude Code --HTTP--> mcp container (:8787) ββ> postgres container
ββ> OpenRouter OR ollama container (compose profile)
```
- PostgreSQL + MCP server in separate containers
- Embeddings via **OpenRouter** (default) or **local Ollama** via the `ollama` compose profile
- Each brain instance uses two ports (default: MCP 8787, Postgres 5433); you can run multiple named brains on different ports
### Native mode
```
Claude Code --stdio (or HTTP)--> server.mjs ββ> your local/remote Postgres
ββ> host-installed Ollama (:11434)
```
- No Docker. Ollama runs directly on the host (`brew install ollama` or the official installer)
- Postgres is whatever PG you already have, with `pgvector` and `ltree` extensions enabled
- MCP server runs as a local Node process registered via `claude mcp add` (stdio default, HTTP optional)
- Good if you already run Ollama and Postgres for other reasons
### RDS mode
```
Claude Code --stdio--> server.mjs --> AWS RDS (your database)
--> OpenRouter (embeddings)
```
- Connects to an existing remote Postgres with `pgvector` and `ltree` extensions
- `BRAIN_SCOPE` is required -- isolates your thoughts from others sharing the database
- Good for teams or syncing a brain across multiple machines
---
## How Semantic Search Works
When you capture a thought, the text is sent to your configured embedding provider -- **local Ollama** (default `gte-qwen2-1.5b-instruct`) or **OpenRouter** (`openai/text-embedding-3-small`) -- and returned as a 1536-dimensional vector. That vector is stored next to your text in PostgreSQL with an HNSW index.
When you search, your query is embedded the same way and scored with the **three-axis formula**:
```
score = (3.0 Γ cosine_similarity) + (2.0 Γ importance) + (0.5 Γ recency_decay)
```
Results come back sorted by combined score, so recent *and* important *and* relevant thoughts rise to the top.
The schema's vector column dimension is template-substituted at scaffold time (default `1536`). A 1024-dim opt-in is supported for local models like `mxbai-embed-large` -- substitute `{{EMBED_DIM}}=1024` in `schema.sql` and set `OLLAMA_MODEL=mxbai-embed-large` together. On startup the MCP server reads and logs the actual column dimension (e.g. `embedding dim: 1536 (detected)`), so dimension drift surfaces immediately.
### ltree scoping
Every thought carries an `ltree[]` scope (e.g. `personal`, `work.acme.app`). When `BRAIN_SCOPE` is set, every query is filtered to that scope -- multiple users or projects can share one database without leaking thoughts to each other.
---
## Async Memory Storage
Set `MYBRAIN_ASYNC_STORAGE=true` to make `agent_capture` return in ~3ms. The thought is inserted with `embedding=NULL`; a background worker in the same Node process polls NULL-embedding rows every 500ms and backfills them. The `thoughts` table itself is the queue, so nothing is lost on crash.
Trade-off: a thought is not retrievable via `agent_search` until the embedding lands (typically <1s). To eliminate the capture-then-search race, `agent_search` runs `flushEmbedQueue` in parallel with its own query embedding so a thought captured ~500ms before the search becomes findable on the same call. Recommended whenever the embedding call is the slow path -- i.e. local Ollama (Bundled / Native / Docker+Ollama).
In stdio mode (Native / RDS) the worker only runs while Claude Code is open; thoughts captured right before you close Claude embed on next launch.
---
## Shell Wrappers (auto-start the brain when you launch Claude)
The `shell/` directory ships preflight wrappers for `zsh`, `bash`, `fish`, `csh`, and `tcsh`. Once sourced, running `claude` health-checks the bundled container at `http://localhost:<port>/health`, starts/restarts it via `docker compose up -d` if it's not healthy, polls until ready (default 120s timeout), and then launches Claude Code. If the container is already healthy, overhead is sub-100ms.
The setup wizard offers to install these for you. Manual one-liner for zsh once `~/.claude/mybrain/shell/mybrain.zsh` exists:
```sh
# add to ~/.zshrc
[ -f ~/.claude/mybrain/shell/mybrain.zsh ] && source ~/.claude/mybrain/shell/mybrain.zsh
```
Tunables (set before the `source` line):
```sh
export MYBRAIN_HEALTH_TIMEOUT=60 # seconds to wait (default: 120)
export MYBRAIN_QUIET=1 # suppress mybrain output (default: 0)
```
The wrapper never blocks Claude Code -- if Docker isn't running, it logs a warning and starts Claude anyway.
---
## Requirements
**Bundled mode:**
- Docker Desktop
**Docker mode:**
- Docker
- OpenRouter API key (only if using the cloud provider)
- Node.js 18+ (only if you install manually)
**Native mode:**
- Node.js 18+
- PostgreSQL with `pgvector` and `ltree` extensions
- Ollama installed and running on the host
**RDS mode:**
- Node.js 18+
- PostgreSQL with `pgvector` and `ltree` extensions (remote)
- OpenRouter API key
---
## Usage Examples
Once installed, talk to Claude naturally:
- `Remember this: Sarah said she wants to start a consulting business next quarter.`
- `What do I know about Sarah?`
- `Show me my recent thoughts.`
- `Search my brain for anything about deployment pipelines.`
- `How many thoughts do I have?`
- `Capture thought: pg_dump with --data-only skips schema changes.`
- `Trace what led to my decision about authentication.`
- `Show me my preferences.`
Claude will pick the right tool (`agent_capture`, `agent_search`, `atelier_browse`, `atelier_stats`, `atelier_relation`, `atelier_trace`) automatically.
---
## Repository Layout
```
.claude-plugin/
plugin.json Plugin manifest (declares skills)
marketplace.json Marketplace definition
.mcp.json MCP server config (stdio, plugin-root path)
skills/
mybrain-setup/SKILL.md Interactive setup wizard (4 modes)
mybrain-overview/SKILL.md Architecture + tool reference
shell/
mybrain-preflight.sh Health-check + container start
mybrain.zsh zsh wrapper
mybrain.bash bash wrapper
mybrain.fish fish wrapper
mybrain.csh csh wrapper
mybrain.tcsh tcsh wrapper
templates/
server.mjs MCP server (stdio + HTTP, /health endpoint)
package.json Node dependencies
schema.sql Full schema (ltree, match_thoughts_scored, HNSW, {{EMBED_DIM}} placeholder)
Dockerfile MCP container image (Docker mode)
Dockerfile.bundled Single-container image (PG + Ollama + MCP)
start.sh Bundled-mode entrypoint (init PG, start Ollama, pull model, run MCP)
compose.yml Multi-container compose (Docker mode)
compose.bundled.yml Single-container compose (Bundled mode)
.env.example Environment template (Docker / Native / RDS)
.env.bundled.example Environment template (Bundled)
server.mjs Top-level server (used by stdio registration)
```
---
## Troubleshooting
**Bundled mode -- first boot is slow / container shows `unhealthy`.**
First boot pulls the embedding model (~1.7 GB) into the volume. On a slow connection this can exceed the healthcheck `start_period` (300s). Wait it out -- Docker's restart policy keeps the container coming back, and once the model is cached subsequent starts are <10s. Watch progress: `docker compose logs -f mybrain`.
**Bundled mode -- `/health` returns nothing.**
Check the container is up: `docker compose ps` inside `.mybrain/<name>/`. If the container is restarting in a loop, inspect logs for the failing service (Postgres init, Ollama pull, or the MCP server itself).
**"No thoughts found" on every search.**
The schema may not be loaded. In Bundled/Docker modes, run `docker compose down -v && docker compose up -d` in your `.mybrain/<name>/` directory to rebuild the volume with the schema. In Native/RDS modes, re-apply: `sed 's/{{EMBED_DIM}}/1536/g' templates/schema.sql | psql "$DATABASE_URL" -f -`.
**`Embedding API error: 401`.**
Your `OPENROUTER_API_KEY` is missing or invalid (Docker/RDS with OpenRouter only). Check it's set in `.env` or the `claude mcp add` command.
**Claude doesn't see the tools.**
Restart Claude Code after installing. In Bundled/Docker modes, check the container is running and healthy: `docker compose ps`.
**`agent_capture` succeeds but `agent_search` returns nothing.**
If async storage is enabled, the embedding may not have been written yet -- `agent_search` flushes the queue in parallel with its own query embedding, so a one-shot retry usually picks it up. Otherwise lower the similarity threshold: `Search my brain for X with threshold 0.1`. The default (0.2) is conservative.
**Embedding dim mismatch on insert.**
The MCP server logs `embedding dim: N (detected)` on startup. If your model produces a different dim than the column expects, pgvector raises a clear error. Either pull a model that matches the column dim, or rebuild the schema with the matching `{{EMBED_DIM}}`.
**Port conflicts in Bundled/Docker mode.**
Each brain instance uses one port (Bundled: MCP 8787) or two ports (Docker: MCP 8787, Postgres 5433). Run `/mybrain-setup` again with a different brain name to pick new ports.
---
## License
Apache License 2.0 β see [LICENSE](LICENSE) for the full text.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues