Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

DuckBrain

DuckBrain

DuckBrain gives AI coding agents read and write access to an Obsidian vault over MCP. It indexes Markdown pages with DuckDB full-text search, so agents can find and update wiki pages while the source stays in your vault. Install it with uv tool install duckbrain, then set VAULT_PATH and run duckbrain as the MCP server.

Quick start

Install DuckBrain:

uv tool install duckbrain

Run the MCP server over stdio, pointing it at your vault:

VAULT_PATH=/path/to/your/vault duckbrain

To connect an AI coding agent, configure its MCP client to run duckbrain with VAULT_PATH set. The setup sections below show configurations for OpenCode, Claude Code, Cursor, and Hermes.

Agent setup

Use the platform-specific setup script for one-command installation with Claude Desktop:

macOS / Linux:

curl -O https://raw.githubusercontent.com/timhiebenthal/duckbrain/main/setup-duckbrain.sh
bash setup-duckbrain.sh

Windows (PowerShell):

Invoke-WebRequest -Uri "https://raw.githubusercontent.com/timhiebenthal/duckbrain/main/setup-duckbrain.ps1" -OutFile "setup-duckbrain.ps1"
.\setup-duckbrain.ps1

The script installs DuckBrain, configures Claude Desktop, validates everything, and is safe to run multiple times. See the Setup Guide for details.

After installing DuckBrain, follow the setup guide for your agent:

  • OpenCode — MCP server + session plugin (recommended)
  • Claude Code — MCP server + CLAUDE.md + SessionStart hook
  • Cursor — MCP server + rules + hooks
  • Hermes — MCP server + AGENTS.md
  • Codex CLI — vault context and journaling

For another MCP client, run duckbrain with VAULT_PATH set.


OpenCode

The OpenCode setup includes the MCP server and a session plugin for vault context and journaling.

Add to opencode.json:

{
  "mcp": {
    "duckbrain": {
      "command": "duckbrain",
      "env": { "VAULT_PATH": "/path/to/your/vault" }
    }
  }
}

Download the session plugin (you need bun for the install):

mkdir -p ~/.config/opencode/plugins/
cd ~/.config/opencode/plugins

for f in vault-context.ts vault-context-helpers.ts package.json; do
  curl -O "https://raw.githubusercontent.com/timhiebenthal/duckbrain/main/opencode/plugins/$f"
done

bun install

The plugin supports OpenCode 2 and OpenCode 1. One default export serves both: OpenCode 2 reads its setup entrypoint, OpenCode 1 reads its server entrypoint.

OpenCode 1 users: the dual entrypoint needs 1.18.29 or newer. On older V1 releases the plugin will not load - upgrade OpenCode, or use a DuckBrain release from before this plugin shipped.

Restart OpenCode. The plugin gives your AI automatic vault awareness and a few useful defaults:

  • Vault-aware context — your AI sees your vault's topics, recent notes, and today's daily entry automatically. No need to ask "what's in my vault" or paste paths.
  • Daily note journaling — the AI captures session progress, decisions, and discoveries into your daily note as you work, so you don't lose context between sessions.
  • Real local-time timestamps — entries are timestamped with your actual local time, not whatever the AI guesses.
  • End-of-session save — when you finish a session, the AI is prompted to journal anything new before the conversation closes. (Window close is still a loss — use /journal for guaranteed save.)

Claude Code

Prerequisite: uv or uvx on your PATH — the plugin runs the MCP server via uvx duckbrain (no manual pip install needed; uvx fetches and caches it automatically)

Install via plugin marketplace

claude plugin marketplace add /path/to/duckbrain/claude/
claude plugin install duckbrain@duckbrain-local
# Claude Code prompts for your vault path, or pass it non-interactively:
# claude plugin install duckbrain@duckbrain-local --config vault_path=/path/to/vault

Claude Code prompts for your vault path at enable time — no manual VAULT_PATH env var needed.

What you get

Enable plugin → prompted for vault path once
     ↓
Session start → SessionStart injects LEARNINGS guard + tags + daily notes
     ↓
During session → guard prompts Claude to journal after non-trivial work
     ↓
Every ~15 min → UserPromptSubmit re-surfaces the concise journal nudge (throttled)
     ↓
Context full → PreCompact injects snapshot + journal nudge
     ↓
Session end → type /journal → Claude writes summary to daily note
     ↓
SessionEnd hook → appends "Session end — HH:MM" timestamp

