Memento: agent memory I can read, edit and prune
I built my agents a long-term memory out of markdown in my Obsidian vault so I can read it, edit it and prune it myself.
I have used Claude Code almost exclusively as my agentic development tool since my first Max plan subscription in April 2025 and haven’t looked back. Previously using Cline, Roo Code, etc.. I am much more comfortable on the command line. I do use Codex and opencode for various specific cases. Multi model reviews are one of those. I’m a firm believer in the right model for the job, and having a plethora of models available via OpenRouter, OpenAI 1p and Anthropic 1p lets me leverage the best tool for each task I’m working on.
Multi model review using Claude models in conjunction with OpenAI astra or sol is invaluable in development and planning phases, bug fixes, feature development, etc. Whichever tool I’m in.. every new session starts out not knowing anything about the last.
Problem: turns out long term agent memory is a hard problem to solve for. There are many many (many) open source projects (mem0 and claude-mem are two of the bigger ones) and many many approaches that do yield great results for most users. I have tried some claude-mem techniques, and I’ve used mem0-style memory in other setups. I found recalling stale information, or not enough information, was detrimental to my processes.
Solution: I wanted something simple that I could read, edit, prune, and augment easily. I also wanted to follow the best practices outlined by Claude Code product owner Boris Cherny and use fresh sessions a lot (avoid compaction) and stick sessions to a scoped concern (I am still trying to get the hang of this).
As an Obsidian user, markdown handoff documents (full featured summaries that tee up the next session) made so much sense to me. A simple skill of /handoff (and the inverse /onboard) lets me move onto fresh context sessions quickly and easily while not losing pace. It allows me to put a project down for a few days or weeks and onboard right back to where I was in a fresh context.
I worked with Claude Opus 4.6 (my favorite Claude model to date) to build this.
How it works
All memories belong to a project, and the same project resolves to the same id on every machine by design. Memento does this with a fallback chain in compute_project_id (first match wins):
vault://<path relative to the vault> # the project lives in the vault
git://<sha12 of the origin remote url> # otherwise, a git repo
path://<sha12 of the $HOME-relative path> # otherwise, just the folder
I hash origin’s remote url, so the same repo cloned anywhere on any machine maps to the same memory file(s).
I run /handoff at the end of a session. It writes:
- a continuation doc stamped with the session end time, tees up the next session
- a short forward-looking retro: behavioral observations go to a retro log, each one hashed so repeats get recognized and promoted
- task candidates for the technical loose ends (the next /onboard offers to turn these into real tasks)
- the carry block: a structured list of what’s still open for that project, diffed against the previous carry
Note: I used to have automation via a SessionEnd hook that mined each transcript with an LLM, but I retired it in June: every run was its own claude -p on the bill, and it kept burning tokens re-synthesizing stuff it already summarized. I bagged this for a more manual approach and it works great for my workflow.
I love the carry block. My ever increasing backlog of ideas, todos, fleeting thoughts about projects I’m working on. I have to have dedicated routine reviews of this but a lot of my best ideas come during the flow where I can just say “backlog this”, or “carry this until next week” and this system helps me “remember” all of this effectively and have provenance to where that came from.the session where each idea first came up.
At session starts, a bootstrap hook reads the last 10 session files and turns them into one-liners: about 150 tokens of index in under 100 ms (file reads only, no model call). The project’s carry block gets injected right alongside it. Claude Code only keeps 10,000 characters of hook output, so the carry has to fit under that or it gets dropped. Anything deeper is a vault-search query on demand (BM25 plus semantic over the vault) and an MCP server handles ad-hoc reads.
Dream cycles and older memories fading out naturally were something I continue to evolve and leverage. Every night at 4 AM a run harvests memory files, uses Haiku to normalize relative dates (so “yesterday” becomes an actual date) and rebuilds the index. Costs about two cents. A weekly run on Sunday at 5 AM looks for patterns across sessions, about 15 cents.
This system is fantastic and it’s cross-machine, cross-environment (Obsidian Sync official handles the sync). Everything is markdown in the vault, config included: defaults first, then a shared layer in the vault, then machine-local overrides. I added memento install codex in June so Codex gets the same memory, and v0.12.0 (the carry block release) runs 628 tests.
Why it stays plain
Having tighter and easier control of context injection and keeping memory pure keeps the agent working more predictably and as a result more autonomously when needed. Durable long term memory needs to be written to locations where you can easily see the rules and edit them. Clean context is the responsibility of the human in the loop.