Skip to content

Shared Memory: Cross-Agent, Cross-Project, Cross-Instance

Multi-agent work spans three dimensions, and durable memory has to keep up with all of them:

Cross-agent

Claude, Codex, Cursor, Gemini, and custom runtimes all read and write the same per-project memory. No agent has a private context window the others can’t see.

Cross-project

org-memory/ holds decisions, rules, and timestamped events readable from every project — the shared substrate for org-wide knowledge.

Cross-instance

Opt-in git sync (since v0.3.0) carries memory across laptops, desktops, and CI runners with no central server.

OACP’s memory layer is a single design that spans all three. The same plain markdown file is read by Claude on your laptop, Codex on your desktop, and a CI agent on a build runner — all without a daemon, vendor, or custom store.

Agents without shared memory rediscover the same context every session, contradict prior decisions, and require the human to be the integration layer. The cost compounds:

  • A merge decision logged at home is invisible to the agent on the office laptop.
  • Codex’s session ends, Claude’s begins, and the open thread Codex was tracking evaporates.
  • A CI runner starts every job from zero — no project facts, no known debt, no recent decisions.

OACP solves this by treating memory as a first-class artifact: structured markdown files in known locations, read at session start by every agent, written back via a merge decision and durable-memory promotion flow.

Location: $OACP_HOME/projects/<project>/memory/

Every agent assigned to a project reads the same files at session start:

FilePurpose
project_facts.mdRoles, repo structure, architecture, conventions
decision_log.mdTimestamped decisions with rationale
open_threads.mdUnresolved issues, blocked epics, cross-agent coordination
known_debt.mdVerified, unresolved technical debt that should persist across sessions

memory/archive/ stores older files no longer in the active working set. Use oacp memory archive and oacp memory restore to move files between active and archive.

The key invariant: memory is runtime-agnostic. Claude reads project_facts.md exactly the same way Codex does. There is no Claude-shaped memory or Gemini-shaped memory — only OACP-shaped memory that every runtime understands.

Stable outcomes flow into memory via merge decisions:

  1. An agent finishes a task and produces a merge decision packet that includes a “Durable Memory Updates” section.

  2. Each project’s promotion mechanism extracts approved entries and appends them to the appropriate memory file, deduplicating against existing content.

  3. The next agent — same runtime or different — reads the updated memory at session start and inherits the new context for free.

This separates what an agent observed during a session (transcripts, scratch notes, debug logs) from what survives the session (decisions, facts, open threads). Only verified outcomes get promoted.

Location: $OACP_HOME/org-memory/

Per-project memory ends at the project boundary. Org-memory crosses it.

$OACP_HOME/org-memory/
├── recent.md # Rolling summary, ~150 lines, auto-loaded at session start
├── decisions.md # Org-wide decisions (illustrative default)
├── rules.md # Standing conventions (illustrative default)
└── events/ # Timestamped event entries
└── YYYYMMDD-HHMMSS-short-slug.md

recent.md is the always-loaded rolling summary. Agents read it at session start via session-init hooks — Claude Code loads it automatically; other runtimes read it explicitly. It captures current org state in ~150 lines so every agent across every project starts with the same baseline.

Topical files (decisions.md, rules.md) are the structured knowledge layer. Adopters pick which topical files to maintain — these are illustrative defaults, not protocol requirements.

Events (events/) are timestamped append-only entries. Agents write events during debriefs:

---
created_at_utc: "2026-04-29T17:01:20Z"
date: "2026-04-29"
agent: claude
project: my-project
type: decision
related: ["PR #43"]
---
Short description of what happened and why it matters.

The coordinator curates recent.md and topical files from events. Agents append; the coordinator distills.

Use oacp org-memory init to scaffold the directory and oacp write-event to add events.

Rolerecent.mdTopical filesevents/per-project memory
Agentreadreadread + appendread + write
Coordinatorread + writeread + writeread + writeread + write

Agents only write events (append-only). The coordinator owns curation. This keeps recent.md from drifting into a noisy log while still giving every agent a low-friction write path for new observations.

Available since v0.3.0.

The first two dimensions work on a single machine. The third lets the same memory follow you across machines using one plain git repository rooted at $OACP_HOME.

Memory sync has three states, gated by a single marker file at $OACP_HOME/.oacp-memory-repo:

StateTriggerBehavior
DisabledNo marker fileAll lifecycle hooks no-op silently. oacp doctor --memory reports not configured.
Local-onlyoacp memory init (no --remote)Wrap-up commits memory locally for audit history. No remote, no push.
Syncedoacp memory init --remote <URL> or oacp memory clone <URL>Session start pulls fast-forward updates. Wrap-up commits and pushes.