The plugin bundles four hooks (SessionStart, UserPromptSubmit, PreCompact, SessionEnd), the duckbrain MCP server config, and a /journal slash command. No manual settings.json editing.

Manual wiring (advanced)

If you prefer wiring hooks yourself without the plugin, the standalone scripts in scripts/claude-vault-*.sh still work — see the comments in each file for the required settings.json entries.


Cursor

Full vault awareness via .cursorrules (injected into every system prompt), MCP server, /journal slash command, and a SessionEnd hook. See cursor/README.md for complete setup.

Quick setup:

# 1. Copy .cursorrules to your project root
cp cursor/.cursorrules /path/to/your/project/.cursorrules

# 2. Copy MCP config to your project
mkdir -p /path/to/your/project/.cursor
cp cursor/.cursor/mcp.json /path/to/your/project/.cursor/mcp.json
# Edit mcp.json: replace /path/to/duckbrain with your actual clone path

# 3. Copy /journal command
mkdir -p /path/to/your/project/.cursor/commands
cp cursor/commands/journal.md /path/to/your/project/.cursor/commands/journal.md

# 4. Install SessionEnd hook
mkdir -p ~/.cursor/hooks/
cp cursor/hooks/vault-journal.sh ~/.cursor/hooks/vault-journal.sh
chmod +x ~/.cursor/hooks/vault-journal.sh

Wire the hook in ~/.cursor/hooks.json:

{
  "version": 1,
  "hooks": {
    "sessionEnd": [
      { "command": "/home/youruser/.cursor/hooks/vault-journal.sh" }
    ]
  }
}

Session flow: .cursorrules is injected every turn → AI calls vault_context() at session start to load daily notes and search results → guard prompts AI to journal after non-trivial work → /journal writes summary → SessionEnd hook appends timestamp.

Known gaps: no unsolicited journal nudge (no session.idle hook in Cursor), no automatic SessionStart injection (the hook is confirmed broken by Cursor devs — .cursorrules fills the gap reliably).


Hermes Agent

Has been tested and validated.

Add to mcp.json:

{
  "mcpServers": {
    "duckbrain": {
      "command": "uv",
      "args": ["run", "duckbrain"],
      "env": { "VAULT_PATH": "/path/to/your/vault" }
    }
  }
}

Add to AGENTS.md:

# DuckBrain vault
Call vault_info() at session start to discover vault topics.
Use vault_search() when the query matches vault content.
After non-trivial work, save learnings with vault_write().

Restart Hermes.


Tools

Tool What it does
vault_search Full-text search over vault pages
vault_read Read a page by title or filepath
vault_write Create a page or append to today's daily note
vault_context Load daily notes + keyword search in one call
vault_info Vault stats: page counts, tags, last modified

Vault Schema

your-vault/
├── wiki/
│   ├── entities/       # people, orgs, tools
│   ├── concepts/       # ideas, frameworks
│   ├── sources/        # summaries of ingested content
│   ├── synthesis/      # cross-cutting analysis
│   ├── index.md        # page catalog (auto-updated)
│   ├── log.md          # write history (auto-updated)
│   └── tags.md         # topic index (auto-updated)
├── daily/              # daily notes (YYYY-MM-DD.md)
└── .env                # VAULT_PATH (optional)

Pages use YAML frontmatter:

---
title: Claude Mem
item-type: entity
tags: [ai, memory, mcp]
created: 2026-05-28
updated: 2026-05-28
---

Nerdy Details

Implementation internals — not needed for installation.

Architecture

┌──────────────────────────────────────────────────────────────┐
│                      AI Agent                                │
│  ┌──────────────────────────┐  ┌──────────────────────────┐  │
│  │ MCP Client (stdio)       │  │ MCP Client (streamable-HTTP)│  │
│  │  vault_search,           │  │ (Settings → Connectors)   │  │
│  │  vault_read, vault_write │  │  http://localhost:8000/mcp│  │
│  │  vault_context, vault_info│  │                           │  │
│  │                          │  │ Hooks / Plugins          │  │
│  └──────────┬───────────────┘  └──────────┬───────────────┘  │
└─────────────│──────────────────────────────│──────────────────┘
              │ MCP stdio                    │ HTTP
              ▼                              ▼
