{"id":486,"date":"2026-06-06T04:10:08","date_gmt":"2026-06-06T04:10:08","guid":{"rendered":"https:\/\/nazeem.me\/?p=486"},"modified":"2026-06-06T04:10:08","modified_gmt":"2026-06-06T04:10:08","slug":"two-brains-for-my-ai-how-obsidian-and-trilium-split-the-work","status":"publish","type":"post","link":"https:\/\/nazeem.me\/?p=486","title":{"rendered":"Two Brains for My AI: How Obsidian and Trilium Split the Work"},"content":{"rendered":"<p>I&#x27;ve spent the last few months tinkering with a local AI stack on my desktop \u2014 Ollama for local inference, Hermes orchestrating the whole thing, and a Claude subscription for the heavy lifting. It works. But there was always one nagging gap I kept dancing around: where does the AI&#x27;s <em>memory<\/em> actually live?<\/p>\n<p>For a while I went back and forth on whether to use Obsidian or Trilium as the knowledge store. I tried picking one. I tried picking the other. And then it finally clicked that I was asking the wrong question. They&#x27;re not competitors. They do genuinely different jobs, and once I let them do those different jobs, the architecture got <em>simpler<\/em>, not more complicated.<\/p>\n<p>So here&#x27;s where I landed.<\/p>\n<hr \/>\n<h2>The Realisation: Two Kinds of Memory<\/h2>\n<p>The thing nobody tells you about &quot;AI memory&quot; is that it&#x27;s actually two separate problems wearing one coat:<\/p>\n<ol>\n<li><strong>Reference knowledge<\/strong> \u2014 the curated, stable stuff. Things I&#x27;ve written down deliberately and want to keep. This is read-mostly. The AI pulls from it, but it shouldn&#x27;t be scribbling all over it.<\/li>\n<li><strong>Working memory<\/strong> \u2014 the daily log. Decisions, scratch notes, &quot;remember I changed X today.&quot; This is high-frequency, messy, and constantly being written to by both me <em>and<\/em> the AI.<\/li>\n<\/ol>\n<p>The moment I framed it that way, the tool choice answered itself. I already use both apps for exactly these two purposes, so I&#x27;d been overthinking it.<\/p>\n<ul>\n<li><strong>Obsidian<\/strong> holds my <code>.md<\/code> files \u2014 my curated reference library. Plain markdown on disk, portable, mine forever.<\/li>\n<li><strong>Trilium<\/strong> is where I dump my daily notes. It&#x27;s a proper database with an API, which turns out to matter a lot for the working-memory job.<\/li>\n<\/ul>\n<p>One is the library. The other is the journal. Don&#x27;t make the library be the journal.<\/p>\n<hr \/>\n<h2>Why The Split Plays To Each App&#x27;s Strengths<\/h2>\n<p>This isn&#x27;t arbitrary. Each app is <em>built<\/em> for the role I&#x27;m giving it.<\/p>\n<p>Obsidian being plain markdown means anything can read it \u2014 Claude Code just <code>cd<\/code>s into the folder, and an in-vault RAG plugin like Smart Connections does local semantic search through Ollama without phoning anywhere. Brilliant for retrieval. But writing back to markdown with an automated agent is fragile \u2014 no schema, no permissions, and with files syncing around my network, I&#x27;m one race condition away from a merge headache. So I don&#x27;t let the AI write here. If it produces something worth keeping, <em>I<\/em> promote it by hand.<\/p>\n<p>Trilium is the opposite shape. It&#x27;s a database behind an API (ETAPI), with native MCP support and proper permission control \u2014 read-only or read\/write, my choice. That makes the agent-writes-back loop actually reliable. Dated entries, structured attributes, an interface Hermes and Claude can both hit cleanly. Exactly what you want for a journal the AI helps maintain.<\/p>\n<p>So: Obsidian gets read-only treatment because it&#x27;s my canon. Trilium gets read\/write because it&#x27;s the working log and it&#x27;s structurally built to handle it.<\/p>\n<hr \/>\n<h2>The Architecture<\/h2>\n<p>Here&#x27;s the whole thing on one diagram:<\/p>\n<pre><code>   Obsidian Vault (.md)              Trilium (daily notes \/ DB)\n   reference knowledge               working memory + journal\n        \u2502                                   \u2502\n        \u2502 READ-mostly                       \u2502 READ + WRITE\n        \u25bc                                   \u25bc\n   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n   \u2502 Smart Conn. \u2502                   \u2502 Built-in AI  \u2502\n   \u2502 + Ollama    \u2502                   \u2502 + ETAPI\/MCP  \u2502\n   \u2502 Claude Code \u2502                   \u2502              \u2502\n   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518                   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n          \u2502                                 \u2502\n          \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba Hermes \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                  (orchestrator: routes\n                   reads vs writes)\n                          \u2502\n                  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n                  \u25bc               \u25bc\n               Ollama          Claude\n            (local worker)   (escalation)<\/code><\/pre>\n<p>The key shift here is that Hermes stops being <em>just<\/em> an orchestrator and becomes a <strong>router<\/strong>. It knows where each operation belongs. The rule set is almost embarrassingly simple:<\/p>\n<ul>\n<li><strong>Reads<\/strong> hit both stores \u2014 reference from Obsidian, recent context from Trilium.<\/li>\n<li><strong>Writes<\/strong> go to Trilium only, scoped to the daily-notes subtree.<\/li>\n<li><strong>Obsidian writes<\/strong> are human-gated. Always.<\/li>\n<\/ul>\n<p>Underneath both, the same two-tier model I&#x27;ve been running all along: Ollama does the routine local work (free, private, fast), and Claude gets the escalation \u2014 the complex reasoning and long-context synthesis that the local models can&#x27;t touch.<\/p>\n<hr \/>\n<h2>The Flow That Makes It Worth The Effort<\/h2>\n<p>Running two apps only pays off because of how they feed each other:<\/p>\n<ol>\n<li><strong>Capture.<\/strong> Daily stuff \u2014 decisions, meeting notes, half-formed ideas \u2014 gets written to Trilium. By me, or by the agent.<\/li>\n<li><strong>Retrieve.<\/strong> When I ask a question, Hermes pulls reference context from Obsidian <em>and<\/em> recent working memory from Trilium, then stitches them into the prompt. Recent Trilium entries first (what&#x27;s top of mind), then Obsidian reference matches (the background), then my actual question. Keeps the prompt focused and stops it bloating past the context window.<\/li>\n<li><strong>Promote.<\/strong> Every so often, the good stuff from the Trilium daily log graduates into a proper Obsidian <code>.md<\/code> note. The journal is ephemeral; the library is forever. This step is manual on purpose \u2014 it&#x27;s the quality gate that keeps my curated vault clean.<\/li>\n<\/ol>\n<p>That promotion step is genuinely the whole point. Trilium absorbs all the messy, high-frequency writes \u2014 which protects my Obsidian vault from being cluttered up by an over-eager agent \u2014 and only vetted, distilled knowledge ever crosses the line into the library.<\/p>\n<hr \/>\n<h2>A Couple Of Guardrails<\/h2>\n<p>Because I don&#x27;t trust <em>anything<\/em> with write access until it&#x27;s earned it:<\/p>\n<ul>\n<li><strong>Trilium&#x27;s AI features are still experimental,<\/strong> so I started the MCP connection and Hermes both at <strong>read-only<\/strong>, and only promoted to read\/write once I&#x27;d watched them behave for a while.<\/li>\n<li><strong>The agent writes into a dedicated subtree<\/strong> \u2014 an <code>AI Memory<\/code> parent note \u2014 rather than scattering machine-written content through my real notes. Keeps it quarantined, easy to audit, trivial to roll back if it goes sideways.<\/li>\n<\/ul>\n<hr \/>\n<h2>Where This Leaves Me<\/h2>\n<p>No separate vector database, no extra infrastructure to babysit. Obsidian&#x27;s RAG handles reference retrieval, Trilium&#x27;s ETAPI handles dated working memory, and each app does the one thing it&#x27;s actually good at. Hermes routes between them, Ollama does the grunt work, Claude handles the hard problems.<\/p>\n<p>The lesson, as usual, was that I&#x27;d been overcomplicating it. The answer wasn&#x27;t a clever tool or a new piece of kit \u2014 it was just letting two tools I already used keep doing their jobs, and being disciplined about which one the AI is allowed to write to.<\/p>\n<p>If you&#x27;ve made it this far: yes, I really did spend an unreasonable amount of time deciding where a chatbot is allowed to save its notes. Worth it though.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#x27;ve spent the last few months tinkering with a local AI stack on my desktop \u2014 Ollama for local inference, Hermes orchestrating the whole thing, and a Claude subscription for the heavy lifting. It works. But there was always one nagging gap I kept dancing around: where does the AI&#x27;s memory actually live? For a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ai_generated_summary":"","wpai_meta_description":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-486","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/posts\/486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nazeem.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=486"}],"version-history":[{"count":1,"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/posts\/486\/revisions"}],"predecessor-version":[{"id":487,"href":"https:\/\/nazeem.me\/index.php?rest_route=\/wp\/v2\/posts\/486\/revisions\/487"}],"wp:attachment":[{"href":"https:\/\/nazeem.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nazeem.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nazeem.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}