Back
tooling|obsidian|AI9 min read

A Knowledge Base That Two Minds Share

I have a problem most engineers have: I document things, then never find them again. Meeting notes, architecture decisions, project setups, debugging war stories - they all go into some folder and rot. I wanted a system where I could write naturally and retrieve intelligently, without maintaining a search index by hand or relying on exact keyword recall.

Here's what I built.

The Stack

Obsidian is where I write. Markdown files, wikilinks, tags, frontmatter. Nothing proprietary. The vault lives in iCloud (~/Library/Mobile Documents/iCloud~md~obsidian/Documents), which means it syncs across my Mac, iPad, and iPhone automatically. I can jot down a note on my phone during a meeting and it's indexed by the time I sit down at my desk.

QMD is a local search engine that indexes markdown files. It builds two indexes over my vault: a BM25 keyword index for exact term lookups, and vector embeddings for semantic search. The embeddings run locally on Apple Silicon via Metal - no data leaves my machine. It exposes search as an MCP tool, which means any AI assistant that supports MCP can query my notes.

Claude Code (and Claude Desktop) connect to QMD via MCP. When I'm working on a project and need context - "what did I decide about the database schema?" or "what was that SSL issue I hit last month?" - Claude searches my vault, pulls relevant snippets, and uses them in context.

How It Fits Together

Knowledge Pipeline

Obsidian Vault
auth-service-setup.mdinfrastructure
passkey-gotchas.mdwebauthn
ssl-tls-debugging.mddeployment
database-schema.mdarchitecture
cdk-custom-domain.mdaws
Waiting for content
Claude Session
Ask something...

Click Replay to see a query in action

write
index
query
search
results
context

Setup was straightforward:

  1. Point QMD at the vault: qmd collection add "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/hivemind" --name hivemind
  2. Generate embeddings: qmd embed
  3. Enable the QMD plugin in Claude Code settings
  4. Add QMD as an MCP server in Claude Desktop config

There's also a Claude Code hook that keeps the index fresh automatically. Claude Code lets you run shell commands in response to tool use. In ~/.claude/settings.json, I have a PostToolUse hook with an if filter that only fires when a file inside the vault is written or edited:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "if": "Write(**/iCloud~md~obsidian/**)",
            "command": "(qmd update && qmd embed) & # & backgrounds so Claude isn't blocked"
          },
          {
            "type": "command",
            "if": "Edit(**/iCloud~md~obsidian/**)",
            "command": "(qmd update && qmd embed) & # & backgrounds so Claude isn't blocked"
          }
        ]
      }
    ]
  }
}

No shell script needed. The if field uses gitignore-style patterns to match against the file path, so edits outside the vault are ignored entirely. When it does match, qmd update refreshes the keyword index and qmd embed refreshes vector embeddings. Both search modes stay current without me thinking about it.

The Documentation Loop

Here's the part that makes this more than a note-taking app. I have Claude Code set up to document every project I work on into this Obsidian vault. Architecture decisions, infrastructure setup, gotchas, deployment steps - it all gets written as markdown with proper frontmatter and wikilinks.

I also drop meeting transcriptions into the vault. A lot of decisions happen in calls and never make it into a ticket or a doc. The transcript goes in, QMD indexes it, and now Claude can surface "we decided X in the sync on March 12th" when the context matters.

This creates a flywheel:

  1. I work on a project with Claude
  2. Claude documents what we built, what broke, what we decided
  3. Those docs get indexed by QMD
  4. Next time I (or a new Claude session) work on the same project, the context is already there

The instructions that drive this live in my CLAUDE.md:

- **Obsidian as Knowledge Base**: Build a knowledge base in the
  Obsidian vault. For every new project, create a directory and
  document decisions, setup, and gotchas. Keep updating stale
  docs and correct wrong assumptions as the project evolves.
- **qmd as search engine**: Use QMD to search markdown. At
  conversation start, search for existing context before asking
  the user to re-explain. After completing a task, ask if the
  outcome should be documented into the vault.

That last line is what keeps the vault growing. Claude prompts me, I say yes or no, and the flywheel keeps turning. And because it also updates existing docs when things change, the vault doesn't accumulate stale information - it stays current.

The key insight is that Claude has no memory between sessions. But my vault does. Every conversation that produces something worth keeping gets persisted as a markdown file. The next session picks up where the last one left off - not because the AI remembers, but because the knowledge base remembers.

More Than a Second Brain - It's Claude's Long-Term Memory

The thing that surprised me is how much this changes what Claude can do. This isn't just a note-taking system with good search. It's an external memory that gives Claude continuity across sessions.

