Reference
Exact names and shapes for storage schema v5.
Node kinds
Section titled “Node kinds”Object types are project, feature, decision, gotcha, and question.
project— one per repo, created bymemory init; its title and first body sentence head the generated product map.feature— carries an optionalstageandanchors.decision,gotcha,question— title plus Markdown body.
memory save accepts node kinds feature, decision, gotcha, and
question; the project node is created by init and updated by id.
Object ids are kind.slug, matching:
^[a-z][a-z0-9_]*\.[a-z0-9][a-z0-9-]*$Examples: feature.webhook-retry-queue, decision.retries-run-in-worker.
Statuses
Section titled “Statuses”Object statuses: active, stale, superseded, open, closed.
Questions use open/closed; other kinds use active/stale/superseded.
Relation statuses: active, stale, rejected.
Stages
Section titled “Stages”Feature-only lifecycle stage: idea, building, shipped, paused, dead.
The product map groups features by stage and excludes dead features.
Relations
Section titled “Relations”Predicates: affects, depends_on, supersedes, related_to.
Optional confidence: low, medium, high.
Sidecar fields
Section titled “Sidecar fields”Each node is a JSON sidecar plus a Markdown body file. Sidecar shape:
| Field | Type | Notes |
|---|---|---|
id | string | kind.slug |
type | string | One of the five kinds |
status | string | See statuses above |
title | string | |
body_path | string | Relative path of the Markdown body |
stage | string? | Feature-only |
anchors | string[]? | Repo-relative path globs, e.g. src/billing/ |
tags | string[]? | Unique non-empty strings |
evidence | object[]? | {kind, id}, kind in memory, relation, file, commit, task, source |
source | object? | {kind, task?, commit?}, kind in agent, user, cli, mcp, system |
origin | object? | {kind, locator, captured_at?, digest?, media_type?} for external provenance |
superseded_by | string? | Set when status is superseded |
content_hash | string | SHA-256 of the body |
created_at / updated_at | string | ISO date-times |
Save input
Section titled “Save input”memory save --stdin and the save_memory MCP tool take the same intent
JSON:
{ "task": "Ship retry handling for Stripe webhooks", "nodes": [ { "id": "feature.webhook-retry-queue", "kind": "feature", "title": "Webhook retry queue", "body": "Failed Stripe webhooks re-enter a worker-owned retry queue.", "stage": "building", "anchors": ["services/billing/src/webhooks/"], "tags": ["billing"], "related": [ { "predicate": "depends_on", "to": "feature.billing-worker", "confidence": "high" } ] } ], "stale": [{ "id": "gotcha.old-retry-loop", "reason": "fixed by the new queue" }], "supersede": [ { "id": "decision.inline-retries", "superseded_by": "decision.retries-run-in-worker", "reason": "moved to worker" } ], "delete": [{ "id": "question.retry-owner", "reason": "answered" }]}Rules:
taskis required;nodes,stale,supersede, anddeleteare optional arrays.- A node with an
idthat resolves to an existing object is an update; otherwise it is a create.kind,title, andbodyare required on create. stageis feature-only.relatedentries create relations from this node.--dry-runvalidates and plans without writing. Every successful save refreshes the product map and rebuilds the index.
Config
Section titled “Config”.memory/config.json:
{ "version": 5, "project": { "id": "project.my-repo", "name": "My Repo" }, "memory": { "defaultTokenBudget": 2000, "autoIndex": true }}versionis the storage schema version. Memory refuses to operate on storage with a different version; recovery ismemory resetthenmemory init(there is no migration pre-1.0).defaultTokenBudgetis thememory querybudget when--budgetis not passed.
Storage layout
Section titled “Storage layout”.memory/ config.json # schema version, project identity, defaults memory/<slug>.json # node sidecars memory/<slug>.md # node bodies relations/<slug>.json # relations schema/ # bundled JSON schemas for validation events.jsonl # append-only event log sync-state.json # committed sync marker index/ # generated SQLite FTS index (gitignored) recovery/ # pre-overwrite backups of dirty files (gitignored) .backup/ # reset archives (gitignored)Canonical files are meant to be committed and reviewed; everything generated
is gitignored and rebuildable with memory rebuild.
Sync marker
Section titled “Sync marker”.memory/sync-state.json:
{ "version": 1, "last_sync_commit": "<git sha>" }memory sync diffs last_sync_commit..HEAD plus working-tree changes, and
advances the marker on a non-dry run. A missing or invalid marker triggers a
full anchor verification instead of failing.
Project registry
Section titled “Project registry”memory status --all, memory projects, and the viewer’s projects dashboard
read the user-level registry at $MEMORY_HOME/projects.json, defaulting to
~/.memory/projects.json. The registry stores project roots and metadata for
discovery; canonical memory stays in each project’s own .memory/ directory.
Events
Section titled “Events”Canonical events in events.jsonl: memory.created, memory.updated,
memory.marked_stale, memory.superseded, memory.deleted,
relation.created, relation.updated, relation.deleted, index.rebuilt.