The Exomind

The Context Wall, applied to life. I turned diary, finances, work notes, meetings, and years of emails into a queryable knowledge base that Claude Code drives in plain English. The full blueprint: refactor, ingestion, daemon, autonomous operation.

The Exomind — AI

In The Context Wall I argued that a single 4,000-line markdown file eventually breaks under its own weight, and that QMD is the upgrade path. The framing was AI-native engineering: a context file for your codebase.

This post is the follow-up. I took my own medicine. Then I did something I wasn't planning to do.

I applied the same stack — Claude Code, QMD, a disciplined knowledge hierarchy — to my entire life. Personal archives. Administrative records. Domain operations. Finance history. Work artifacts. Thousands of emails. Meeting transcripts. Piles of half-written notes scattered across tools. All of it.

And now when I want to know what someone said in a past meeting, I ask in plain language. When I want to log a payment, I say it. When I want a report, I say it. Everything is indexed. Nothing is lost. And the AI drives the infrastructure so I don't have to.

This is the field report. The blueprint. The receipts.


Why extend the Context Wall argument to life

The Context Wall was narrow: your ctx.md eventually breaks because transformers pay less attention to tokens in the middle, and you run out of window. QMD fixes that with on-device hybrid search.

But the argument generalizes. Your life is the biggest, messiest, longest-running knowledge base you'll ever own. It's wildly larger than any code project. It's scattered across apps, emails, PDFs, notes apps, calendar events, photos, conversations you can't remember. It has no structure. Nothing is queryable. Nothing is indexed.

And the loss is brutal. You forget what you decided in January. You re-learn the same lessons every year. You lose context on relationships, commitments, finances, work. You look for something and you can't find it, so you rebuild it from scratch. That's not just annoying — that's compound interest on ignorance.

What if your AI had perfect recall of everything you've ever done? What if every decision, every journal entry, every receipt, every meeting note, every learning, every mistake was indexed, searchable, and available in context the moment you needed it?

That's what I built. It takes a week. It's worth it.


The repo

One monorepo. Three layers.

  • content/ — curated knowledge. What you wrote. Voice-preserved. Every area has its own CLAUDE.md (rules for the AI) and overview.md (always-loaded summary).
  • data/ — machine-generated or ingested. Tool outputs. Raw email extracts. Calendar dumps. Meeting transcripts. Things you don't hand-edit.
  • tools/ — automation. Python, Node, shell. Reads from content and data, writes back, produces outputs — PDFs, API calls, reports.

Areas under content/ (generalized names):

  • diary/YYYY/MM/ — dated personal entries
  • life-story/ — long-form autobiographical narrative, chapter-split
  • finance/ — wealth snapshots and income tracking (not transactions)
  • insights/ — AI-generated analysis over your own data, dated
  • plans/goals/ and plans/projects/ — objectives and roadmaps
  • reflections/ — retrospectives and lessons
  • notes/ — the catch-all
  • templates/ — markdown templates for dated entries (diary, finance-snapshot, goal, insight, reflection)
  • household/ — domestic matters, employment contracts, payroll
  • legal/ — legal records, structured
  • homeschool/ — curriculum, sessions, daily logs, contacts (for anyone with kids)
  • blog/ — the blog knowledge base that this very post lives in

The top-level structure is intentional: by the time you're done reading a folder name, you know whether to go deeper or not. No ambiguity. No where does this belong? questions.


The refactor

I started with what most people start with: four monolithic files. A 4,000-line operations database. Another bigger one (roughly 6,000 lines). A 197,000-line (!) email dump. A 37,000-line calendar export. Plus about sixty smaller files. Total: roughly 257,000 lines. The knowledge was there — but it was shaped wrong.

The Context Wall argument applies. A single 6,000-line file means attention degradation, cold starts, painful git diffs, and the creeping urge to not write things down because the file is already too big. Exactly the failure mode QMD was built to fix.

So I split. Not by line count. By semantics. Every section that had a clear topic became its own file.

The biggest monolith — the ~6,000-line database for another area — had always been a nightmare to navigate. It became an overview.md plus about two dozen focused files, split at the semantic section boundaries that were already implicit in the document. Largest remaining single file: about 2,600 lines. Most are under 200. The overview.md loads automatically when I work in the area. Everything else is retrievable via QMD.

The operations database split into 17 topic files plus a log/YYYY-MM-DD.md directory for daily activity notes. The overview ate the weekly-schedule reference. The session tracker — the live operational state — got its own file. Source citations stayed with each topic.

