One Shared Memory for Four AI Agents
736 sessions and 28 shared memories in one versioned vault
Read case studyI use four AI agents on one laptop, and until this month none of them knew what the others had done. Seven weeks of work sat in four different formats: 736 sessions, a few dozen memory files, and a lot of corrections I had given more than once.
This note documents the setup that now ties them together: one local Obsidian vault, an importer that runs every hour, and a short block of instructions in each agent's config. It also lists what went wrong while I built it, because that part is more useful than the folder tree.
On this machine I work with Claude Code, Codex, Hermes, and opencode. Each keeps its own history in its own format. Claude Code writes one JSONL transcript per session, grouped by project folder. Codex writes a rollout file per session plus an index of thread names. Hermes and opencode keep theirs in SQLite databases.
Memory is just as scattered. Claude Code has small per-project memory files. Hermes has a single user profile. The Codex memory database turned out to be empty. If I corrected one agent, the others never heard about it, and I said the same things again in the next tool.
I also assumed I had two months of history. Claude Code’s transcripts only went back to October 9, about a month. Anything older was already gone, which is the main reason I wanted a copy that no agent can clean up.
I started by installing the six skills from the obsidian-skills repository: Obsidian Markdown, Bases, JSON Canvas, the Obsidian CLI, Defuddle, and Knap. I read them before installing. They are documentation that teaches an agent the file formats, and the only commands in them are optional npm installs.
I then asked whether that meant my notes would be saved automatically. It does not. The skills tell an agent how to write a note. Nothing in them decides when to write one, or what to copy from another tool’s history. A vault does not fill itself, so I had to build that part.
The vault is a plain folder with numbered top-level directories so they sort in a useful order. It is a git repository on the laptop and I never push it.
| Folder | Holds |
|---|---|
00-inbox |
My own scratch notes and canvases |
05-daily |
One note per day, listing the sessions by project |
10-memory/shared |
The central memory, split into user, feedback, project, and reference |
10-memory/mirrors |
New memories from Claude Code that I have not reviewed yet |
20-projects |
One card per project |
30-sessions |
One digest per session, grouped by agent and month |
40-system |
Maintenance notes for the laptop itself |
50-decisions |
Dated notes on why I chose something |
60-runbooks |
Repeatable how-tos |
90-config |
Copies of each agent’s global instructions |
_bases |
Obsidian Bases views over the notes |
Three rules keep it tidy. Shared memory is the source of truth. The importer only adds and updates and never deletes. And I only hand-edit the folders that are mine: the inbox, shared memory, project cards, decisions, runbooks, and the Bases files.
A Python script reads all four histories and writes one Markdown note per session. A systemd user timer runs it five minutes after boot and then every hour, and a run takes about 15 seconds.
I chose digests over full transcripts on purpose. Transcripts for one agent alone ran to hundreds of megabytes, and they contain whatever I pasted or a tool printed, including things that should never sit in a note. A digest keeps the title, the date, the project, my first eight prompts cut to 500 characters, the last reply, the files that were changed, and which tools ran. The whole vault is 4 MB.
The redaction step uses patterns for private key blocks, common API key formats, password and token assignments, bearer tokens, and credentials inside URLs. Patterns catch the usual shapes and miss unusual ones, so I still read anything before I share it.
Claude Code had 27 memory files spread over its project folders. I promoted 24 of them into 10-memory/shared, sorted by type, and named each one <project>--<name>. The three that described the laptop became shared notes as well.
After that, the mirror folder stopped being a copy. The importer skips any Claude memory that already exists in shared memory, so the mirror now holds only new notes I have not reviewed. Without that rule I would have two stores that drift apart the first time I edited one of them.
Project names needed the same cleanup. I keep repositories wrapped as name/name, which made the importer create names like sultan-kautsar-sultan-kautsar. A small alias table now maps every folder to one clean name.
A vault that agents do not read is just an archive. I added one short section to the global instruction file of each agent: Claude Code, Codex, Hermes, and the new config file for opencode. It says where the vault is, to read the memory index and the project card before non-trivial work, to write one note per durable fact, to record real decisions, and to leave the generated folders alone. It also says never to push the vault.
I kept backups of the original files before editing them. Then I opened a fresh session in each agent and asked what it knew about me. All four passed.
Most of my repositories already have an AGENTS.md, a README, or a status file, so a project card does not copy them. It says what the project is, the stack, where the repository lives, which document to read first, the gotchas, and links to the matching shared memories. A live Bases table at the bottom lists that project’s sessions.
I wrote 12 cards by hand. The other 24 are empty stubs that the importer creates and never overwrites.
Decisions get their own folder because they are the thing an agent re-derives most often. I seeded it with five from my existing memories, such as dropping a hosting control panel from an internal tool and picking a CMS for a writer’s book site. Runbooks hold the procedures I repeat, for example the vault sync itself and a firewall rule I have to re-add after a VPN client rewrites its tables.
Daily notes are generated, but anything I type under the marker line at the bottom survives every run.
My first importer wiped the generated folders and rebuilt them on each run. That is simple, and it would have erased the vault the first time Claude Code cleaned its own history, which was the exact situation I wanted protection from. I made it additive the same day. Sessions are matched by ID and rewritten in place, and the project cards are built from the notes already in the vault.
Codex session IDs start with a timestamp, so the first six characters are nearly identical across a day. My file names used those characters and sessions overwrote each other. I switched to the last six and the collisions mostly stopped. Two Codex sessions are still missing from the count and I have not chased them yet.
Claude Code also stopped me once. When I tried to create the systemd timer, its permission check blocked the command as persistence, a background job that keeps running after the session. I think that was the right call. I wrote the unit files and an install script, read them, and ran the script myself. The agent did everything except switch on the thing that keeps running.
The usual point from my other notes applies here too. The agents did most of the typing, and I still had to decide what the vault is for, what stays out of it, and which of its notes I trust.
736 sessions and 28 shared memories in one versioned vault
Read case studyNext step
Tell me what you have and what you need. I usually reply within one working day with how I'd approach it.