brain-keeper
Provides tools for managing an Obsidian vault as a hierarchical knowledge base, including adding, searching, maintaining, evaluating, and exporting notes, and routing relevant notes into coding agent prompts.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@brain-keepersave our MCP routing decisions from this session to my brain vault"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
brain-traverse
Dynamic context routing for coding agents. Your knowledge lives in a hierarchical Obsidian vault, "the brain". On every prompt, a fast System-1 decision model walks that tree and injects only the note that applies, not one enormous system prompt.
Two hops, typically well under a second, and the agent sees the one guide it needs.
┌─────────────────────────────────────────┐
prompt ───────>│ router (Pi extension / Claude Code hook)│
│ gate + hop 1 ──> hop 2 ──> leaf .md │──> injected as context
└──────┬───────────────────────┬──────────┘
│ POST /v1/systemone │ reads _index.json
v v
┌──────────────────────────┐ ┌──────────────────┐
│ decisions API │ │ Obsidian vault │
│ TypeSafe Jev (default) │ │ (the brain) │
│ or self-hosted Laya │ └────────┬─────────┘
└──────────────────────────┘ ^ writes
┌────────┴─────────┐
agent ──tools / MCP─────────>│ brain-keeper │
└──────────────────┘Router: a Claude Code plugin hook and a Pi extension. It routes each prompt through the vault and adds the matching note to the conversation. Supports parallel composite routing for cross-cutting queries under a unified context budget.
Keeper: 17
brain_*tools for adding to, searching, maintaining, evaluating and exporting the brain, plus commands to capture and research knowledge into it. They are native tools in Pi, and an MCP server for Claude Code, Codex and any other MCP client.Decision model: picks the note at each step. Either the hosted TypeSafe Jev API, which needs only an API key, or Laya, an open model you run on your own machine. See Choose a decision model.
Starter brains: ready-made notes you can add in one command, and a way to share your own brain through GitHub. See Starter and shared brains.
Choose a decision model
At each folder of the brain, a decision model reads the prompt and the
criteria of the notes and subfolders there, and picks one. You can use either
of two models. They answer the same API, so you can switch later by changing
one setting.
TypeSafe Jev (hosted, the default) | Laya (local, self-hosted) | |
What it is | TypeSafe's hosted decisions API | The open Laya model on your own hardware, served by host-laya |
What you need | An API key from console.typesafe.ai/keys | A Linux machine with Docker. The packaged image targets an Intel Arc GPU (about 1.7 GB of VRAM) |
Cost | Your own hardware | |
What leaves your machine | Each prompt, cut to 1,500 characters ( | Nothing, when the host is on your own network |
Speed | A network round trip per step, capped at 2 s per request and 3 s per prompt | About 35 ms per step on a local network, capped at 0.5 s and 1 s |
To set up | Add the key. Nothing to run | Run host-laya, then point |
If the model is slow or unreachable, the prompt goes ahead without a note: routing pauses and retries later, and it never blocks your agent.
Use TypeSafe Jev
Get a key at console.typesafe.ai/keys and give it to duker-brain in one of these ways:
Claude Code: the plugin's Decisions API key setting. Claude Code asks for it when you enable the plugin and keeps it in your system's credential store.
Anywhere: the
TYPESAFE_API_KEYenvironment variable.
Leave the decisions URL empty: Jev is the default.
Use a local Laya model
Start the decisions service on a machine you control. host-laya is the reference deployment: a Docker image for Ubuntu with an Intel Arc GPU, which you start with
docker compose up -d. Laya itself also runs on NVIDIA GPUs (CUDA) and on the CPU (LAYA_DEVICE=cudaorcpu), but only the Intel Arc image is packaged today, so on other hardware you adapt its Dockerfile. On a CPU, expect about 200 ms per decision.Point duker-brain at it. In Claude Code, set the plugin's Decisions API URL to the service, for example
http://my-server:8081. Anywhere else, put"decisionsUrl": "http://my-server:8081"in~/.config/brain-traverse/config.json, or setBRAIN_DECISIONS_URL.No API key is needed, unless you started host-laya with
LAYA_API_KEY. Do that whenever the service is reachable from other machines, and give duker-brain the same value as its API key (the plugin setting, orBRAIN_DECISIONS_API_KEY).
To see which model is in use and whether it answers, run /duker-brain:status
in Claude Code, /brain status in Pi, or brain-traverse health.
Related MCP server: obsidian-mcp
Install
You need Node.js 22 or newer on your PATH, and a decision model:
a TypeSafe API key, or a local Laya service.
Claude Code (plugin)
Inside Claude Code:
/plugin marketplace add DukeR-git/duker-brain
/plugin install duker-brain@duker-brainWhen you enable the plugin, it asks for three optional settings: the vault
folder, the decisions API key and the decisions API URL. For TypeSafe Jev, fill
in the key; for a local Laya, fill in the URL (see
Choose a decision model). Leave them empty to use
TYPESAFE_API_KEY and the config file instead. Then create a brain, here
starting from the Python backend starter, and check that routing works:
/duker-brain:init ~/brain --starter python-backend
/duker-brain:statusFrom then on every prompt is routed, and the matching note is added as context.
When a note goes in, Claude Code shows one line such as
brain: asyncpg_pooling 0.93 53ms; set displayInjection to false to hide
it. You also get the 17 brain_* tools and these commands:
Command | What it does |
| Create a brain, or adopt an existing Obsidian vault, and make it the default |
| Settings, service health and what the last prompt routed to |
| Add a starter brain or someone's shared brain as its own folder |
| Pull new and changed notes into the brains you added, keeping your edits |
| File what is worth keeping from this session into the brain |
| Research a topic and write it up as a note |
The plugin runs prebuilt bundles from dist, so nothing is installed
besides the plugin itself. Its state (which notes each conversation already
holds) lives in Claude Code's plugin data folder. After /compact or /clear,
the next prompt gets the full note again.
Pi
pi install git:github.com/DukeR-git/duker-brain
export TYPESAFE_API_KEY=sk-... # for TypeSafe Jev; for a local Laya, set decisionsUrl insteadThat installs the router, the 17 brain tools, and the /brain,
/brain-init, /brain-add, /brain-update, /brain-capture, /brain-research
and /brain-export commands. Then create a brain from inside Pi and reload:
/brain-init ~/brain --starter python-backend
/brain reload--starter adds a starter brain so routing has
something to do straight away; --example adds a small sample tree instead.
Leave both out to start with just the catch-all note. /brain status shows whether routing is live, and /brain help
lists all in-session subcommands.
Pointing /brain-init at an existing Obsidian vault is safe: it never
overwrites a note (it does regenerate _index.json files, which are build
output). Add --dry-run to see what it would do first, and list folders that
are not knowledge (Templates, Attachments, Daily Notes) in the vault's
.brainignore. Run brain_doctor (or brain-keeper doctor) afterwards to see
what the notes still need.
Codex and other MCP clients
These harnesses get the keeper: the tools and the two commands. Automatic routing on every prompt is available for Claude Code (above) and Pi.
git clone https://github.com/DukeR-git/duker-brain
cd duker-brain
npm install
node brain-keeper/bin/brain-keeper.mjs init ~/brain --starter python-backend
node brain-keeper/bin/brain-keeper.mjs setupsetup prints the exact commands for this checkout, for example:
codex mcp add brain -- node /path/to/duker-brain/brain-keeper/bin/brain-keeper.mjs serveTo give Claude Code only the tools, without routing, use the same command
with claude mcp add brain --scope user.
It also says where to copy the two command files. See brain-keeper/commands.
Already using Pi? The package is cloned at
~/.pi/agent/git/github.com/DukeR-git/duker-brain, so you can point the MCP
commands there instead of cloning again.
Starter and shared brains
You do not have to start from an empty brain. A starter brain is a ready-made set of notes, with routing criteria and evals, that goes into your brain as one folder:
brain-keeper starters # what is available
brain-keeper add python-backend # add one to the brain you have
brain-keeper init ~/brain --starter python-backend # or start a new brain with itStarter | What it covers |
FastAPI, asyncio, SQLAlchemy 2.0 and PostgreSQL, Alembic, pytest, uv |
Anyone's brain on GitHub works the same way, so a team can keep its knowledge in one repository and everyone adds it:
brain-keeper add your-org/team-brain # a whole repository
brain-keeper add your-org/monorepo/brains/go # one folder in it
brain-keeper add your-org/team-brain#v2 # at a tag or branchbrain-keeper update later pulls in new and changed notes. A note you edited
is kept, and the update tells you it also changed upstream. Only Markdown notes
and evals.json are copied, never scripts, but the notes do reach your coding
agent as context, so only add brains from sources you trust.
In Claude Code these are /duker-brain:add and /duker-brain:update, and in
Pi /brain-add and /brain-update. To publish your own brain, and for the
details of how updates work, see brains/README.md.
Configuration
One config serves the router, the keeper and the CLIs. Settings are read in this order, and later sources win:
~/.config/brain-traverse/config.json: per user.initwritesvaultRoothere../brain-traverse.config.json, or the file named by$BRAIN_CONFIG: per project.BRAIN_*environment variables.
The settings you are most likely to touch:
Key | Env | Default | |
|
| none | The brain. |
|
| none | Required for Jev, and for a Laya host started with |
|
|
| Or a self-hosted Laya, e.g. |
|
|
| Pin a version such as |
|
|
| Below this, fall back to the catch-all note. |
|
|
|
|
Every value is validated: a typo'd key or a value of the wrong type is ignored
with a warning instead of silently misbehaving. brain-traverse config (or
/brain config in Pi) prints the resolved settings, where each came from, and
anything that was ignored. config.example.json lists every
key; the full reference is in pi-traverser.
The router and the keeper read the same settings, so brain_check_routing
predicts exactly what the router will do.
Timeouts
Jev and Laya answer the same request on POST /v1/systemone, so only
decisionsUrl (and the key) differ between them; see
Choose a decision model. A decisions URL on the
local network (localhost, 192.168.x.x, 10.x, a bare host name, *.local)
gets tight defaults: 500 ms per request and 1 s per route. A remote URL gets
2 s and 3 s. Set timeoutMs and routeBudgetMs to override them.
host-laya is not installed by pi install or the Claude Code
plugin; it runs on the machine that has the GPU.
Writing the brain
Note frontmatter is the source of truth, and every _index.json is a build
artifact. A note describes itself; a folder describes itself in _about.md:
---
id: asyncpg_pooling
title: asyncpg Connection Pooling
criteria: PostgreSQL connections, asyncpg pool sizing and lifespan setup, acquiring and releasing connections, PgBouncer transaction mode, statement cache errors
---criteriais what the decision model actually reads. Write 10–25 words that tell a note apart from its siblings; it is not a summary of the note.Keep each folder to 15 children or fewer. Past that, each option gets too few tokens to describe itself.
One root note carries
fallback: true, the catch-all used when routing is unsure. A folder may have its own catch-all too: when routing reachesBackend/confidently and then hesitates, Backend's catch-all is used rather than the root's.
The keeper tools recompile the manifests after every write. If you edit in
Obsidian by hand, run brain_rebuild (or brain-keeper rebuild), or leave
brain-keeper watch running. Writes are atomic, and removed notes go to the
vault's .trash/ rather than being deleted, but keeping the vault in git is
still the best undo.
Repository layout
Folder | What it is |
The router: the Pi extension, the Claude Code hook, and the | |
The Claude Code plugin and marketplace manifests, and the plugin's own commands. | |
The starter brains, and how to share your own. | |
Self-contained bundles of the CLIs and the hook, built by | |
The authoring tools: Pi tools, the MCP server, the | |
Shared by both: vault schema, frontmatter parser, compiler, traversal engine and decisions client. | |
Optional self-hosted decisions service (Python and Docker, hardware-specific). | |
The original architecture plan (each package README notes where the build deviates from it) and the roadmap. |
The router reads _index.json manifests and the keeper writes them. Both
import the same schema, the same 15-child rule and the same frontmatter parser
from brain-core, so a manifest the keeper emits is one the router accepts. A
test asserts that recompiling the fixture vault produces no diff.
brain-core is imported by relative path, with no build step. The three
TypeScript folders must therefore stay side by side. The npm workspace at the
root only exists so that dependencies install in one place.
Command-line tools
After npm install in a checkout, run them with node. After npm link,
they are also on your PATH.
node pi-traverser/bin/brain-traverse.mjs route "How do I size an asyncpg pool?" -v
node pi-traverser/bin/brain-traverse.mjs eval # run routing regression evals
node pi-traverser/bin/brain-traverse.mjs health # which backend, and is the key accepted?
node pi-traverser/bin/brain-traverse.mjs stats # what gets injected, what never does, near ties, cache hits
node brain-keeper/bin/brain-keeper.mjs doctor # vault health
node brain-keeper/bin/brain-keeper.mjs add python-backend # add a starter or shared brain
node brain-keeper/bin/brain-keeper.mjs update # update the brains you added
node brain-keeper/bin/brain-keeper.mjs export --format cursor # export rules to .cursor/rules/
node brain-keeper/bin/brain-keeper.mjs search "pgbouncer"
node brain-keeper/bin/brain-keeper.mjs tree --criteriaDevelopment
npm install
npm test # all three packages
npm run typecheck
npm run build # rebuild the self-contained dist/ bundles (commit the result)brain-core 171 vault model, compiler, config, traversal, cache, evals, exporter
pi-traverser 71 the Pi extension, the Claude Code hook, injection formatting, config, CLI
brain-keeper 109 operations, the 17-tool surface, shared brains, Pi registration, MCP server
host-laya 22 the HTTP layer against a stub engine (pytest; no torch needed)None of the tests need a GPU, a network or an API key. A mock decisions server
imitates both backends: host-laya's /healthz, and Jev's bearer-key checks.
host-laya's own scripts (smoke_test.py, bench.py, parity_check.py) need
the real service, and so does the opt-in live test:
BRAIN_LIVE_URL=https://api.typesafe.ai TYPESAFE_API_KEY=sk-... npm test.
cd host-laya && pip install -r requirements-test.txt && pytestCI (.github/workflows/ci.yml) runs the Node suites
on Linux and Windows, builds the dist/ bundles, and runs the host-laya tests.
Contributions are welcome: see CONTRIBUTING.md. Security issues go through SECURITY.md, not public issues. Release notes are in CHANGELOG.md, and planned work is in docs/ROADMAP.md.
License
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
- TaprootOAuthcom.taproothq
Persistent memory layer for AI tools. Save and recall notes across Claude and other MCP clients.
MCP-native notes and memory for ChatGPT, Claude, and other AI tools.
Shared long-term memory vault for AI agents with 20 MCP tools.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides Claude Code with deep access to an Obsidian vault through 28 tools for structural analysis, semantic retrieval, and git-backed timeseries tracking. It transforms your vault into a live knowledge base that Claude can search, navigate, and reason about using its knowledge graph.2MIT
- AlicenseBqualityBmaintenanceBridges Obsidian vaults with MCP-compatible AI tools, enabling read/write/search of notes, task management, and vault operations through 34 tools and prompt templates.3461 npm3MIT
- FlicenseNot gradedqualityCmaintenanceEnables reading, writing, searching, and managing Obsidian vault notes through MCP tools and prompts, allowing AI agents to interact with local knowledge bases.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to read, write, search, and manage an Obsidian vault with tools for notes, tags, folders, and full-text search.6 npmMIT