Skip to main content

Erudition

Portable, typed, git-friendly memory for AI agents.

Claude Code's built-in memory is local-only and opaque. It lives inside Claude Code itself, isn't portable across machines, and isn't something you can casually read, diff, or edit by hand. Erudition is an MCP server that gives an agent read/write access to a memory store that's none of those things: a plain folder of markdown files, organized around a real taxonomy instead of a junk drawer, editable in whatever notes app you already use, and portable across every machine you own via git.

This README covers what Erudition does and how to install it. For the reasoning behind why it's built this way, and just as importantly, why it isn't built several other, more obvious ways, see WHY.md.

What it is

  • An MCP server. Works with Claude Code, Claude Desktop, or any other MCP-compatible client, exposing nine tools (see Tools below).
  • A markdown vault, not a database. Every memory is a .md file with YAML frontmatter, in a folder you fully control. No proprietary format, no service to run, no account to create. Obsidian is a good viewer/editor for it, but Erudition doesn't require Obsidian. Any plain-text editor works.
  • A taxonomy, not a junk drawer. Memories are typed (user / feedback / project / reference by default), so an agent (and you) can tell "a fact about how I like to work" apart from "a fact about this specific project" at a glance.

What it isn't

  • Not a hosted product. It runs locally, wherever your agent runs.
  • Not a "chat with your notes" RAG plugin. Erudition is about agent memory (what an agent should remember across sessions), not general document search.
  • Not a replacement for Claude Code (or Claude Code's own memory). It's a layer on top, and it's designed to stay small rather than grow into a competing agent runtime.

Quickstart

1. Install

git clone https://github.com/Ralf090102/Erudition.git
cd Erudition
pip install -e .

This installs the erudition command (the PyPI distribution is named erudition-mcp; the import path and CLI command stay erudition).

2. Point it at a vault

Erudition needs to know which folder is your vault:

export ERUDITION_VAULT_PATH="/path/to/my-notes"

That's a complete, valid setup on its own. If you want the auto-commit toggle or a custom taxonomy, write an erudition.toml instead (or alongside). Copy erudition.example.toml and see the Configuration table below for every option.

3. Connect it to your MCP client

For Claude Code, add it to your MCP server config:

{
  "mcpServers": {
    "erudition": {
      "command": "erudition",
      "env": {
        "ERUDITION_VAULT_PATH": "/path/to/my-notes"
      }
    }
  }
}

Restart your client. You should see all nine tools below available.

Erudition keeps a small search index at {vault}/.erudition/. It's a rebuildable cache, not real content, so add .erudition/ to the vault's own .gitignore.

Tools

Tool What it does
read_note(path) Read a note's contents.
list_notes(folder="") List markdown notes in a folder, recursively (empty string lists the whole vault).
search_notes(query, folder="") Search note contents, backed by a rebuildable SQLite FTS5 index rather than a linear scan. This makes matching token-based, not raw substring: wid* matches "widgets," a bare idget doesn't the way a plain substring scan would. Supports FTS5 phrase ("exact phrase") and boolean (AND / OR / NOT) syntax. Falls back automatically to a plain linear scan if the local sqlite3 build lacks FTS5. Returns matching file paths and the lines that matched; if a query is still slow despite the index, the result includes a one-line note suggesting the staleness check itself might be worth revisiting.
write_note(path, content, overwrite=False, dry_run=False) Write a note; refuses to clobber an existing one unless overwrite=True. dry_run=True writes nothing and returns a preview (new content, or a diff against what's there) instead.
append_to_note(path, content, dry_run=False) Append to a note, creating it (and any parent folders) if it doesn't exist yet.
list_memory_types() List the vault's configured taxonomy: valid type values for save_memory, and what each is for.
save_memory(type, name, description, content, overwrite=False, dry_run=False) Save a typed memory (validated against the taxonomy), with standard frontmatter, indexed in MEMORY.md.
sync_memory() Mirror the vault's memory folder out to a configured local memory directory.
rebuild_search_index() Force a full rebuild of the search index from scratch. Rarely needed, since search_notes already self-heals from a cheap per-search staleness check; mostly a manual escape hatch for recovery or peace of mind after a large batch of external edits.

The taxonomy

Erudition's default memory types, and what each is for:

Type What goes here
user Who the person is: their role, goals, expertise. Lets an agent tailor how it explains things.
feedback Corrections and confirmed approaches, like "don't do X, we tried it and it broke Y" or "yes, that approach was right." Stops an agent from repeating a mistake or re-litigating a settled call.
project Ongoing context about why (decisions, deadlines, stakeholders) that isn't visible in the code or git history alone.
reference Pointers to where information actually lives, e.g. "bugs are tracked in Linear project X," not a copy of the bugs themselves.

This is a starting point, not a fixed schema. Define your own types under [taxonomy.*] in erudition.toml if your vault needs a different shape. See erudition.example.toml.

Saving and syncing memories

Beyond generic write_note, Erudition understands the taxonomy. save_memory validates the type you pass against the vault's configured types, writes the memory to Memory/{type}_{slug}.md with standard frontmatter, and keeps Memory/MEMORY.md as a lightweight index, one line per memory:

save_memory(
    type="feedback",
    name="Prefers terse commit messages",
    description="User wants one-line commit messages, no bullet lists.",
    content="Confirmed after three separate corrections. Applies to this repo only.",
)

If your agent also keeps its own local memory folder (Claude Code does), sync_memory() mirrors everything under the vault's memory folder out to it, so writing a memory once in the vault doesn't also require a manual second write elsewhere. Configure the destination via local_memory_dir (see Configuration below). sync_memory() errors clearly if it isn't set, rather than silently doing nothing.

Write safety: a permanent design choice, not a limitation

Erudition assumes one active writer at a time. Flat markdown files have no locking, so if a human and an agent (or two agent sessions) write to the same note within moments of each other, the later write silently wins. No merge, no conflict marker, no error.

This is deliberate, not an oversight. Closing that gap completely would mean row-level locking, which means becoming a database. That trades away the one thing that makes a markdown vault worth using over a SQLite-backed alternative: you can open, read, and edit every memory in any plain-text editor, no tooling required. Instead, Erudition offers durability without locking: an optional auto_commit setting that git-commits every write with a distinct, identifiable message (erudition: write <path>). It doesn't prevent a collision, but it means a collision is always recoverable via git log / git diff instead of silently gone.

If you run more than one agent session against the same vault at the same time, that's exactly the scenario this boundary is about. Treat "one writer at a time" as a real constraint, the same way you would with any file two processes might edit concurrently.

Separately from durability, write_note, append_to_note, and save_memory all accept dry_run=True: nothing gets written, and you get back a preview instead, either the full content for a brand-new note, or a unified diff against what's already there for an overwrite. Useful for checking what a change would actually do before committing to it, especially with overwrite=True.

Optional: Claude Code hook integration

This is Claude-Code-specific and entirely optional — it's a companion to the core MCP server above, not a change to it, and it doesn't do anything with other MCP clients. If you don't use Claude Code, skip this section.

Two problems this solves: remembering to read a "where we left off" note at the start of every session, and remembering to call sync_memory() after making changes. Claude Code has its own hook system (separate from MCP) for exactly this: SessionStart can inject context automatically when a session begins, and Stop runs after every turn.

Add this to your project's .claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "erudition hook session-start"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "erudition hook stop"
          }
        ]
      }
    ]
  }
}

erudition hook session-start reads the note at session_start_note (defaults to Memory/CURRENT.md; see Configuration) and injects its contents as session context. erudition hook stop calls sync_memory(). Both are best-effort: a missing note or an unconfigured sync_memory is a silent no-op, never an error that could block a session or a turn.

Configuration

Setting Env var erudition.toml key Default
Vault path ERUDITION_VAULT_PATH vault_path (required, one or the other)
Auto-commit on write ERUDITION_AUTO_COMMIT auto_commit false
Memory taxonomy [taxonomy.*] the four types above
Memory folder ERUDITION_MEMORY_FOLDER memory_folder Memory
Local memory mirror (for sync_memory) ERUDITION_LOCAL_MEMORY_DIR local_memory_dir unset
Session-start note (for the optional hook) ERUDITION_SESSION_START_NOTE session_start_note Memory/CURRENT.md
Config file location ERUDITION_CONFIG ./erudition.toml if present

An env var always wins over the config file for the setting it covers. Full example with every option: erudition.example.toml.

Development

pip install -e ".[dev]"
pytest

Status

Early stage. Config-driven vault path, generalized taxonomy, the write-safety toggle (including dry-run previews), the taxonomy-aware memory tools (save_memory, sync_memory, list_memory_types, append_to_note), a rebuildable FTS5 search index, and a real, repo-tracked test suite are all done. Not yet on PyPI. Expect breaking changes before a 1.0 release.

License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

erudition_mcp-0.1.0.tar.gz (31.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

erudition_mcp-0.1.0-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file erudition_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: erudition_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 31.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for erudition_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 081bdb02d9cd0cc70c1b307a2fed6701f5bb4303ec1af2c8d5da5f74206b7bb2
MD5 84503ef9f1798d15fc29204586f63a10
BLAKE2b-256 fd10e6b5807fb76849b2a3ea3f751d0c281e6f86c17d0708c90084305779b3d4

See more details on using hashes here.

File details

Details for the file erudition_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: erudition_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for erudition_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c270847464a4a529c4a3403ba0f80aa47e24bf63609dfd45651788ec069e4be
MD5 f3c05e869cb64071c7718d3693eac68f
BLAKE2b-256 2adcccc41849ea8a7dc211242e47e637f6398fd6f4e48376563515fda97ada4d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page