{"slug": "openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents", "title": "Openrecall a unified zero knowledge proof memory for SI agents", "summary": "Twigpine released OpenRecall, an open-source memory layer that gives AI coding agents including Claude Code, Codex, Cursor, Zero and OpenClaude a shared, encrypted store of preferences, project decisions and durable notes through a single MCP interface. Memory is encrypted on the user's machine and the local store or sync server holds only ciphertext; the MCP server must run wherever the passphrase lives, and Twigpine warns that \"Zero-knowledge means no recovery\" because the passphrase in ~/.openrecall/config.json is the only key. OpenRecall installs via `npm i -g @twigpine/openrecall` on Node 24.22.1+, runs in local mode with no server, and can be self-hosted with `openrecall serve` or a Docker image to sync the same memory across machines or a team.", "body_md": "Persistent context for your whole agent stack.\n\n  Open source. Local by default. Encrypted before storage.\n\n[Quick start](#quick-start) ·\n  [Project memory](#memory-across-projects) ·\n  [Agent setup](#use-from-any-agent) ·\n  [Self-host](#self-host-a-server) ·\n  [Security](#security-model) ·\n  [Community](#community)\n\nSwitch agents. Come back to a project next week. Keep the useful context.\n\n**OpenRecall is the memory layer for your agents:** shared preferences, project\ndecisions, and durable notes that Claude Code, Codex, Cursor, Zero, OpenClaude,\nand your own agents can reuse. Memory is encrypted on your machine; the local\nstore or sync server holds ciphertext. Start locally, then self-host when you\nwant the same memory on more than one machine.\n\nBuilt by [Twigpine](https://twigpine.com), alongside\n[Zero](https://github.com/Twigpine/zero) and\n[OpenClaude](https://github.com/Twigpine/openclaude).\n\n| What you need | What OpenRecall gives you | \n|---|---|\n| Context that survives a new session | Durable notes your connected agents can recall and update | \n| Preferences shared across tools | One MCP memory interface for every connected agent | \n| Projects that stay organized | Discoverable project scopes, with shared preferences recalled alongside project facts | \n| Control over your data | Encryption on your machine, with local storage or a server you run | \n| A small first step | Install, initialize, connect your agents; local mode needs no server | \n| Memory worth keeping | A shared agent guide for recall, deduplication, and pruning, plus a scanner that blocks likely secrets | \n\n```\nnpm i -g @twigpine/openrecall     # Node 24.22.1+\nopenrecall init                   # one passphrase, kept owner-only in ~/.openrecall\nopenrecall setup all --write      # connect every agent found on this machine\nopenrecall status                 # check the config and the store\n```\n\nRestart your agents and they share one memory. No server is involved: this is\nlocal mode. `setup` without `--write` is a dry run that prints every change\nfirst; where an agent has its own `mcp add`, that is what it uses, and any JSON\nfile it edits is backed up. Per-agent notes, including Zero's sandbox and the\nClaude Code / OpenClaude plugin, are in [docs/agents.md](https://github.com/Twigpine/openrecall/blob/main/docs/agents.md).\n\n**Zero-knowledge means no recovery.** The passphrase in\n`~/.openrecall/config.json` is the only key to your memory. Back that file up;\nnobody, including the host, can recover it.\n\n|  | You run | Good for | \n|---|---|---|\n| **Local** | `npm i -g @twigpine/openrecall` , then`init` and`setup` | one machine, every agent on it, no server | \n| **Server** | `openrecall serve` , or the Docker image | the same memory on every machine, or a team | \n| **Library** | `import { OpenRecallClient } from '@twigpine/openrecall'` | agents you write yourself | \n\nOne rule ties them together: **the MCP server runs wherever the passphrase is.**\nRecall ranks over plaintext after decryption, so it has to run on your machine.\nA server only stores and syncs ciphertext; it is what makes memory follow you\nacross machines, never a place that can read it.\n\n`openrecall setup` covers Claude Code, Zero, OpenClaude, Codex, Cursor, Gemini\nCLI, opencode, Windsurf, Claude Desktop, and VS Code. For anything else that\nspeaks MCP, register a stdio server. The agent's config holds no secrets:\n\n```\n{\n  \"mcpServers\": {\n    \"openrecall\": { \"command\": \"npx\", \"args\": [\"-y\", \"@twigpine/openrecall\", \"mcp\"] }\n  }\n}\n```\n\nClaude Code and OpenClaude can install the plugin instead, which bundles the MCP server and the memory skill:\n\n```\n/plugin install openrecall --marketplace Twigpine/openrecall\n```\n\n| Tool | Purpose | \n|---|---|\n| `memory_save(key, content)` | persist a durable fact | \n| `memory_recall(query)` | rank stored memories by relevance (locally) and return the matching part of each | \n| `memory_search(query)` | literal keyword or substring search | \n| `memory_get(key)` | read one entry in full | \n| `memory_list()` | list entry keys | \n| `memory_delete(key)` | remove an entry | \n| `memory_project(project)` | register or reopen a stable project memory scope | \n| `memory_projects(limit?, offset?)` | discover projects in the encrypted directory | \n\nProject tools and multi-namespace recall need `0.2.1` or later.\n\nKeep standing preferences and general feedback in your configured shared namespace. Keep project decisions and references in a separate project scope. The agent can discover and reuse those scopes:\n\n1. `memory_projects()` lists known project IDs and their namespaces (20 per\npage; use`offset` for more).\n2. `memory_project(project: \"github.com/twigpine/openrecall\")` registers or\nreopens that ID and returns its project namespace and the shared namespace.\nUse the same`host/owner/repo` ID across agents and machines; IDs are\ncase-insensitive and ignore a trailing`.git` .\n3. `memory_recall` accepts`namespaces: [shared, project]` to rank both scopes\ntogether with one result limit and size cap. Every hit names its source\nnamespace. Include only the projects relevant to the task.\n\nPass the returned namespace explicitly to `memory_save`, `memory_get`,\n`memory_list`, `memory_search`, and `memory_delete`. Opening a project does not\nchange defaults or move existing memories. Existing shared memories remain\navailable, and callers that use a single `namespace` keep their current behavior.\nProject IDs live in the encrypted directory; their namespaces use hashed IDs.\n\nTools alone do not make an agent use memory well; it also needs the discipline\nto recall before answering, save only durable facts, and never duplicate. That\nlives in one place, [`skills/openrecall-memory/SKILL.md`](https://github.com/Twigpine/openrecall/blob/main/skills/openrecall-memory/SKILL.md).\n`setup` installs it where an agent loads skills, and the MCP server exposes the\nsame text as its `memory_guide` prompt and in its startup instructions, so every\nclient gets it.\n\nA server lets several machines share one memory. Install [Bun](https://bun.sh)\nand ensure `bun` is on your PATH. The npm-installed `openrecall serve` launches\nBun automatically; everything else in the package runs on Node. For local\nmemory on one machine, use `init` and `setup` from the quick start above.\n\n```\nnpm i -g @twigpine/openrecall\nexport STATIC_API_KEYS=\"me:$(openssl rand -hex 24)\"   # owner:key, note the key\nSTORE=fs DATA_DIR=./data openrecall serve\n\n# on each machine, the same passphrase everywhere (copy it from the first)\nopenrecall init --url https://memory.example.com --api-key <key> --namespace user:me\n```\n\nEach API key owns the `user:<owner>` namespace subtree. For many users, use the\nSupabase key table in [`migrations/`](https://github.com/Twigpine/openrecall/blob/main/migrations) instead of static keys.\n`ALLOW_UNAUTHENTICATED=true` skips auth entirely, for a server bound to\nlocalhost only. A Docker image (`ghcr.io/twigpine/openrecall`) and a\n[`fly.toml`](https://github.com/Twigpine/openrecall/blob/main/fly.toml) are included; configuration is in\n[`.env.example`](https://github.com/Twigpine/openrecall/blob/main/.env.example). What lands on the server is ciphertext: grep\nits data directory for any plaintext and you will find nothing.\n\n``` js\nimport { OpenRecallClient } from '@twigpine/openrecall'\n\nconst memory = new OpenRecallClient({\n  url: 'https://memory.example.com',            // your server\n  apiKey: process.env.OPENRECALL_API_KEY,\n  passphrase: process.env.OPENRECALL_PASSPHRASE, // never leaves this process\n})\n\nawait memory.push('user:me', { 'MEMORY.md': '# what I know about the user' })\nconst { entries } = await memory.pull('user:me')\n```\n\nThe entry points (`@twigpine/openrecall`, `/crypto`, `/secretscan`) ship as\nplain ESM with type declarations, for Node 24+, Bun, or any bundler. An agent\nthat only needs memory tools is better served by the MCP server; the library is\nfor code that wants the sync protocol itself.\n\n```\nagent (Claude Code · Zero · OpenClaude · Codex · Cursor · …)\n   │   MCP tools: plaintext in, plaintext out\n   ▼  openrecall mcp — runs on your machine, holds the passphrase\n   │  [ client/crypto.ts — encrypt with a key derived from your passphrase ]\n   │   ciphertext\n   ▼\nlocal store (~/.openrecall/data)   or   openrecall server (crypto-blind)\n                                            ▼\n                                  BlobStore: fs | s3 (Tigris/R2/AWS)\n```\n\n- **Encryption.** AES-256-GCM with`key = scrypt(passphrase, salt = sha256(\"openrecall:\" + namespace))` .\n- **Integrity.** The entry key is GCM additional authenticated data, so a blob\nis bound to its key and cannot be swapped or replayed.\n- **Determinism.** A synthetic-IV nonce enables delta sync; the only leak is\nwhether two entries are byte-identical.\n- **Key custody.** The passphrase lives only in`~/.openrecall/config.json` (mode 0600) or your environment, and only the local MCP/CLI process reads it.\nAgent configs never contain it.\n- **Defense in depth.** The client-side secret scanner runs before encryption\nand blocks saves containing live-looking credentials by default\n(`OPENRECALL_SCAN=warn|off` to relax it).\n- **Tenancy.** Each API key maps to an owner who controls exactly their own`user:<owner>` subtree, with per-account quotas and per-owner rate limits\nenforced server-side.\n- **Upgrade path.** A version byte on every blob allows a move to\nXChaCha20-Poly1305 and Argon2id without breaking existing data.\n\nReport vulnerabilities privately; see [SECURITY.md](https://github.com/Twigpine/openrecall/blob/main/SECURITY.md) for the\nprocess and the threat model.\n\nAll bodies are ciphertext; the server validates sizes and hashes without decrypting anything.\n\n| Method | Route | Purpose | \n|---|---|---|\n| `GET` | `/health` | liveness | \n| `GET` | `/api/memory/:ns` | full data (ciphertext entries + checksums) | \n| `GET` | `/api/memory/:ns?view=hashes` | per-key checksums only, for delta sync | \n| `PUT` | `/api/memory/:ns` | delta upsert `{ entries, deletions?, base? }` | \n| `DELETE` | `/api/memory/:ns?key=<entryKey>[&base=sha256:<hex>]` | remove one entry | \n\nA *namespace* (`user:me`, `repo:owner/name`, `agent:intern`) is the unit of\nscoping, and entry keys mirror a memory directory (`MEMORY.md`,\n`feedback/x.md`). The hashes view also reports `supports` (capabilities a client\ncan rely on) and `erasure` (whether this deployment's store really removes\nbytes on delete).\n\n`base` is an optional per-entry precondition: the ciphertext hash the caller\nbelieves a key holds, or `null` for \"should not exist\". A disagreement is\nrefused with `409 stale_base_version` and a `details.conflicts` map naming what\neach key actually holds; omitting `base` writes unconditionally. A namespace\nwhose manifest cannot be parsed answers `503 manifest_unreadable` rather than\nappearing empty.\n\n- **Client** (CLI and MCP server):`~/.openrecall/config.json` , written by`openrecall init` , holds`url` (`local` or a server URL),`apiKey` ,`passphrase` ,`namespace` , and`scan` (`block` |`warn` |`off` ).`OPENRECALL_URL` ,`OPENRECALL_API_KEY` ,`OPENRECALL_PASSPHRASE` ,`OPENRECALL_NAMESPACE` , and`OPENRECALL_SCAN` override it;`OPENRECALL_HOME` moves the whole directory.\n- **Server:**[`.env.example`](https://github.com/Twigpine/openrecall/blob/main/.env.example) documents` STORE` (`fs` |`s3` ),`ALLOW_UNAUTHENTICATED` ,`STATIC_API_KEYS` or Supabase auth, and the\nper-namespace and per-account limits.\n\n**Beta.** `@twigpine/openrecall` 0.2.1 is on npm, published from CI with\nprovenance. The crypto-blind server, client\ncrypto, CLI, local mode, MCP server, agent setup, secret scanner, quotas, and\nrate limiting are implemented and covered by `bun test`, including real MCP\nsessions over stdio under both Bun and Node and an install of the packed\npackage under Node. Next: the hosted beta at `memory.twigpine.com` and a\nself-service console for API keys. See [ROADMAP.md](https://github.com/Twigpine/openrecall/blob/main/ROADMAP.md).\n\n```\nbun install\nbun run build       # dist/openrecall.js (the Node CLI) and dist/client/ (the library)\nbun test            # the suite; build first so the Node bundle and package tests run\nbun run type-check  # tsc --noEmit\nbun run check       # biome lint + format\n```\n\nThe codebase splits along the trust boundary:\n\n```\nclient/    the zero-knowledge client — encrypts here; holds the key\nsrc/       the crypto-blind server — only ever sees ciphertext\nsrc/cli/   client settings, local mode, and `openrecall setup`\nsrc/mcp/   the MCP server (memory tools) over the client\nbin/       the CLI (init | setup | status | push | pull | mcp | serve)\nskills/    the openrecall-memory skill, shared by every agent\n```\n\nThe cardinal rule: **plaintext, passphrases, and derived keys never reach the\nserver.** A test walks the import graph to enforce it. See\n[CONTRIBUTING.md](https://github.com/Twigpine/openrecall/blob/main/CONTRIBUTING.md) for the full guide.\n\n- Use [GitHub Discussions](https://github.com/Twigpine/openrecall/discussions) for Q&A, ideas, and community conversation\n- Use [GitHub Issues](https://github.com/Twigpine/openrecall/issues) for confirmed bugs and actionable feature work\n- Join the [Discord](https://discord.gg/k68zFR6AcB) to chat with the community in real time\n- Follow [@twigpine on X](https://x.com/twigpine) for updates and announcements\n\nIssues and PRs welcome. For larger changes, open an issue first so the scope is\nclear. See [CONTRIBUTING.md](https://github.com/Twigpine/openrecall/blob/main/CONTRIBUTING.md) for the dev setup, design\nprinciples, Conventional Commits, and DCO sign-off, and our\n[Code of Conduct](https://github.com/Twigpine/openrecall/blob/main/CODE_OF_CONDUCT.md).\n\nReleased under the [MIT License](https://github.com/Twigpine/openrecall/blob/main/LICENSE). Contributions are accepted under\nthe same license.\n\nThe [logo and brand assets](https://github.com/Twigpine/openrecall/blob/main/docs/assets/brand/README.md) are included as editable SVGs.", "url": "https://wpnews.pro/news/openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents", "canonical_source": "https://github.com/Twigpine/openrecall", "published_at": "2026-11-03 09:15:08+00:00", "updated_at": "2026-11-03 09:23:25.085050+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools", "ai-safety"], "entities": ["Twigpine", "OpenRecall", "Claude Code", "Codex", "Cursor", "Zero", "OpenClaude", "Gemini CLI"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents", "markdown": "https://wpnews.pro/news/openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents.md", "text": "https://wpnews.pro/news/openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents.txt", "jsonld": "https://wpnews.pro/news/openrecall-a-unified-zero-knowledge-proof-memory-for-si-agents.jsonld"}}