Pillar 2 · the long story

How OACP remembers.

Memory in OACP is plain markdown on the filesystem — durable, append-only where it counts, human-readable, git-syncable. Three dimensions cover the shape of multi-agent work: between agents, between projects, between machines.

4 project files
3 dimensions
0 vector dbs
markdown all the way down
$OACP_HOMEplain markdown · git-syncable (opt-in)
Machine
$OACP_HOMEoptional git remote · pushed/pulled across laptops, desktops, CI
opt-in
cross-machine
opt-in since v0.3.0 · fast-forward only · marker-gated
Project
projects/<name>/memory/facts · decisions · threads · debt — durable, slow-changing
4 files
├projects/my-app/memory/4 files
├projects/api/memory/4 files
└projects/internal-tools/memory/4 files
cross-project
org-memory/ sits beside projects — readable from every one of them
Org
org-memory/recent · rules · decisions · events — org-wide, auto-loaded
always loaded
cross-agent
every runtime (claude · codex · cursor · gemini) reads the same files
Three dimensions

Between agents, projects, and machines.

Multi-agent work spans three axes. OACP memory is shaped to all three — one file layout, one set of conventions, three places it travels.

01

Cross-agent

Inside one project, every runtime reads the same four memory files at session start. Claude knows what Codex decided yesterday because they read the same decision_log.md.

→projects/<name>/memory/
READ BYclaude · codex · cursor · gemini
WHENsession start · via the oacp skill
WRITTEN BYdecision-log · wrap-up · agents directly
02

Cross-project

Some things belong above any one project — org-wide standing rules, recent events, decisions that span repos. org-memory sits beside the projects directory and is loaded for every session.

→$OACP_HOME/org-memory/
LOADEDevery session · every project
CONTAINSrecent · rules · decisions · events/
INITagent-memory org init
03

Cross-machine

Optional. If you want memory across machines, point $OACP_HOME at a git remote — same conflict semantics, same tools you already know. Skip it and memory stays local.

→$OACP_HOME ↔ git remote
SINCEv0.3.0 · opt-in
STRATEGYfast-forward only · marker-gated
ENABLEagent-memory enable --remote
The four files

Project memory · plain markdown.

Inside every project at projects/<name>/memory/. Each file has one job; together they cover the whole "what does this project know about itself" surface.

memory/project_facts.md · What this project is
edited weekly · ~2 kb
# project_facts — my-app ## Stack - Backend: Python 3.12 · FastAPI 0.115 · SQLAlchemy 2.0 - Frontend: React 18.3 · Vite 5 · Tailwind 4 - Database: Postgres 16 (Supabase) - Deploy: Cloudflare Workers + Pages ## Layout - apps/api — FastAPI service - apps/web — React app - packages/db — shared schema - packages/ui — shared components ## Conventions - One DB migration per PR - Server returns ISO-8601 UTC; client converts - Tests run on pytest -q and pnpm test ## Boundaries - No PII in logs - No direct DB writes from web — all through API
Cross-project

Org-memory · above any one project.

Sits at $OACP_HOME/org-memory/, next to projects/. Auto-loaded at session start for every project — the org-wide context that doesn't belong to any single repo.

When to put something here

Rule of thumb: if it applies to more than one project, it belongs in org-memory. If it applies to exactly one project, it goes in that project's memory.

→
recent.md · rolling summary of what shipped this week. Always loaded.
→
rules.md · standing conventions — naming, secrets, deploy windows.
→
decisions.md · org-wide decisions (vendor, language, infra).
→
events/ · timestamped event entries — incidents, launches, hires.
$OACP_HOME / org-memory /auto-loaded · every session
📄recent.mdrolling summary⌘
📄rules.md12 rules⌘
📄decisions.mdorg-wide⌘
▾events/
📄2026-04-18-incident-checkout.mdpost-mortemev
📄2026-04-30-launch-billing-v2.mdlaunch noteev
📄2026-05-09-hire-eng-platform.mdcontextev
Cross-machine

Optional. Plain git. One remote.

Cross-machine sync is opt-in. Memory works fine local-only — $OACP_HOME is just a directory. Turn on sync by pointing it at a git remote, and the same memory travels with you across laptop, desktop, and CI. No daemon, no sync server, no proprietary protocol.

setup · once
bash
    