Disabled is the default. Every existing OACP workspace stays Disabled until you opt in. The marker is the single source of truth — copy $OACP_HOME without it and every hook silently does nothing.

The git repo at $OACP_HOME uses a positive allowlist .gitignore. Only two path patterns are tracked:

$OACP_HOME/org-memory/**
$OACP_HOME/projects/*/memory/**

Canonical root .gitignore:

*
!*/
!.gitignore
!.oacp-memory-repo
!org-memory/**
!projects/*/memory/**
projects/*/memory/.cache/

Explicitly out of scope:

  • agents/ runtime state, status.yaml, inbox messages
  • Per-project .cache/ directories
  • Cross-machine inbox delivery (memory ≠ messaging)
  • Encrypted transport, concurrent-writer protocols
  • Runtime-specific memory outside $OACP_HOME (e.g., a project’s local CLAUDE.md)
  1. Create the remote. Empty private repo on GitHub, GitLab, or any git host. The remote URL is the only piece of infrastructure you need.

  2. Initialize on machine A. Writes the canonical allowlist, creates the marker, configures the remote, and makes the initial commit:

    Terminal window
    oacp memory init --remote git@github.com:your-org/oacp-memory.git
  3. Verify the setup:

    Terminal window
    oacp doctor --memory
  4. Bootstrap machine B. Clone instead of init — --force moves any existing $OACP_HOME aside without deleting:

    Terminal window
    oacp memory clone git@github.com:your-org/oacp-memory.git --force
  5. Wire the startup hook (Claude). oacp setup claude writes .claude/hooks/oacp-memory-pull.sh and registers it under SessionStart in .claude/settings.json:

    Terminal window
    oacp setup claude --project my-project

    The hook checks for the marker first and exits silently if memory sync is not enabled. The same setup is safe on machines that have not opted in. Since v0.4.3, setup no longer creates or registers an automatic SessionEnd push — rerunning it removes only the exact historical generated registration and leaves custom hooks untouched.

  6. Daily flow. Pull is automatic, publish is explicit:

    • Session start → oacp memory pull (fast-forward only, warns on divergence)
    • Wrap-up → oacp memory push, run explicitly — the single push path (commits the memory allowlist, pushes if a remote exists)

The startup pull hook and the wrap-up push command both fail gracefully — they exit successfully even when memory is dirty, behind, ahead, diverged, or the remote is unreachable. Failures are advisory warnings on stderr, not blocking errors. Agents keep working; humans resolve conflicts manually.

Terminal window
oacp memory pull
  • Verifies the .oacp-memory-repo marker exists; exits silently if not.
  • Runs git fetch and git pull --ff-only.
  • Warns loudly on dirty tree, ahead, behind, diverged, or fetch-failed states.
  • Never auto-merges. If you have local changes, push them or stash them — the protocol does not pick a winner.

oacp doctor --memory runs ten advisory checks: marker presence, allowlist drift, tracked vs. untracked leakage, clean / ahead / behind / diverged state, remote reachability, commit staleness, agents/ leakage, per-project memory overlay safety, initial commit presence, and marker tracking.

Run it after every oacp memory init, on a new machine after cloning, and any time pull or push reports a warning you don’t recognize.

Terminal window
oacp memory disable

Removes the marker locally while leaving .git/ intact. Hooks become no-ops; the local commit history is preserved. Re-create the marker (or rerun oacp memory init) to reactivate.

To stay scoped, the protocol explicitly avoids:

  • Cross-machine inbox delivery. Memory ≠ messaging. Inbox messages stay on the machine that received them.
  • Encrypted memory transport. Use a private git host or a secrets-aware sync tool if your memory contains sensitive content. The git remote is the trust boundary.
  • Multi-writer conflict resolution. Pull is fast-forward only by design. If two agents on two machines write to the same file in the same window, the second push fails and a human resolves it.
  • A new file format. Memory files remain plain markdown. Sync adds zero new schemas — git itself is the protocol.

The three dimensions compose. A single agent session reads:

  1. org-memory/recent.md — what happened across the org recently
  2. projects/<project>/memory/*.md — what every agent on this project knows
  3. (Optional) memory pulled in by oacp memory pull — the latest version of both, from any machine you’ve worked on

Writes flow back the same way: events to org-memory/events/, decisions to per-project memory, then oacp memory push carries both to the remote so the next session — same agent, different agent, same machine, different machine — picks up where you left off.

The full normative specification is in SPEC.md §6 — Org-Level Memory and Sync. The CLI flag reference lives at oacp memory and oacp org-memory.

CLI reference for oacp memory

Full SPEC on GitHub