When I start a new conversation and say "I need to add passkey support to the auth service," Claude doesn't start from zero. It searches the vault, finds the infrastructure doc, the architecture decisions, the gotchas from the last deployment, the exact CDK config we used. It reads all of that, and the conversation picks up as if we never stopped.

This matters because real projects are messy. They span weeks. They involve decisions that build on each other. Without the vault, every Claude session is a cold start - I'd spend the first 20 minutes re-explaining context. With it, Claude can trace the full history: what was the original PRD, what changed during implementation, what broke in deployment, what we learned.

Some concrete examples of what this enables:

  • Resuming abandoned threads. I started a database migration three weeks ago and got pulled onto something else. When I came back, Claude found the migration doc, the schema review notes, and the open questions I'd left for myself. No context was lost.
  • Cross-project pattern matching. Say you're debugging a database connection error in Project B. Claude searches the vault and finds that three months ago, in a completely unrelated Project A, you documented the exact same issue with a different description. Same underlying cause, different context. The vault connects dots across projects that your memory wouldn't.
  • Onboarding new Claude sessions to complex state. My infrastructure spans multiple CDK stacks, multiple services, and multiple environments. A new Claude session can search the vault and understand the full topology in seconds - which stack depends on which, what's deployed where, what env vars are set.
  • Catching contradictions. If I ask Claude to implement something that conflicts with a past decision, it can surface the original reasoning. "We decided against token blacklists in the auth architecture doc because of complexity - are you sure you want to add one now?"

The vault becomes a shared context layer between me and every future Claude session. I write once, and every subsequent conversation benefits. It's the closest thing to giving an AI long-term project memory without actually having persistence built into the model.

The trick is that the docs have to be good. Not polished - good. They need to capture why we made decisions, not just what we built. "We used a conditional rpID because hardcoding breaks localhost" is useful in six months. "Configured rpID" is not.

Query Types

QMD supports three search modes, and combining them gets surprisingly good results:

  • Keyword (lex): BM25 search. Good for exact terms: "connection pool" timeout
  • Semantic (vec): Vector similarity. Good for concepts: "how does rate limiting work?"
  • Hypothetical (hyde): You write what the answer might look like, and it finds docs that match. Best for nuanced questions.

In practice, I almost always combine lex + vec. First sub-query gets double weight, so I lead with the strongest signal.

What I Like About This

Everything is local. Embeddings run on-device. Notes live on my filesystem. No cloud service owns my data. iCloud is just a sync layer - I could replace it with Syncthing or Dropbox tomorrow.

It's plain markdown. No lock-in. If QMD disappears, I still have a folder of .md files that any text editor can open. The wikilinks and frontmatter are Obsidian conventions, but they're still valid markdown.

Claude becomes genuinely useful for recurring work. Instead of re-explaining my project setup every session, Claude searches the vault and gets up to speed in seconds. The quality of assistance goes up dramatically when the AI has real context about your specific codebase and decisions.

The phone-to-desk pipeline works. I capture a quick note on my phone, it syncs via iCloud, QMD picks it up on next index, and Claude can reference it in my next coding session. No manual steps.

It's not just for work. I use the same vault to plan trips, track fitness and health notes, and manage finances. Anything worth writing down goes in. When I ask Claude to help me plan a weekend trip, it already knows my preferences from past travel notes. When I'm reviewing my budget, it has context from previous months. The system works for any domain where you accumulate decisions over time.

What Could Be Better

The vector search quality depends heavily on how you write. Dense, jargon-heavy notes with no context don't embed well. I've started writing notes more conversationally - explaining the why, not just the what - and retrieval improved noticeably.

Re-indexing is fast but not instant. There's a few-second delay between writing a note and it being searchable. Fine for my workflow, but worth knowing.

The system also only works as well as your discipline in writing things down. The best search engine in the world can't find docs that don't exist. I've gotten into the habit of treating documentation as a first-class output of any project, not an afterthought.

The Setup in ~5 Minutes

If you want to try something similar:

  1. Install Obsidian and create a vault. On macOS it defaults to ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/ which syncs via iCloud automatically. Your notes show up on iPhone and iPad without any extra config.
  2. Install QMD and point it at your vault:
    bash
    qmd collection add "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/your-vault" --name your-vault
    qmd embed
    
  3. Enable the QMD plugin in Claude Code, or add it as an MCP server in Claude Desktop's config.
  4. Add instructions to your CLAUDE.md telling Claude to search QMD for context at the start of a conversation, document outcomes into the vault, and keep existing docs updated.

That's it. No database, no SaaS, no config files longer than 5 lines.