SecondBrain
# SecondBrain
[](https://pypi.org/project/secondbrain-memory/)
[](https://pypi.org/project/secondbrain-memory/)
[](LICENSE)
[](https://modelcontextprotocol.io)
[](https://github.com/no-carve-only-pizza/secondbrain-oss/stargazers)
**One shared, local-first memory for every AI coding agent you use.**
Codex forgets what Claude Code learned. Cursor starts from zero on a project
Antigravity has worked on for weeks. Each tool keeps its own history in its own
private store, so you re-explain the same context over and over.
SecondBrain fixes that. Your memory is a plain Markdown vault plus a tiny
[MCP](https://modelcontextprotocol.io) server. Every MCP-capable agent reads and
writes the **same** notes, so context follows you across tools and machines.
```
Codex ─┐
Claude Code ─┤
Cursor ─┼──▶ SecondBrain MCP ──▶ ~/SecondBrain (Markdown + local index)
Antigravity ─┘ (memory_search, AI_CONTEXT/ 10_Projects/ 30_Knowledge/
your agent ─┘ memory_capture, ...) 40_Decisions/ 50_Conversations/ ...
```
- **Local-first.** Human-readable Markdown on your disk. No account required.
- **Zero heavy deps.** Core tools use only the Python standard library. Semantic
search is optional and runs locally via [Ollama](https://ollama.com).
- **Shared by protocol.** Any agent that speaks MCP joins automatically.
- **Governed.** A curated ontology plus `audit` and `eval` commands keep a
long-lived memory from rotting.
---
**Jump to:** [Why](#why-this-exists) · [Install](#5-minute-install) ·
[Tools](#what-your-agents-can-do) · [How it works](#how-it-works) ·
[Why it's worth a star](#why-it-is-worth-a-star--three-differentiators) ·
[Privacy](#privacy--safety) · [Layout](#repository-layout)
---
## Why this exists
AI coding agents are getting genuinely useful, but their memory is siloed:
- Switch from one agent to another and you lose all accumulated context.
- The same preferences, decisions, and project state get re-typed constantly.
- There is no single place *you* own and can read, edit, and back up.
SecondBrain makes memory a **file format + a protocol** instead of a feature
locked inside one app. See [docs/comparison.md](docs/comparison.md) for how this
differs from hosted memory services like Mem0 and Zep.
---
## 5-minute install
### 1. Install
```sh
pip install secondbrain-memory
```
(Optional) local semantic search:
```sh
# https://ollama.com — then:
ollama pull bge-m3
```
If you skip Ollama, set `retrieval.semantic.enabled: false` in your config and
SecondBrain runs keyword-only.
### 2. Create your vault
```sh
secondbrain init ~/SecondBrain
secondbrain index
```
This scaffolds the vault (with example notes you can delete) and writes a config
to `~/.config/secondbrain/secondbrain.yaml`.
### 3. Connect your agents
```sh
# macOS / Linux
python3 install/install_unix.py
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File install\install_windows.ps1
```
On macOS the harvester auto-schedules via a LaunchAgent; on Linux it uses a
`systemd --user` timer if `systemctl` is available. Both are optional and
controlled by `automatic_capture.enabled` in your config.
The installer registers the MCP server with each agent in your config and drops
a shared-memory rule into each agent's global instructions. Restart your AI apps.
Prefer to wire one agent by hand? Point any MCP client at:
```json
{
"mcpServers": {
"secondbrain": {
"command": "python3",
"args": ["-m", "secondbrain.mcp_server"],
"env": { "SECONDBRAIN_CONFIG": "/absolute/path/to/secondbrain.yaml" }
}
}
}
```
Or launch it with `npx secondbrain-memory` (the npm package is a thin launcher
for the Python server).
### 4. Verify
```sh
secondbrain health
secondbrain search "hybrid search" --top 3
```
---
## What your agents can do
The MCP server exposes ten tools:
| Tool | Purpose |
|---|---|
| `memory_search` | Hybrid keyword + semantic search over notes and history |
| `memory_get` | Read a note or a historical catalog entry |
| `memory_related` | Traverse 1-2 ontology hops around a note |
| `memory_capture` | Save durable user/decision/project/knowledge/inbox memory |
| `memory_update` | Append a dated section to an existing note |
| `memory_recent` | Recent per-tool session logs |
| `memory_status` | Index and harvester status |
| `memory_rebuild` | Rebuild the index |
| `memory_audit` | Flag stale/duplicate/conflicting/unresolved memory |
| `memory_eval` | Report retrieval recall@k and MRR |
The same actions are available on the CLI: `secondbrain search|index|audit|eval|
harvest|backup|health|config`.
---
## How it works
- **Vault (source of truth).** Markdown notes under a [PARA-style](https://fortelabs.com/blog/para/)
layout. Notes carry lightweight frontmatter (`type`, `status`, relations).
- **Index (derived, disposable).** SQLite FTS5 for keywords + optional local
embeddings, fused with reciprocal rank fusion. Delete it any time; rebuild with
`secondbrain index`.
- **Ontology.** A small relation vocabulary connects canonical notes; search
results get a light boost from directly linked notes.
- **Harvester.** Optionally scans your local agent histories, redacts secrets,
and builds a searchable, summary-only catalog — never full transcripts.
- **Config.** One `secondbrain.yaml` drives everything: point `vault_root`
anywhere and the whole toolchain follows.
---
## Why it is worth a star — three differentiators
1. **Cross-agent by default.** Memory lives in files + MCP, so Codex, Claude
Code, Cursor, and Antigravity share one brain. Hosted memory services center
on an SDK/backend your app calls; here, sharing is the starting point.
2. **Local-first and inspectable.** The whole memory is Markdown you can
`git diff`, grep, and edit. Embeddings run on your machine. No service to run,
no data leaving your laptop.
3. **Governed, measurable memory.** A curated ontology plus `audit` (health) and
`eval` (recall@k / MRR) treat memory quality as something you can verify — not
just an ever-growing store.
Full detail: [docs/comparison.md](docs/comparison.md).
---
## Screenshots & demo
Scripts to reproduce the README media live in
[docs/screenshots.md](docs/screenshots.md).
---
## Privacy & safety
- Ordinary personal info is stored **only if you opt in**
(`privacy.ordinary_personal_information: allowed`).
- The MCP server and harvester **refuse to store** values that look like
passwords, API keys, tokens, or private keys.
- Backups are AES-256 encrypted (`secondbrain backup`).
- The MCP server refuses to read or write outside your configured vault.
---
## Repository layout
```
secondbrain-oss/
├── secondbrain.yaml # config (points at ./vault by default)
├── src/secondbrain/ # config-driven Python package
│ ├── config.py # the one place paths are resolved
│ ├── memory_index.py # FTS5 + embeddings + ontology
│ ├── memory_search.py memory_audit.py retrieval_eval.py
│ ├── harvest.py catalog.py backup.py health_check.py
│ ├── mcp_server.py # stdio MCP server (secondbrain-mcp)
│ ├── cli.py # the `secondbrain` command
│ └── template_vault/ # packaged copy used by `secondbrain init`
├── vault/ # the reference/demo vault (same as template)
├── install/ # install_unix.py (macOS + Linux), install_windows.ps1, adapters
├── bin/secondbrain-mcp.js # npx launcher
└── docs/ # comparison, screenshot script
```
## Contributing
Issues and PRs welcome. Keep the core dependency-free, keep personal data out of
the repo, and run `secondbrain eval` before changing retrieval.
## License
[MIT](LICENSE).
---
## Maintainer self-check: no personal data leaked
Run through this before every publish or release. This repository is a template;
it must contain **zero** real personal or private information.
**Automated scan** (portable, no non-ASCII literals in the command itself)
```sh
# 1. ASCII personal tokens and absolute home paths. Expect NO matches.
grep -rInE "your-name|/Users/[a-z]|C:\\\\Users\\\\" \
--exclude-dir=.git --exclude-dir=node_modules --exclude-dir='*.egg-info' . \
|| echo "clean: no personal tokens"
# 2. Any CJK / non-Latin text (catches leaked non-English personal data).
# Reports files with runs of Hangul/Han/Hiragana/Katakana. Review each hit;
# only Unicode-range regex boundaries in *.py are expected.
python3 - <<'PY'
import os, re
pat = re.compile(r"[\uac00-\ud7a3\u3040-\u30ff\u4e00-\u9fff]{2,}")
for dp, dn, fn in os.walk("."):
dn[:] = [d for d in dn if d not in {".git", "node_modules"} and not d.endswith(".egg-info")]
for f in fn:
p = os.path.join(dp, f)
try:
for i, line in enumerate(open(p, encoding="utf-8"), 1):
if pat.search(line):
print(f"{p}:{i}: {line.strip()[:100]}")
except Exception:
pass
PY
```
Replace `your-name` with your actual name/handle when running this locally.
**Manual checklist**
- [ ] Does any file contain a **real name** (mine or anyone else's)?
- [ ] Does any file contain a **real project, client, employer, or school name**?
- [ ] Any **CVE numbers, vulnerability research, or security-target details**?
- [ ] Any **absolute home paths** (`/Users/<me>`, `C:\Users\<me>`) or machine names?
- [ ] Any real **emails, phone numbers, student/employee IDs, or birthdays**?
- [ ] Any **API keys, tokens, passwords, cookies, or private keys** (even fake-looking)?
- [ ] Are all example notes clearly **fictional** (Widget Store, Homelab, etc.)?
- [ ] Do config files point at **generic paths** (`./vault`, `~/SecondBrain`)?
- [ ] Are `vault/50_Conversations`, `00_Inbox`, `60_Imports`, `90_Archive`
empty except for templates/`.gitkeep`, and ignored by `.gitignore`?
- [ ] Do screenshots/GIFs show only the **demo vault**, no personal windows?
If any box is unchecked, do not publish until it is resolved.
TDQS
Scored across 10 tools
Each tool targets a clear, distinct operation: search, direct read, graph traversal, capture, update, recent logs, status, rebuild, audit, and evaluation. There is minimal overlap between these functions, and the descriptions make boundaries obvious.
All tools share the 'memory_' prefix and use snake_case, but the second part varies: most are verbs (search, get, capture, update, rebuild, audit, eval), while 'related', 'recent', and 'status' are not standard verb forms. This is a minor deviation from a fully uniform verb_noun pattern.
With 10 tools, the server is well-scoped for a memory/knowledge management system. Each tool serves a distinct purpose from retrieval to maintenance to quality evaluation, and the count is within the ideal range for usability.
The server covers read, search, traverse, create, update, maintenance, and evaluation. The only obvious gap is a delete/removal operation, which may be intentionally omitted for safe memory management, but it is a minor missing capability.