Skip to main content

Project Memory

Curated memory facts are short, human-reviewable truths committed in your repository: operator corrections, working agreements, non-obvious project facts. They are repo-owned, so every managed harness (Claude Code, Codex, Pi, ACP, Kimi Code, Muse, Prime Agent) sees the same list, on every machine, after a normal git pull. This is distinct from Claude Code’s own per-machine auto-memory, which Overdeck does not read.

What a fact is

One markdown file with YAML frontmatter, named <id>.md:
type: user is valid only in the operator and machine stores (below). The id must match /^[a-z0-9][a-z0-9-]{0,79}$/. A project-store or operator-store fact whose title, description, tags, or body contains a machine-specific path (an absolute path into a home directory) is refused — see Several machines below.

Where facts live

  • Project store: <planHome>/.overdeck/memory/, one file per fact, committed on your code branch. For a single repository, planHome is the project root. For a polyrepo, it is the repository your project nominates as its plan home (pan_records.repo).
  • Operator store (--user): ~/.overdeck/context/memory/. This is where “who the operator is” facts live. It travels with you: once you run pan memory sync --setup <git-url>, it is synced across your machines (see Syncing operator memory below). It refuses home-directory paths whether or not it is synced.
  • Machine store (--machine): ~/.overdeck/context/machine-memory/, this machine only, never synced. It is the only store that accepts home-directory paths, so facts about local paths and hardware go here.
All three stores are flat directories. A README.md, a dotfile, a subdirectory, or a non-.md file is ignored, so a human README can sit alongside the facts.

How agents see them

Every managed launch injects a rendered index, right after the project layer and before the workspace section:
The operator section follows immediately with the heading ## Operator memory, and the same shape. Its source line says whether the store is synced: synced across your machines by pan memory sync, or not synced; pan memory sync --setup <git-url> shares it across machines. The machine section comes last, with the heading ## Machine memory and the source line this machine only, never synced. Nothing is stored: the index is rendered from frontmatter fresh at every launch, and a launch never touches git or the network. It is ordered by type (feedback, project, reference, user), then by updated descending, then by id. The project section is bounded at 12,000 characters, the operator section at 4,000, and the machine section at 2,000; once the budget is reached, the index stops and prints how many more facts to find with pan memory list (--user, --machine). A fact carrying a non-empty review marker is never injected — only pan memory list --review shows it. Only the index line is injected; open the fact file (pan memory show <id>) for its body. A fact added inside a workspace reaches every session’s index once its branch merges and the primary checkout pulls — not the agent’s own next session inside that same workspace.

Adding and curating facts

Writes land in your checkout; the PR is the review. add, edit, and retire write into the checkout that owns your current directory (or --project <key>’s primary checkout, --user for the operator store, or --machine for the machine store) and print the git add/git rm plus commit command to run for a project fact — Overdeck never commits a project fact for you. A --user write to a synced operator store runs one sync and prints its outcome; the fact is written even when that sync is offline. add --type user without --user or --machine is refused: user facts belong in the operator store. A fact whose text trips the secret scanner (an API key, a token: value pair) is refused with no file written; rephrase it. If .overdeck/ is gitignored in your project, add refuses with the exact line to add to .gitignore. pan memory search <query> prints matching curated facts first, under Project memory:, Operator memory: and Machine memory: headings, before the usual observation hits below them. --json output is unchanged — it is still the observation array only.

Facts vs. observation memory vs. OKF knowledge

Facts use the same frontmatter keys (type, title, description, tags) OKF’s indexer reads, so /okf author can promote a fact into the knowledge bundle by moving the file and re-casing its type.

Previewing

The dashboard’s Context page preview shows the same Project / Operator / Machine memory sections the launch composition injects, for the project the previewed layer belongs to. The preview places memory after the layers rather than before the workspace section — it is a source-labelled audit view, not a byte-identical copy of what a launch sends.

Several machines

Each store travels a different way:
  • Project facts travel through the project repository. Commit a project fact, push it, and a normal git pull of the primary checkout on another machine brings it into that machine’s next sessions.
  • Operator facts travel through your sync remote, once you set it up (next section).
  • Machine facts never travel.
Because the project and operator stores reach other machines, a fact in either can never hold a path into a home directory: it would be true only on the machine that wrote it. pan memory add/edit refuse such text with the exact match and a fix: rewrite it with ~ or a relative path, or keep it on this machine only with --machine. pan done refuses to finish an issue with an uncommitted fact still sitting in the working tree — commit it like any other change before signaling completion.

Syncing operator memory

The operator store becomes a plain git clone of a private repository you own. Create an empty private repository (Overdeck never creates it and never checks that it is private), then run the same command on each machine:
On the first machine, setup pushes your existing operator facts. On every later machine, it pulls them and merges in that machine’s own facts. Before the first commit, setup moves any operator fact that contains a home-directory path into the machine store and prints moved <id> to the machine store. If the remote cannot be reached, setup changes nothing on disk. Credentials come from your own git setup (an SSH key or a credential helper); a token inside an HTTPS URL is never printed. After setup, four things sync the store, and a launch never does:
  1. pan memory sync, run by hand.
  2. pan sync, before its --if-changed shortcut (skipped under --dry-run and --backup-only).
  3. The dashboard, 60 seconds after it starts and then every 15 minutes.
  4. pan memory add|edit|retire --user, once after each write.
Each sync commits local changes, fetches, merges origin/main, and pushes. When two machines changed the same fact, the remote version keeps the id and your version is kept as a new fact <id>-conflict-<machine> with review: [sync-conflict], so it is never injected. Both machines see both versions. Resolve it with:
An edit always beats a deletion. A changed fact whose text trips the secret scanner or contains a home-directory path is held back: it stays on this machine, uncommitted, and every sync reports it. pan memory sync --status shows the remote, the last commit, ahead/behind counts as of the last fetch, uncommitted changes, and conflict copies, without touching the network. To move an older home-path operator fact by hand: