Nikhil Sood / Case studies

Production system case study / 11 min read

How I Built Shared Memory for Claude Code and Codex

Claude Code and Codex can work in the same repository, but their private context stores do not create a shared engineering memory. I built a provider-neutral layer that captures bounded facts, preserves provenance, retrieves them under tenant scope, and publishes only durable knowledge to a human-readable Obsidian vault.

  • 63 memories migrated with provenance
  • 62 active memories embedded locally
  • 16 evidence-derived graph relations
  • 48 shared-memory tests passing

Can Claude Code and Codex share memory?

Yes, but the safe version is a provider-neutral memory service rather than a shared transcript folder. Claude Code and Codex can query the same tenant-scoped records through MCP while Git remains authoritative and every recalled claim carries its source, branch, commit, confidence, and lifecycle state.

Without that layer, two capable coding agents can behave like two engineers who never read each other's handoff. Claude Code may discover an invariant in one session, Codex may fix a failure in another, and neither provider-native memory guarantees that the other can retrieve the result with its provenance and freshness intact.

A shared transcript folder would have been easy and wrong. Transcripts contain secrets, irrelevant conversation, unstable provider formats, and instructions that must never become authority. The requirement was narrower: preserve observable engineering facts, decisions, commands, failures, fixes, and handoffs, then make them searchable without treating historical text as executable instruction.

I split memory into three layers

The design separates truth by lifecycle. Git holds reviewed instructions, architecture decisions, policy, and the current handoff. PostgreSQL holds high-volume operational continuity such as checkpoints, source references, idempotency records, session summaries, and audit events. Obsidian holds curated knowledge that should remain useful to a person months later.

This separation prevents a common failure mode in agent memory systems: treating every remembered sentence as equally durable. A retry outcome belongs in operational memory. A stable authorization invariant belongs in Git. A reusable architecture explanation may graduate to the vault only after it is verified and sourced.

  • Git is the highest-authority, reviewable context layer.
  • PostgreSQL is the concurrent operational continuity layer.
  • Obsidian is the curated human knowledge layer, not a transcript mirror.

Capture is bounded, defensive, and asynchronous

Provider lifecycle hooks send versioned session events to one synchronization CLI. The end hook does not perform an unbounded model call or database transaction. It validates repository ownership, hashes the source, and atomically queues a metadata-only spool record. The next safe flush parses provider formats into sanitized observable events and creates conservative memory candidates.

Network failure does not lose the event. Transient errors retry with bounded exponential backoff. Permanent validation or secret-rejection failures move to quarantine instead of looping forever. Exact requests are idempotent, while a changed payload under a reused key is rejected.

Recall is scoped before it is ranked

Tenant identity comes from authenticated server context, never from a tenant ID supplied in a search request. Repository and project authorization are applied before ranking. The current deterministic baseline uses case-insensitive title and content matching plus exact source-file signals, then weights record kind, branch and task matches, confidence, status, recency, and provenance. A GIN full-text index exists in the schema, but the inspected ORM path does not yet issue a tsvector query.

The provider receives a bounded context package with an explicit warning that recalled memory is untrusted historical material. The current repository, migrations, schemas, and tests still outrank it. That boundary matters because a memory record can contain stale advice or prompt-injection text even when the storage layer itself is secure.

Concurrency required provenance and supersession

Parallel agents make last-write-wins unsafe. Each memory has a content hash, optimistic version, source agent, branch, commit, source files, confidence, and lifecycle status. Corrections supersede earlier records transactionally; they do not silently overwrite history. Stale and deleted records retain provenance and audit history.

Vault synchronization uses origin IDs and normalized hashes. If the database and the note both changed, the system creates a conflict artifact for manual resolution instead of choosing a timestamp winner. A deliberate two-sided conflict test preserved both edits and returned to an in-sync state after merge.

The verified result

The local system passed provider recall, authentication, concurrency, and vault round-trip tests. Claude and Codex both retrieved the same integration markers under the same safety boundary. The MCP surface exposed bounded search, read, write, update, supersession, relation, embedding, session, and health operations, while unauthenticated initialization returned 401.

For the graph and vector phase, 63 memories were migrated, 62 active records received 384-dimensional local MiniLM embeddings, and 16 relations were derived only from shared-source provenance. No semantic edge was invented. Polygres reported graph, vector, and hybrid retrieval ready, returned five scoped hybrid hits, and traversed a known evidence-linked path.

What I would do differently next

The first production cutover should begin with the identity gateway, not richer retrieval. Static development bearer authentication is appropriate for a local verified environment, but a multi-tenant deployment needs organizational identity, TLS, backups, retention controls, and exported service metrics before the database becomes a shared company dependency.

I would also measure memory usefulness directly. Retrieval quality is not the number of vectors stored; it is whether a cited memory changed an agent decision and remained correct. The next feedback loop should record which memories were used, rejected, or contradicted, then adjust ranking without weakening deterministic fallback.

Sources and further reading

  1. [1] Model Context Protocol transports. The provider-neutral tool boundary.
  2. [2] PostgreSQL full-text search. The deterministic retrieval baseline.
  3. [3] pgvector. Vector storage and similarity-search reference.
  4. [4] Repository architecture and verification. Implementation evidence; private or restricted repository access may be required.