The 197,000-line email dump became data/<area>/email/YYYY-MM.md — one file per month. Each email preserved verbatim, grouped by when it was received. I wrote a 60-line Python script to parse the Date: headers, group, renumber, and write. Re-runnable. Content verified by message-ID count: zero loss.

The 37,000-line calendar export followed the same pattern: monthly files, each event tagged with its source calendar.

Old diary archives (previously one giant annual.md per year) became one YYYY/MM.md per year-month. Consistent with the per-day structure I use for current entries. I can now ls content/diary/<year>/ and see every month I wrote something, at a glance.

One rule I settled on: split by semantics, not by size. Size is the symptom. A large file with clear sections is actually fine — split at the section boundaries. A large file with no structure is a sign you don't understand your own knowledge yet. Fix that first.


The ingestion

Once the structure was right, I had to pull in everything that wasn't already there.

Accumulated Google Drive content. 555 files. 239 PDFs, 101 videos, 78 images, 36 more videos, 22 audio files, 19 JPEGs, 8 HEIC, 8 DOCX, 7 more audio, 6 text files, 6 Google Doc shortcuts, 1 zip.

Breakdown of what's actually extractable without OCR or transcription:

  • PDFs with a text layer — extracted via pdftotext -layout, fallback to plain pdftotext. 141 of 237 yielded clean text.
  • Image-only PDFs — 96 of them. Scanned documents with no text layer. Flagged for OCR with priority labels. Catalogued by filename + path so they're at least searchable by metadata.
  • DOCX filestextutil -convert txt -stdout. Clean.
  • Text files — direct read.
  • Google Doc shortcuts — JSON pointers to Drive docs, not content. Noted the URLs.
  • Audio and video — listed by path, not transcribed in this pass. Tagged for future Whisper runs.

Then the merge. I spawned two parallel sub-agents — one for each domain area — each with a clear brief: read the inventory, read the existing files, identify what's new versus already captured, and merge with source citations. No duplication. Voice-preserved. Image-only PDFs flagged with priority tiers.

One agent handled one area. The other handled another. Together they merged around 100 documents with full source citations — every addition tagged with **Source:** /path/to/original.pdf, so I can audit exactly where any piece of knowledge came from. Both reported back with surprising findings — things I hadn't realized were buried in old PDFs. Some of them mattered more than I realized.

Sub-agents are the scaling primitive for large ingestion tasks. You can't do this kind of merge in a single Claude session — the token budget alone kills you. But you can orchestrate three or four agents, each with a focused brief, each reporting back. The parent session holds the plan; the children do the heavy lifting. The parent commits the results and moves on.

Total wall-clock time for the refactor and ingestion: about four hours, most of it spent waiting for sub-agents to finish merging PDFs.


QMD, briefly

If you haven't read The Context Wall, start there. The short version: QMD is an on-device hybrid search engine for markdown knowledge bases by Tobi Lütke. BM25 full-text + vector embeddings + local LLM reranking, all running locally through node-llama-cpp with GGUF models. It exposes a Model Context Protocol server so Claude Code can query it as a first-class tool.

Install:

npm install -g @tobilu/qmd

qmd collection add content --name life-content
qmd collection add data    --name life-data

qmd context add qmd://life-content "Personal knowledge base: diary, legal, ops, finance, insights"
qmd context add qmd://life-data    "Machine-generated sources: email dumps, calendar exports, transcripts"

qmd update   # build BM25 index
qmd embed    # build vectors (downloads ~2GB of models on first run)

First qmd embed pulls about 2GB of models: an embedding model (embeddinggemma-300M), a reranker (Qwen3-Reranker-0.6B), and a query-expansion model. Subsequent runs are incremental — only new or changed chunks get re-embedded.

After the initial embed, I had 170 files indexed, 5,866 vector chunks, and 39MB of on-disk index. Queries are sub-second. Reranking with the local LLM adds another few hundred milliseconds. The whole thing runs on my laptop with Metal acceleration. No cloud, no quota, no privacy trade-offs.

Verification: I asked seven deliberately awkward questions across the new structure. Every one hit the right file. Including questions about content that had been split out of a monolith earlier in the same session — content that didn't exist as separate documents when I started.

That was the moment I knew this was going to work.


From tool to infrastructure: the daemon

Running qmd query from the command line works — but every cold start reloads 2GB of models into memory, which takes about 17 seconds. That friction destroys the workflow. You stop querying. You go back to grep. You lose the magic.

