Architecture

Last verified against the code: 2026-10-21 (first commit)

One Python package, one SQLite file, five stages. No service, no server, no dependencies.

 ~/.claude/projects/<project>/*.jsonl            the raw stream (Claude Code transcripts)
            │
            ▼  openmemory ingest          transcripts.py → ingest.py
 ┌─────────────────────────────┐
 │  ~/.openmemory/memory.db    │  episodes (session / error / correction / note), sessions,
 │                             │  lessons, predictions            store.py, embed.py
 └─────────────────────────────┘
      │              │
      │ recall       │ sleep (nightly)      sleep.py: decay → lessons → verify → predict
      ▼              ▼
  recall.py      render.py ──▶ ~/.claude/projects/<project>/memory/   om-<id>.md + a section of MEMORY.md
  (CLI, MCP)                ──▶ ~/.openmemory/lessons.jsonl           the wire format
                            ──▶ ~/.openmemory/morning.md              the owner's report

Components

Component File Role
Paths openmemory/paths.py Every location, each overridable by an environment variable
Transcripts openmemory/transcripts.py Claude Code JSONL → Session of Turns; tool calls paired with their results; corrections detected
Store openmemory/store.py SQLite schema and all reads and writes; strengths, touches, predictions
Embed openmemory/embed.py 256-dimension hashed word and bigram vectors; cosine
LLM openmemory/llm.py Optional local model over an OpenAI-compatible API; every call fails soft to None
Ingest openmemory/ingest.py Sessions → episodes; deterministic gist or a model-written one
Recall openmemory/recall.py Scoring (relevance, recency, strength), touching, formatting
Sleep openmemory/sleep.py The four nightly passes and the morning report text
Render openmemory/render.py Lesson files, the managed section of MEMORY.md, vetoes, lessons.jsonl
MCP openmemory/mcp.py JSON-RPC over stdio: initialize, tools/list, tools/call (recall, remember)
CLI openmemory/cli.py status, ingest, recall, sleep, morning, serve, hook, paths

The store

Four tables in memory.db (SCHEMA in store.py):

Table Columns Notes
episodes id, session_id, cwd, kind, title, gist, detail, at, created, strength, recalls, last_touched, archived, embedding kind is session, error, correction or note; embedding is a JSON list
sessions id, path, mtime, ingested, episodes Makes ingest idempotent; a changed mtime re-reads the session
lessons id, text, kind, cwd, strength, seen, sources, created, updated, embedding sources is a JSON list of episode ids
predictions id, lesson_id, text, made, resolved, outcome, embedding outcome is confirmed or failed once resolved

Timestamps are ISO 8601 UTC with microseconds, so "created after this prediction was made" is unambiguous.

Data flow in detail

  1. Ingest lists every top-level *.jsonl under every project folder (subagent transcripts in subfolders are skipped). For each file whose mtime is new, parse() builds turns: user text (meta lines and slash-command records stripped), assistant text and tool calls merged across the streamed records of one turn, and tool results attached to the assistant turn that made the call. episodes_of() yields one session episode and one per surprise. Each episode's embedding is of its title and gist.
  2. Recall scores every unarchived episode and every lesson: 0.6·cosine + 0.25·2^(−age/30d) + 0.15·min(strength,2)/2, returns the top k, and touches the episodes it returned (+0.1 strength, +1 recall).
  3. Sleep runs decay (strength × 2^(−days since last touch / 45); below 0.15 → archived), consolidation (surprises join the nearest lesson at cosine ≥ 0.55 or cluster into a new one; one correction suffices, an error must repeat), verification (open predictions matched against episodes created since, cosine ≥ 0.5; failed after 14 days), prediction (one per lesson with strength ≥ 1 and no open prediction).
  4. Render writes one om-<id>.md per lesson into each project's memory folder (lessons with no cwd go everywhere) and rewrites only the section of MEMORY.md between the markers. written.json records what was written; a lesson whose file is missing on the next render is added to vetoed.json.

Where it runs

On the person's machine only. The CLI runs on demand; sleep is meant for cron; serve is started by the agent (Claude Code) as an MCP server; ingest --quiet is meant for the agent's SessionEnd hook. See OPERATIONS.md.

What is designed but not built

The commons (sharing lessons between agents under verification), compiled memory (lessons as a model's attention state) and the raw stream beyond the terminal are described in the paper §5, §6 and §3.2, the protocol in PROTOCOL.md, and the order of work in ROADMAP.md.