Build a Local, Bitemporal Memory System for Claude Projects
I built a local memory system for Claude that is a bit different from others I have seen. The reason was familiar: repeated context loss and gaps, even within projects. I am not technical—I come from a healthcare background—so it was essentially vibe-coded, but I used a method I had not seen elsewhere. I started by interviewing Claude about what would be useful to it, rather than beginning with only what I wanted. The three biggest gaps were the rationale behind decisions, current versus historical states, and the difference between global and project-level detail. We also identified ways memory can go wrong, including stale facts being confidently asserted as truth and rejected ideas resurfacing. Claude’s built-in memory stores flat topics without entity links, captures what but not why, is not well temporally grounded, and is gated by Claude. I researched other memory builds, from homebrew systems to enterprise tools, and found that they generally fell into three groups: - Vector dumps, which lack rationale and supersession and can become stale - Plain Markdown with grep or embeddings, such as Basic Memory, which similarly lacks real temporal grounding and an entity graph - Heavyweight knowledge-graph stacks such as Neo4j, LangChain, and GraphRAG None of these did what I wanted. My store holds entities only, not transcripts. It stores decisions, observations, people, and projects connected by typed edges. Each entry has content, a scope—either portfolio-worthy or working detail for one project—a rationale, and information about where it came from. The system is also bitemporal, so it distinguishes what is current from what is not. Nothing is edited in place: a correction adds a new assertion instead of overwriting the old one. Underneath, it uses SQLite, with sqlite-vec for semantic search and FTS5 for keyword search. Nothing writes automatically. Claude has to propose a memory, and I have to approve it. This prevents the store from filling with noise, keeps it token-efficient, and acts as a governance lever. MCP links Claude to my server. It is local-only at present, although there is potential to add remote access in the future. The server provides instructions for making proposals, so the system is theoretically portable, and I also created a Claude skill to accompany it. I ran the build across multiple projects and created specialist projects for different roles: - A central development and oversight project served as the decision-maker and prompt-writer. - Cowork handled the building and tested each module inside a sandbox. It had no authority to change decisions, and I used a fresh project for each stage of the build. - I handled deployment separately by typing every command on the server and pasting the output back. - I repeated Claude’s Cowork-authored tests on the actual server. Real-world testing after deployment identified only minor issues, which were quick to fix. This separation was administratively heavy because I had to keep switching between projects as tasks started and finished, but it caught several errors in the rules and code. Despite my lack of technical knowledge, the project is now well documented and I have room to develop it further. I may eventually put it on GitHub. It has become a standard component of my workflows, my projects are tracked much better, and Claude and I are on the same page more often.
0 comments