The fix is to run QMD as a persistent HTTP daemon. One process, loaded once, serving many queries. On macOS that means launchctl. I wrote a launch agent plist at ~/Library/LaunchAgents/io.qmd.daemon.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>io.qmd.daemon</string>

    <key>ProgramArguments</key>
    <array>
        <string>/opt/homebrew/bin/qmd</string>
        <string>mcp</string>
        <string>--http</string>
    </array>

    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>

    <key>StandardOutPath</key>
    <string>/tmp/qmd.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/qmd.err</string>

    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
    </dict>

    <key>ProcessType</key>
    <string>Background</string>
</dict>
</plist>

RunAtLoad means it starts when I log in. KeepAlive means it respawns if it crashes. It binds to http://localhost:8181/mcp — the MCP endpoint that Claude Code talks to.

Load it once:

launchctl load ~/Library/LaunchAgents/io.qmd.daemon.plist

From that moment forward, QMD is always running. Every session. Every reboot. Forever. I don't think about it. I don't start it. I just query.

The project's .mcp.json points at the daemon via HTTP transport:

{
  "mcpServers": {
    "qmd": {
      "type": "http",
      "url": "http://localhost:8181/mcp"
    }
  }
}

Claude Code connects to the running daemon instead of spawning its own qmd process. No cold start. Sub-second queries.

One daemon serves every project on the machine. Collections are the isolation boundary — each project adds its own collection to the running daemon, and queries can filter by collection. I'll come back to this.


Zero-maintenance indexing: the post-commit hook

QMD needs to know when files change. You could run qmd update && qmd embed manually after every edit. Nobody does that. It rots.

Better: a git post-commit hook that runs after every commit, asynchronously, silently, in the background.

#!/bin/bash
# .git/hooks/post-commit
{
  qmd update 2>&1
  qmd embed  2>&1
} >> /tmp/qmd-update.log 2>&1 &
disown || true

Three lines of actual work. Runs after every commit. Updates the BM25 index. Refreshes vector embeddings for changed files. All async, all backgrounded, commits stay fast. If something fails, it's logged and you can debug later.

The hook is installed via an idempotent setup script in the repo: ./tools/setup-qmd-hook.sh. Safe to re-run. On a new machine, you clone the repo, run the setup script, and indexing is automatic from that moment on.

Write → commit → indexed. You never think about it again.

Keeping QMD current: the update daemon

The daemon runs the binary that was on disk the moment it launched. If qmd upgrades via npm, the running process is still the old one — new features don't show up until something restarts it. Doing that by hand defeats the point of the whole setup.

So QMD gets its own scheduled updater. A second launchd agent (io.qmd.updater) fires nightly, checks npm for a new @tobilu/qmd version, installs it if there is one, and issues a launchctl kickstart on the daemon so the new binary takes over — with the models reloaded once and held hot again. All of it logged to /tmp/qmd-update.log. I never think about upgrades.

The update script is short:

#!/bin/bash
# ~/.local/bin/qmd-auto-update.sh — called by launchd nightly
set -u
LOG="/tmp/qmd-update.log"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG"; }

export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"

CURRENT="$(npm list -g --depth=0 @tobilu/qmd --json 2>/dev/null \
  | grep -o '"version": *"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"/\1/')"
LATEST="$(npm view @tobilu/qmd version 2>/dev/null)"

[ "$CURRENT" = "$LATEST" ] && { log "up to date ($CURRENT)"; exit 0; }

log "upgrading $CURRENT → $LATEST"
npm install -g "@tobilu/qmd@$LATEST" >> "$LOG" 2>&1

# Restart the daemon so it picks up the new binary
launchctl kickstart -k "gui/$(id -u)/io.qmd.daemon" >> "$LOG" 2>&1
sleep 8

# Health check
if curl -sf http://localhost:8181/health >/dev/null 2>&1; then
  log "✓ QMD $LATEST running."
else
  log "✗ daemon not responding after restart"
fi

And the launchd agent that schedules it:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>io.qmd.updater</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/Users/you/.local/bin/qmd-auto-update.sh</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>    <integer>3</integer>
        <key>Minute</key>  <integer>33</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/tmp/qmd-updater.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/qmd-updater.err</string>
</dict>
</plist>

Both the update script and the plist get installed by a single idempotent setup script (tools/setup-qmd-auto-update.sh in the repo). Running it on a new machine wires the whole thing up in one shot — alongside the daemon, the post-commit hook, and the memory symlink. Every piece of infrastructure has its own one-liner setup.

