Second Brain.
Personal LLM-maintained knowledge vault — Obsidian + Claude Code, three-layer schema (immutable raw, LLM-written wiki, enforced spec) — that ships as a single self-replicating HTML build guide.
- Year
- 2026
- Role
- Solo Engineer
- Domain
- AI/Tooling
What it does
This project is a personal engineering knowledge vault that is written by an LLM and read by a human. The user drops a source — a PDF, a piece of text, an image, a repository, an audio recording — into a raw/ folder, asks Claude Code to ingest it, and Claude writes structured Markdown into the wiki/ folder using a fixed set of templates, with cross-references rendered as Obsidian wikilinks. The deliverable is the vault itself: a disciplined directory tree, a schema specification that lives in the agent’s primary context file, and a small set of CLI workflows that keep the writing layer, the source layer and the search layer cleanly separated. The vault is rendered by Obsidian, not by a custom frontend, so the same Markdown that the agent writes is what the human reads.
The system also ships as a product of its own: a single self-contained HTML guide (REPLICATE_LLM_WIKI.html) that rebuilds the entire machine on any PC. The file has two readers — for a human it is a visual walkthrough of the architecture with diagrams; for a Claude Code session it is an executable spec, with a build manifest in an HTML comment and every file to create carried in labelled code blocks. Make an empty folder, drop the file in, say “read it and follow the manifest,” answer two questions (your subject domain, and whether to keep the default 13 entity types), and Claude scaffolds the folders, the schema, the templates, the validator, the skills and the hooks — then proves the loop with a smoke test. Source repository is private.
How it’s structured
The vault is organised in three discrete layers with one rule each: sources are immutable, the wiki is LLM-authored, and the schema constrains the wiki — nothing leaks upward. The first layer is raw/, which holds immutable source material (PDFs, text, images, code repositories, audio) and is read-only to the agent so that ingest cannot corrupt the originals. The second layer is wiki/, the only place Claude is allowed to write: thirteen entity-type subfolders (concepts, equations, methods, materials, papers, people, phenomena, sources, standards, systems and more), the templates that define each entity’s frontmatter and headings, an index page, and a log that records every ingest and revision. The third layer is the schema itself: CLAUDE.md carries the master schema — the entity taxonomy, the frontmatter rules, the seven-step ingest discipline — and is read by the agent on every session.

What makes the invariants real instead of aspirational is enforcement in the harness itself. A PreToolUse hook blocks any write under raw/; a PostToolUse hook runs scripts/check_frontmatter.py on every wiki write, so a page with a missing key, a bad date, or an invalid entity type fails the write instead of rotting silently; and a SessionStart hook surfaces the recent ingest log every time a session opens. Around the three layers, .mcp.json registers the qmd search server with a pinned index path, and the skills folder defines the slash-commands (/ingest and its per-type sub-skills, /query, /new-page) that drive the whole system.

How it works
A new ingest goes through a deliberate seven-step cycle. The user drops the source into the appropriate raw/ subfolder and runs /ingest <path>; a thin dispatcher routes to the matching sub-skill by extension (PyMuPDF extraction for PDFs, Claude vision for images and scanned pages, direct reads for text). Claude summarises the source, proposes the wiki pages it would create or extend, and waits for explicit approval before writing anything. After approval, it authors a source page plus the entity pages from the matching templates — each validated on write by the frontmatter hook — updates the index, appends a line to the log, and reindexes search. The pages cross-reference each other with Obsidian’s [[wikilink]] syntax, and equations are transcribed to LaTeX so MathJax renders them live.

Queries flow the other way: /query "<question>" runs a hybrid search through the qmd MCP server (BM25 keyword + vector + LLM re-rank), reads the top-ranked pages in full, and answers with [[wikilink]] citations rather than free-form prose — every claim points back to a wiki page that points back to a raw source. Audio ingestion arrived in Stage 2 via faster-whisper; the workflow is identical, with the transcript landing in wiki/ like any other source.

Replication works because the guide is the machine. The HTML carries nine ordered build steps — scaffold script, CLAUDE.md “brain”, thirteen templates, the frontmatter validator, six skills, the hooks, optional qmd search, the Obsidian render layer, and an end-to-end smoke test — each as an exact artifact the reader’s own Claude session writes to disk. The guide keeps the copy domain-neutral by design: only the mechanism replicates, and the new owner’s answers shape the taxonomy.
What I learned
The biggest lesson was that schema enforcement is what makes an LLM-maintained knowledge base actually useful. Templates per entity type, a hard write boundary, an explicit log, and a validator wired into the harness hooks are the things that keep the vault coherent over hundreds of pages — without them, the LLM produces beautiful prose and unusable structure. I also learned to treat ingest as a two-step ritual: Claude proposes, the human approves, and only then does anything get written; that extra step kept the vault tidy through every ingest. Wiring search into the agent so queries are forced to cite wikilinks turned the vault from a write-heavy archive into something I actually consult.
Making the system replicable taught its own lessons. A document that must serve two readers — a human skimming diagrams and a Claude session executing a manifest — forces you to separate the why (prose and figures) from the what (byte-exact file blocks tagged for the machine), and the discipline improves both. And small operational traps cost the most time: pinning the qmd index to one absolute path so the CLI and the MCP server never read different databases, ASCII-only filenames so wikilinks never silently break, and idempotent scaffolding so a re-run repairs instead of destroys.