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 normalgit 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,planHomeis 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 runpan 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.
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:## 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
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.
Search
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 pullof 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.
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: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:
pan memory sync, run by hand.pan sync, before its--if-changedshortcut (skipped under--dry-runand--backup-only).- The dashboard, 60 seconds after it starts and then every 15 minutes.
pan memory add|edit|retire --user, once after each write.
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:
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: