← Projects

Knowledge vault + personal plugin

Plain markdown · Claude Code plugin · no embeddings · no MCP · no daemon

Vault architecture: inbox/ raw notes are promoted via the distil-vault skill into curated knowledge-vault/ folders (strategy, patterns, playbooks, decisions, projects), with the issei-plugin shipping skills that read directly via Read, Grep, and Glob.
Raw notes in inbox/distil-vault skill → curated knowledge-vault folders, read directly by Claude.

What it is

A curated personal knowledge base — strategy, decisions, patterns, playbooks, project hubs, people notes, voice — that Claude Code reads directly from the filesystem with Read, Grep, and Glob. About 216 markdown files at last count, fitting inside Claude's context window with room to spare. The companion plugin (issei-plugin) ships the skills that interact with it: search-vault, distil-vault, lint-vault, plus a handful of voice and meeting helpers.

Why the project is interesting

Not because of what it is now, but because of what it used to be.

The first version was an MCP server. FastMCP protocol layer; SQLite FTS5 for lexical search; LanceDB for vectors; Ollama nomic-embed-text:v1.5 for embeddings; a file watcher that re-indexed on every change; a hybrid scorer that blended FTS and vector similarity. About 600 lines of plumbing. The Claude session would call a custom tool, the tool would run hybrid retrieval, and the top-k chunks would come back as context.

I deleted all of it.

Why I deleted it

Three things happened in the same week. First, I noticed the vault was 216 files and growing — but not so fast that it would ever stop fitting in context. The "retrieval problem" the MCP was solving wasn't a real problem at this scale. Second, I measured the search-quality lift over a plain Grep + Glob workflow on the same corpus: 3–5%, on heavily curated short documents. Not nothing, but not 600 lines of plumbing and an Ollama daemon dependency. Third, three real bugs in the indexing path showed up at once: the Windows file watcher missed MCP-authored files (atomic rename via os.replace doesn't fire on_modified reliably on the renamed target); FTS and vector writes weren't atomic, leaving the two indexes ~20% out of sync; the chunk tokenizer didn't match the embedder's, so retrieval was scoring against the wrong segments.

At that point the cost-benefit was clear. The MCP stack was solving a problem that didn't exist yet, generating problems that did, and blocking the actual lift — which is the discipline of distilling notes well — behind plumbing maintenance.

What replaced it

A markdown convention and three plugin skills.

The convention is a folder taxonomy (strategy, patterns, playbooks, decisions, projects, people, voice, references, daily) with a frontmatter schema that enforces title, created, tags, and links on every note. The links field is the load-bearing one — every new note has to declare its inbound and outbound edges, which forces the writer to locate the new content in the existing graph rather than letting it pile up un-linked.

The skills do the work the MCP used to do, but at write time instead of query time. search-vault is a Glob + Grep + Read pipeline — no index, no embedding, just patterns over filenames and frontmatter. distil-vault takes raw inbox material and produces a curated note plus updates to 5–15 cross-referenced neighbours, so synthesis happens once, by the LLM, when the note is written. lint-vault runs whole-vault consistency checks — missing backlinks, orphan files, frontmatter drift.

The shift in framing: synthesis happens at write time (the LLM updates 5–15 cross-referenced pages when new material lands), not at query time. That's what keeps the vault navigable as it grows; without it, files pile up un-linked and the "Claude reads the whole vault" affordance erodes.

The pattern the project actually demonstrated

Vector retrieval is the right answer for a class of problem — long-form corpora, mixed-domain knowledge, multi-tenant systems, RAG over content you don't control. None of those apply to a personal vault. The interesting bit is recognising when the platform-level solution is the wrong size for the actual workload, and being willing to delete 600 lines of code that worked.

There's a longer version of this argument in writing.

Links