┌──────────────────────────────┐  ┌──────────────────────────────┐
│  DuckBrain MCP Server        │  │ Side channel:                │
│  vault_info   ──► DuckDB FTS │  │  wiki/tags.md                │
│  vault_search ──► DuckDB FTS │  │  daily/YYYY-MM-DD.md         │
│  vault_read   ──► Filesystem │  │  wiki/log.md                 │
│  vault_write  ──► Filesystem │  │                              │
└──────────────┬───────────────┘  └──────────────────────────────┘
               │ reads/writes
               ▼
┌──────────────────────────────────────────────────────────────────────┐
│                     Your Obsidian Vault                              │
│  wiki/entities/  wiki/concepts/  wiki/sources/  wiki/synthesis/      │
│  daily/          wiki/index.md   wiki/log.md    wiki/tags.md         │
└──────────────────────────────────────────────────────────────────────┘
  • Reads vault files directly — no index to sync, no watchers, no duplicate storage
  • Searches via DuckDB FTS (BM25 ranking), rebuilt fresh from disk on every query
  • Writes new pages with YAML frontmatter, auto-updating index, log, and tags

Inspirations

This project stands on the shoulders of several ideas and tools:

  • Andrej Karpathy's LLM wiki pattern — the idea that a personal markdown wiki, co-maintained by humans and AI agents, compounds into a persistent knowledge base. The vault schema (entities, concepts, sources, synthesis, daily log) is directly inspired by this.
  • DuckDB — the embedded analytical database that makes full-text search over flat files viable without a server, index sync, or persistent storage. The decision to use in-memory FTS instead of a vector database was a deliberate trade-off for simplicity.
  • Obsidian — the local-first, markdown-native note-taking tool that treats your files as the truth. DuckBrain exists because Obsidian vaults deserve tooling that respects the filesystem.
  • MemSearch and Open Brain (OB1) — early experiments in cross-tool agent memory that demonstrated the need for structured vault write-back while choosing different architectures. Their strengths and gaps directly informed DuckBrain's design.
  • Agent Memory Systems (6-level taxonomy) — Simon Scrapes' comprehensive comparison of Claude Code memory approaches provided the framework for understanding where DuckBrain fits in the ecosystem (Level 6: cross-tool MCP with dedicated server).
  • trellis-datamodel — the same author's data modeling tool whose CI/CD patterns (trusted PyPI publishing, version-diff release detection, Keep a Changelog) were borrowed for this project's repository readiness.
  • mondayDB 3 — Solving HTAP for a Trillion-Table System — monday.com's engineering blog on their DuckDB-powered CQRS read serving layer at production scale. Proved that DuckDB in-process with per-tenant file isolation is a viable architecture — the same pattern DuckBrain applies at personal-wiki scale.

The core decision — build, don't integrate — came from a structured comparison of 7 existing tools. All failed on one requirement: vault schema-aware write-back. Rather than fork or extend, DuckBrain started from first principles: what's the simplest thing that gives agents structured read/write access to an Obsidian vault? The answer was DuckDB + MCP + ~500 lines of Python.


Building from Source

git clone https://github.com/timhiebenthal/duckbrain.git
cd duckbrain
uv sync
uv run duckbrain  # will hang waiting on stdio — that's correct

Metadata

Release files for duckbrain 0.8.0b1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for duckbrain 0.8.0b1
File Size Uploaded Provenance Actions
duckbrain-0.8.0b1.tar.gz 30.5 kB Without provenance Details for duckbrain-0.8.0b1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for duckbrain 0.8.0b1
File Interpreter ABI Platform Actions
duckbrain-0.8.0b1-py3-none-any.whl Python 3 none any Details for duckbrain-0.8.0b1-py3-none-any.whl

Total release size: 73.4 kB

Release files / duckbrain-0.8.0b1.tar.gz

Download URL duckbrain-0.8.0b1.tar.gz
Size 30.5 kB
Tags Source
SHA-256 checksum
How to use checksums
69410bff7ac8fc9b4f1b15b9e5850c4c51dce904e03b1eda19f449ea5dc7f645
BLAKE2b-256 checksum
How to use checksums
f231179092ece5c1f732bfd7e203f830faae166ef3c1a659407b7631c4adecea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / duckbrain-0.8.0b1-py3-none-any.whl

Download URL duckbrain-0.8.0b1-py3-none-any.whl
Size 43.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1ece521eb9f83e436dca3d358268c3ec49b9e71e64092ab1f4119981530bd12e
BLAKE2b-256 checksum
How to use checksums
0bc410222fa6308f62289b36d02c9ba680fa59f587216c9aa1389511bd365210
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for duckbrain 0.8.0b1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page