One subtlety worth naming. QMD is installed globally via npm — not via Homebrew — because it isn't on brew at all. That means Homebrew's own update cadence won't touch it, and this updater is the only thing keeping it current. If you're following along with your own setup: the updater is mandatory, not optional. Without it you'll silently fall behind, and a pinned-to-first-install QMD will drift away from the upstream improvements you're paying for in RAM.

The same pattern generalizes to any npm-global tool you depend on: one launchd agent per tool, nightly, with a post-upgrade kick of whatever daemon owns its process. It's a small stack, but it stops mattering once it's in place — which is the whole point.



The memory gotcha nobody talks about

Here's one that bit me halfway through.

Claude Code maintains persistent, file-based memory per project. Feedback rules, project notes, trigger phrases — things the AI has learned about how to work with you over time. That memory lives at ~/.claude/projects/-Users-you-path-to-repo/memory/.

Notice: that path is outside the repo. It's on one specific machine. If you clone the repo on a new laptop, the memory does not follow. Everything Claude has learned about how you prefer to work — gone.

That's a problem, and it gets worse as memory accumulates. Rules about not asking for confirmation. Rules about trust and verification. Catalogs of pending work that should surface on certain trigger phrases. All of it machine-local.

The fix is a symlink. Create .claude/memory/ inside the repo. Move the memory files there. Then replace the original ~/.claude/projects/.../memory directory with a symlink pointing at the repo copy:

ln -s /path/to/repo/.claude/memory ~/.claude/projects/<slug>/memory

Now memory is versioned with the rest of the repo. Every commit backs it up. Every push distributes it. Every clone on a new machine just needs the symlink recreated — and a ten-line setup script handles that automatically, deriving the Claude Code project slug from the repo path:

#!/bin/bash
# tools/setup-memory-link.sh — run once per new machine
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
SLUG="$(echo "$REPO" | sed 's|/|-|g')"
TARGET="$HOME/.claude/projects/$SLUG/memory"
SOURCE="$REPO/.claude/memory"

mkdir -p "$(dirname "$TARGET")"
[ -L "$TARGET" ] && { echo "already linked"; exit 0; }
[ -d "$TARGET" ] && mv "$TARGET" "$TARGET.backup.$(date +%s)"
rm -rf "$TARGET"
ln -s "$SOURCE" "$TARGET"
echo "Linked $TARGET → $SOURCE"

This is the only way to make AI memory portable across machines. Nobody tells you this. The Claude Code docs don't mention it. You discover it when you move laptops and half your agent's behavior disappears.


Natural language in, infrastructure out

The hardest thing about AI-native tools isn't the tools. It's remembering to use them. Remembering to update overview.md. Remembering to commit. Remembering to push. Remembering to cross-reference the related file. Remembering that indexing needs to happen. Remembering which area owns what kind of note.

That's all cognitive overhead. It defeats the purpose. If I have to think about infrastructure, I might as well not have it.

So I encoded the whole operational layer into the project's root CLAUDE.md under a section called Autonomous operation. Rules the AI reads on every session. The gist:

Automatic behaviors (no permission needed)

  • Distribute new content to the right file based on the routing table
  • Update overview.md when the area's structure changes (new file, renamed file, moved file)
  • Keep cross-references consistent when anything is renamed or moved
  • Commit after every meaningful change, using <area>: <action> format
  • Push to main immediately after committing (never batch unless explicitly asked)
  • Use mcp__qmd__query for cross-file search, not grep
  • Watch for files growing past ~500 lines with clear sub-sections → propose or execute splits
  • Watch for stale rules in CLAUDE.md (references to deleted files, old paths, outdated workflows) → fix immediately
  • Preserve voice matching existing content in the area

