In July I wrote about the AI second brain that runs my working life. It’s an Obsidian vault full of plain markdown files that Claude reads, updates, and finds its way around on its own. I also said it would probably look quite different a few months later.
That was three and a half months ago, and today it does indeed look different. The biggest difference is that I’ve added a database. Here’s why, and how.
Where we started
My vault has four layers. Raw inputs that never change, a wiki that the AI writes and keeps current, a small set of rules and reference files that I write myself, and the actual work. Every project has a state file that says what is true right now. An always-on Mac Mini (I call it the AI Shed) runs scheduled jobs that go through my email and Slack every day and file what matters into the wiki.
It works well. But it’s a library of documents, and that has limits. If I ask it something a document can answer, like our position on pricing for a client, it’s excellent. If I ask it something that needs counting or sorting, or an answer I can rely on being complete, it gets shaky and even more so as my document count is entering the thousands.
Why a database
For a while now I had a gut feeling that markdown alone wasn’t enough.
My reasons were the usual ones. A database keeps data in shape. A date field only accepts a date, and you can’t enter the same person twice. The frontmatter at the top of a markdown file has rules too, but nothing enforces them. I also wanted to look back in time without digging through git, and I assumed a database would be faster to search.
Claude disagreed with the last point. With a few thousand files, searching takes milliseconds, so speed isn’t the issue. But completeness is. A question like “which deals have a follow-up due this week?” has one right answer. An AI agent reading through hundreds of files will give you an answer that sounds right and may leave some out, which was happening more and more often as my docs increased in number.
A daily log only records what an agent thought was worth writing down. A database doesn’t have this problem.
I came away with three decisions.
The first was a rule simple enough for an agent to follow when it files something. If it came from outside, like an email, a transcript, or a meeting, it’s a fact and it goes in the database. If we (either the agent or I) wrote it, it’s context and it goes in markdown.
The second was dropping my idea of keeping a full history of everything. The vault already writes a daily file with a summary of each day’s work. So the database holds what’s true now, the daily files hold what happened when, and the markdown pages hold what it all means.
The third was a surprise at first. Most of the facts I’d want to look up exactly are about people. Who works where, when I last spoke to them, who introduced us. Projects, ideas, and opinions are mostly things I read about rather than look up. So I didn’t need a database for my whole life, only a good one for people and companies.
I’d heard HubSpot co-founder Dharmesh Shah talk on a podcast about YouSpot, a personal CRM he built for one person, and it pointed the same way.
How it fits together
There are four tables:
- People: name, every spelling and email address they use, and where they work.
- Companies: name and web domain.
- Interactions: who, when, how (an email or a meeting), and a link back to the original.
- Introductions: who introduced whom, and when.
The database runs on Cloudflare D1, which is SQLite hosted in the cloud. I first wanted to keep it on the Mac Mini, but my laptop needs it too, and a SQLite file that syncs between two machines will get corrupted sooner or later. In front of the database sits a small Cloudflare Worker that rejects any request without the correct key. The Worker also speaks MCP, the standard Claude uses to call tools, so Claude Code on either machine can ask “who do we know at this company?” or “what did we last talk about with this person?” and get a truthful answer.
Email is where the database learns things the wiki doesn’t know. A script reads the headers of my mailboxes through Gmail’s API, using a permission that covers headers and labels but not the body of any message. It checks every address against the people already in the database and records the contact. My calendars work the same way: past meetings, with the attendees and the title.
I made two choices for privacy. Subject lines and meeting titles are only stored for people already in the database, so emails with my doctor or my family never end up in the cloud. And when I’ve written to someone who isn’t in the database, their address goes on a review list without a subject line. That list shows me who’s missing.
Every night at 5:15am the Mac Mini refreshes everything: first the people from the wiki, then the day’s new email headers, then the meetings. It’s done well before my morning briefing arrives at 6:30.
What it does now
A few days in, the database holds 435 people, 331 companies, and 7,561 emails and meetings.
My morning briefing now has a section called “Going cold.” It lists open deals with no follow-up planned, and investors, partners, and advisors I haven’t emailed or met in 30 to 180 days.
The first version of that list was missing most of my deals. Of 171 live deals, 113 didn’t show up, because the contact’s name lived only in a line of the deal record and never got a page of its own in the wiki. The database couldn’t see them. The fix was a rule: every person named on a deal gets a wiki page, with their email address as it appears in my inbox. The agents that log my deals now create those pages as they file.
What I’d tell you
Keep the database small. Mine holds people, companies, and who talked to whom. Anything that needs judgment stays in plain text, where both I and the AI can read it.
And make sure the facts arrive on their own. If I had to type things into this database, I’d have stopped within a month. Instead my inbox fills it every night, and for the first time the vault knows things I never told it.