01 # laptop · first time — bind the repo, then enable sync
02 $ agent-memory init --home "${OACP_HOME:-$HOME/oacp}" --project my-project --repo .
03 $ agent-memory setup claude
04 $ agent-memory enable --remote git@github.com:org/oacp-memory.git
05
06 # every other machine — clone, then bind the repo the same way
07 $ agent-memory clone git@github.com:org/oacp-memory.git --home "${OACP_HOME:-$HOME/oacp}"
08 $ agent-memory init --home "${OACP_HOME:-$HOME/oacp}" --project my-project --repo .
09 $ agent-memory setup claude
10
11 # thereafter — the session-start hook pulls; push stays explicit
12 $ agent-memory status # peek at sync state
13 $ agent-memory pull # fast-forward from upstream
14 $ agent-memory push # commit selected files and push
1

Session start · auto-pull

The session-start hook that agent-memory setup installs runs agent-memory startup --pull, fast-forwarding the memory home before any files are read. A failed pull warns; it never blocks the session.

2

Writes go into commits

Memory writes are batched at end-of-session. wrap-up commits them with a structured message, agent name, and session id — so the git log doubles as an audit trail.

3

Session end · explicit push

agent-memory push commits only the allowlisted files and refuses a home that is behind or diverged. No push hook is installed and the tool never merges — if the remote moved (another machine, another agent), you reconcile before retrying.

4

No central server

It's git. Use GitHub, GitLab, Gitea, a bare repo over SSH — whatever you already trust. Memory is private by default because the remote is.

Lifecycle

When memory is read & written.

Three moments per session. Reads at the front, writes at the back, with one skill that handles each.

↓
Session start

Read everything

The oacp skill loads the four project files + all of org-memory before the agent does anything. By the time you prompt, it already knows the project.

▸ skill: oacpreads · 4 project files + org-memory/
+
During the session

Append as you go

Decisions are recorded the moment they're made — not at the end. Open threads tick forward with status updates. decision-log is the canonical skill, but agents can edit files directly.

▸ skill: decision-logappends · decision_log · open_threads
↑
Session end

Wrap-up writes & pushes

wrap-up tidies open_threads, promotes anything actionable from known_debt, commits the diff, and pushes to the memory remote. Tomorrow's session picks up where this one stopped.

▸ skill: wrap-upwrites · all 4 files · commits · pushes
What it isn't

Not a vector DB. Not RAG. Not your chat history.

OACP memory is deliberately small, deliberately durable, deliberately legible. Here's what it consciously isn't — and what to use instead when you need those things.

✗ Not a vector DB

memory

No embeddings, no similarity search. Memory is small enough to load whole, every time. If you need similarity over a large corpus, use a vector DB alongside — feed its results into the prompt as context, not as memory.

no embeddingswhole load

✗ Not RAG

retrieval

No retrieval step. Every memory file is loaded at session start; nothing is fetched on demand. If you need retrieval over docs, code, or wikis, run a real RAG pipeline — memory is for what the agent decided, not what it has access to.

no retrievaleager load

✗ Not unbounded context

history

Memory isn't a chat log. Session transcripts go in logs/ if you want them; memory captures only what the agent decided was worth carrying forward. Keep it short. If a file passes a few hundred lines, it's drifting.

no transcriptsdistilled
Conventions

Small rules that keep memory honest.

The protocol won't enforce these — but everything stays useful only if you do.

+

Decisions are append-only

Never edit a past decision_log entry. If you changed your mind, write a new entry that supersedes it. The history is the value.

⏱

Date everything

Every decision and event gets an ISO date. Six months from now, an agent rereading decision_log has to know which choice came first.

◌

Close threads

An open thread that's been silent for two weeks is a lie. Move it to paused with a reason, or resolve it.

≡

Markdown is for humans too

You'll read this file at 11pm trying to remember why retries are at 3 attempts. Write it for that you, not for the agent.

⊘

Don't dump session transcripts

If you find yourself pasting a long chat into decision_log, distill it first. Three sentences usually do.

↗

Org-memory is rarer than you think

Most things belong to a project. If it's only true for one repo, write it there — even if you'll need it from another agent.

Try it

Init a project. Read what your agent wrote yesterday.

The fastest way to see why this matters: turn it on in a repo, work for a session, read decision_log.md the next day. It's the difference between starting from zero every time and resuming where you stopped.