Only pause to ask for

  • Destructive operations (force-push, resets, deletions of files the AI didn't create)
  • Cross-area reorganizations affecting more than 5 files
  • Creating new top-level areas under content/
  • Anything touching read-only source folders (in my case: the Google Drive folder)
  • Anything sending external communication — email, publishing, social posts

How to report back

  • No preamble. No shall I. No I'll do that now.
  • Lead with what changed.
  • One sentence is often enough.

Example flows. I speak in italic, Claude executes what follows.

"Here's my diary for today — I went to a bookstore, I found a book I'd forgotten I wanted, and I had a quiet moment where I realized I'm doing this right."

Claude writes content/diary/YYYY/MM/YYYY-MM-DD.md, commits (diary: add YYYY-MM-DD entry), pushes. Reports: Added diary entry. Pushed.

"Wallet update: X BTC, Y USD, Z in local currency."

Claude creates content/finance/snapshots/YYYY-MM-DD.md from the template, updates content/finance/wallets.md, computes the delta from the previous snapshot, reports net worth change and implied spending. Commits. Pushes.

"What did we decide about that thing last month?"

Claude queries QMD, reads the relevant chunks, answers with citations. No commit — it's a read.

I talk in complete English sentences. Claude handles the filesystem, the git, the routing, the cross-references, and the indexing. No where should this go, no shall I commit. Just the work, done, reported.

The cognitive shift is hard to overstate. I stopped thinking about the infrastructure entirely. My brain is free to think about the content. Which, of course, was the entire point.


What this actually does, day to day

Some examples, generalized.

Journaling. I speak an entry, Claude files it under the right date, commits, indexes. Later I query what was that thing I wrote about that specific pattern and get the exact paragraph. An old entry about the same feeling surfaces alongside it. I see the pattern.

Finance. I say my wallet balances. Claude writes a dated snapshot, updates the current-state file, computes delta from the last snapshot, reports net worth change and implied spending. No bookkeeping app. No spreadsheet. Just sentences. The history is perfect. The analysis is automatic.

Domain operations. External data sources (emails, calendar events, meeting transcripts, third-party PDFs) are pulled in by tool scripts and land in data/. Knowledge summaries land in content/<area>/. The daily state — what's pending, who owes what, what needs to happen next — lives in one file per area. Reports are generated on demand and shared to the relevant people.

Blog. I speak a post idea. Claude drafts it in the voice of previous posts. I review, iterate, approve. Claude publishes via the Ghost Admin API, generates the featured image, adds the cross-links to related posts, logs the publish in the marketing log, writes a social post for LinkedIn and X, copies it to the clipboard. This post you're reading right now was produced exactly this way.

Invoicing. Generate my monthly invoice for last month. Claude reads the billing config, computes working days and overtime, generates the PDF from the HTML template, saves it, copies it to the desktop. If I said with these days off, those are subtracted. The invoice number increments automatically.

Task management. I use Things 3. Claude reads its SQLite database (read-only; writes go via AppleScript), snapshots the state, analyzes it against my own Things 3 principles, and produces a health report. I get a score. I fix what's broken. I commit the state.

Meeting notes. Meetings get transcribed automatically. The transcripts land in data/. When I say new meeting notes, Claude pulls them, parses, extracts action items, routes them to the right area (a work decision goes to work, a family commitment goes to household, a research moment goes to a project plan), commits, and indexes.

All of it is queryable from any future session. That's the key. Every line of content I write, everywhere in the repo, is indexed within seconds of committing. Later, I can ask the AI anything about anything. Perfect recall. Instant.


Scaling to multiple projects

Here's a subtlety: one QMD daemon serves all of them.

For a new project that wants to join this setup — a codebase, another knowledge base, a research archive — the onboarding is two commands:

qmd collection add /path/to/new/project --name project-name
qmd context add qmd://project-name "Short description so the AI knows what's in there"

Then copy the .mcp.json block into the new project and you're done. Same daemon. Same models loaded once in memory. Same post-commit hook pattern. Same memory symlink pattern if the new project has its own Claude Code memory.

Why not per-project daemons? Because models cost RAM (~2GB) and cold starts cost 17 seconds. One daemon = one 2GB footprint, shared by every project on the machine. The daemon already has the models hot when you query, regardless of which project you're in.

Queries can be filtered by collection name when you need isolation (qmd query "..." -c project-name). Or left unfiltered when you want cross-project search — which turns out to be surprisingly useful. I sometimes want to find a pattern that spans my life repo and my work repo, and the unfiltered daemon finds it.

This article is, among other things, the onboarding guide for every future project I integrate with this infrastructure. Point Claude Code at this post on a new project, and it knows: here's the daemon, here's the launchd plist, here's the hook, here's the memory pattern, here's how to add a collection, here's what to expect. Five minutes of setup instead of five hours.


Lessons learned, condensed

  • Split by semantics, not by size. Size is the symptom. A 6,000-line file with clear sections is fine to split at the section boundaries. A 6,000-line file with no structure means you don't understand the knowledge yet — fix that first.
  • Separate content from data. Curated knowledge in content/. Machine-generated dumps in data/. Mixing them blurs the question who's allowed to edit this, which turns out to be the question you ask most often once tool scripts start writing back.
  • Always-loaded overview.md beats every other prompt trick. A 200-line overview file gives the AI the big picture for the area before it touches anything. Everything else is retrieved on demand.
  • Sub-agents for heavy ingestion. One parent session with a plan, multiple child agents with focused briefs, each reporting back. That's how you process hundreds of Drive files without destroying your context window.
  • Launchd for services, not cron. You want it running always, restarting on crash, surviving reboots, logging cleanly. Launchd does all of that with a 30-line plist. Don't bolt it together with cron and tmux.
  • HTTP transport for MCP servers that own models. Stdio works, but stdio means cold start per session. HTTP means one process, hot models, sub-second queries.
  • Post-commit hooks for anything that should happen after every commit. Commit-and-forget beats remember-and-run every time.
  • Symlink your AI's memory into the repo. It's the only way to make it portable across machines.
  • Commit atomically, push immediately. Each logical change equals one commit. Don't batch unrelated changes. Don't sit on uncommitted work. The discipline is what makes the auto-reindex work.
  • Let the AI evolve the rules. Every correction you make, every validation you give, gets encoded into a CLAUDE.md rule or a memory entry. The system learns you over time.

The bigger picture: the AI-augmented life

This isn't really a post about Claude Code or QMD or markdown or launchd. Those are implementation details. The post is about what happens to a human when their memory stops being lossy.

Your biological memory is atrocious. You know this. You forget names, dates, promises, decisions, reasoning, context, the exact words someone said that felt important at the time. You forget what you learned last year because you didn't write it down, and when you did write it down you put it somewhere you couldn't find it again. Your past is not a knowledge base. It's a blur of half-remembered events and a few vivid anchors.

The augmentation I'm describing doesn't make you smarter in real time. It makes you continuous. It means every decision you've made is still available. The mistakes you almost-learned-from actually become lessons, because they're queryable next time. The patterns that connect your past self to your present self become visible, because they're in the same searchable index.

And — the part that's hard to describe until you feel it — you start trusting the system enough to write more. When you know every line you write will be found again, perfectly, the moment it's relevant, you stop self-censoring. You stop asking is this worth writing down?. You write everything. The knowledge base gets richer. The patterns get sharper. The AI's advice gets more relevant.

The compounding effect is the whole game. This isn't a one-time setup that gives you a feature. It's an ongoing discipline that makes every day slightly better than the last, as long as you keep writing.

The interface to all of it is plain English. You speak, the system files. You ask, the system answers. You forget nothing, because nothing is allowed to be forgotten.

I don't think of it as a tool anymore. I think of it as an extension.


Where to go from here

If you read The Context Wall and thought interesting, but my ctx.md is only 2,000 lines — start here anyway. The leverage isn't about the code project. It's about everything else.

If you've already set this up for a codebase, apply the same pattern to your notes, diary, finance, and domain projects. One daemon. Many collections. Same hook. Same memory pattern.

If you haven't thought about knowledge as infrastructure before, The Knowledge Equation is the philosophical case for why it matters. The Architect's Protocol is the workflow companion. Human Language Is the Best Programming Language is the interface argument.

And The Knowledge Base That Builds Itself was an earlier take on self-growing knowledge bases — when I wrote it, I thought growth was the hard part. With the setup in this post, growth isn't a separate concern anymore. It's just what Claude does when you talk to it. That whole article is quietly obsolete for my own use.

If you just want the technical blueprint: everything in this post is real. The launchd plist is verbatim. The post-commit hook is verbatim. The memory symlink script is verbatim. Copy them. Run them. Iterate.

Start small. Pick one area — diary, finance, meetings, anything. Put it in a repo. Give it a CLAUDE.md and an overview.md. Let it grow. Add the daemon when it's worth it. Add the hook when you get tired of typing qmd update. Add the memory symlink when you get a new laptop. The whole thing is incremental.

But the longer you wait, the more six-year-old PDFs pile up in your Google Drive. The more meetings go un-noted. The more patterns go unnoticed. The more of yourself you leave behind.

Your past is trying to help you. Most of you isn't listening because most of you can't hear it.

Build the infrastructure. Then you can.


💬
Working with a team that wants to adopt AI-native workflows at scale? I help engineering teams build this capability — workflow design, knowledge architecture, team training, and embedded engineering. → AI-Native Engineering Consulting