open-memex
This server gives AI agents persistent, local, Markdown-based memory — capturing facts across sessions and sharing them between editors on the same machine.
Save memories (
memory_add): store facts, preferences, decisions, constraints, gotchas, and more — scoped to the current project or personal (machine-only), with tags, type, and up to 4 aliases.Search memories (
memory_search): BM25 keyword search across project and/or personal scopes, filterable by type and limit; reviewed memories rank first.Browse memories (
memory_list): list memories newest-first as a numbered inventory per scope, with an audit view (include=all) that shows superseded, retracted, and archived entries.Update facts (
memory_supersede): replace an outdated memory with a corrected version while keeping the old one as auditable history.Delete or hide memories (
memory_forget): permanently delete by id, or soft-retract to hide it from lists and search.Review the sync queue (
memory_status): see outbox drafts, in-repo review states, and uncommitted memory files.Share through Git (
memory_submit,memory_propose,memory_promote): move drafts into the repo as proposed, copy personal memories into project review, and advance proposed → approved → published (or reject/resubmit) with recorded review history.Handle merge conflicts (
memory_resolve): list conflicted memory files or perform a field-level 3-way merge without auto-resolving semantic conflicts.Map PR state (
memory_pr_status): read the branch's GitHub PR and translate merged/approved/changes-requested into memory review states, optionally applying them locally.
open-memex
Persistent memory for your AI coding agents — on your machine, in plain Markdown, shared by every tool you code with.
Every AI coding session starts from zero: you re-explain the project, the agent rediscovers the same gotchas, and yesterday's decisions vanish when the chat ends. open-memex gives your agents a memory that survives the session. Say "remember: we deploy on Fridays" once, and next week Copilot, Cursor, opencode, or Claude Code already knows — because they all read and write the same local memory on your machine.
Free and open source (Apache-2.0). No account, no cloud, no telemetry — everything lives on your machine, in files you can open and edit.
Local-first: memories are plain Markdown files (the source of truth) with a rebuildable SQLite keyword index. Nothing leaves your machine unless you explicitly share it.
One memory, every agent: wire up several editors with one command; they share the same memory instead of keeping separate silos.
Precise synonym search:
shipfindsdeploy,单点登录findsSSO— a curated multilingual map of equivalents is indexed with every memory at write time, so no related wording misses the right answer. Deterministic and auditable, no embedding model required.
New here? This README takes you from install to a working memory in about a minute. The concept guide explains the mental model in depth once you're up and running.
Contents
Related MCP server: agent-memory
Quick start
You need Node.js ≥ 22.14 (check with node -v). Then:
npm install -g open-memex
open-memex initinit detects the editors you have installed (VS Code, Cursor, opencode, and
Visual Studio when your project has a solution file) and connects each one to
open-memex. Restart your editor afterwards.
See it work (30 seconds):
open-memex add "This project deploys on Fridays"Now open a new chat in your editor and ask your agent: "When does this project deploy?" It already knows — no re-explaining. That round trip, capture once and recall forever, is the whole product. Everything below is detail.
Optional but recommended — check everything is wired up:
open-memex doctorCore concepts
Four ideas explain almost everything open-memex does.

1. Two scopes: project and personal.
Every memory belongs to one of two places:
project — knowledge about one codebase (decisions, constraints, lessons). Scoped to the current repo automatically; you never set this up by hand.
personal — knowledge about you (preferences, habits) that applies in every project. It lives only on this machine and can never be shared into a repo.
Facts about you ("I prefer concise diffs") go to personal; everything else
defaults to the current project.
2. Capture → recall. Memories are saved as small Markdown files, one fact each. On the first turn of every new session, open-memex hands your agent the most relevant ones automatically, so it starts the session already knowing them. The agent can also search the full memory on demand. You never have to "load" anything yourself.
3. Your files, your rules.
The Markdown files are the source of truth — open them, edit them, delete them,
grep them. The SQLite index next to them is just a search accelerator and
rebuilds from the files at any time (open-memex reindex). Team sharing, when
you want it, goes through the same review flow as code: nothing is shared
automatically (see Team workflow).
4. Knowledge stays current.
Facts change: decisions get reversed, tools get replaced, yesterday's gotcha
gets fixed. open-memex doesn't let the old version quietly linger —
memory_supersede replaces a memory with its newer version and keeps the
chain, so retrieval serves the current fact while the history stays auditable.
Merely stale memories can be deprecated, and open-memex audit reports
duplicates, stale entries, and broken chains. Pruning is a feature, not
housekeeping: shared memory rots without it.
Which editors, which features
open-memex talks to editors two ways: a native opencode plugin, and a
standard MCP server that any MCP-capable editor can use. (MCP — Model
Context Protocol — is the open standard editors use to give agents extra tools;
open-memex appears in your editor as a set of memory_* tools.) What you get
depends on which path an editor uses:
Editor | Setup | Tools | Session-start recall | Keyword auto-capture |
opencode (native plugin, recommended) |
| 5 core tools | Built in — first turn of every session | Yes — |
VS Code (Copilot) |
| All 11 via MCP | Via MCP guidance* | No — the agent saves when you ask |
Cursor |
| All 11 via MCP | Via MCP guidance* | No — the agent saves when you ask |
Claude Code |
| All 11 via MCP | Via MCP guidance* | No — the agent saves when you ask |
Visual Studio 2022 17.14+ / 2026 |
| All 11 via MCP | Via MCP guidance* | No — the agent saves when you ask |
Codex and other MCP clients |
| All 11 via MCP | Via MCP guidance* | No — the agent saves when you ask |
* MCP has no hard session-start hook, so open-memex sends the agent guidance in
the MCP handshake (including how many drafts are waiting) and init writes the
fuller version into the editor's instruction files. In practice agents follow
it; the opencode plugin is the only path with true built-in first-turn
injection. The Tools section lists the 5 core tools
and the 6 extra workflow tools, so the "5 vs 11" split is explicit.
All editors on the same machine read and write the same memory — a constraint captured in VS Code is respected in opencode; a lesson learned in Cursor shows up in Claude Code. (Different machines do not sync automatically; see the FAQ.)
init also installs an Agent Skill (a short instruction file that teaches
skill-aware agents to use the CLI) for VS Code and Cursor, and for opencode in
per-project MCP mode. With the opencode native plugin wired, no skill is
installed there — the plugin already provides the memory tools, and a second
instruction set only made agents chatty.
How it compares
open-memex | Instruction files ( | Cloud memory services | Chat history | |
Where it lives | Your machine + your repos | In the repo | Vendor servers | Gone when the chat ends |
Who maintains it | Captured as you work; you review | You write and update by hand | The service | — |
When facts change | Superseded, not silently stale — retrieval serves the current version, chain preserved | You hand-edit; stale copies linger | Varies; often silently stale | — |
Works across AI tools | Yes — any MCP client (same machine) | One file per tool convention | Per-integration | No |
Review before sharing | Yes — outbox + pull request | Yes — it's just files | Varies | No |
Human-readable | Plain Markdown files | Yes | Dashboard / API | No |
Instruction files are great for a handful of standing rules — keep using them
(open-memex can even draft one from your memories; see distill-agents below).
open-memex covers the growing pile of decisions, lessons, and preferences that
no one remembers to write down.
Installation
Requirements
Node.js ≥ 22.14 (
open-memex doctorverifies this for you). The floor is the SQLite driver's:better-sqlite313 is built against Node-API 10, which Node gained in 22.14.0 — older Node segfaults on the first database open.
Install the CLI
npm install -g open-memexThat's the stable release. Installing the package may print a reminder to run
open-memex init — the editor wiring is a separate step (see
Setting up your editor), so don't worry if you
don't see the reminder; just run init next.
Two alternatives:
No install — run via npx:
npx -y open-memex <command>runs any command without installing (e.g.npx -y open-memex init --client vscode). Slower to start, nothing to uninstall.Alpha builds (newest features, rougher edges, for testers):
npm install -g open-memex@alpha. Check what's published withnpm view open-memex version(stable) andnpm view open-memex@alpha version(alpha).
If open-memex isn't found after installing, your PATH needs attention — see
Troubleshooting.
From source (for contributors)
git clone -b main https://github.com/stoneskin/open-memex.git
cd open-memex
npm install
node --experimental-strip-types src/cli.ts <command>Setting up your editor
Run init from your project root (the top folder of the repo you're working
in) so the project scope resolves to that repo:
open-memex init --yes
# …or without installing the package first:
npx -y open-memex init --yes--yes accepts the recommended defaults for everything init asks about
(editors to wire, auto-capture, first-turn recall). Leave it off if you want to
answer each question. With no --client, init detects your installed editors
and wires them all — one init covers every project. Prefer a single editor?
Pass --client:
VS Code (Copilot):
open-memex init --client vscodeWrites the MCP server entry; reload the window afterwards and confirm the
open-memex server is started in Copilot Chat's MCP panel. By default this
writes a project-level .vscode/mcp.json (an interactive run asks which
level you want); add --global for VS Code's user-level config instead —
one setup that works in every project.
Cursor:
open-memex init --client cursorSame shape as VS Code: project-level .cursor/mcp.json by default,
user-level MCP config with --global, plus Copilot-style instructions.
opencode (native plugin — recommended):
open-memex init --client opencode --global --yesMerges the native plugin into your user-level ~/.config/opencode/opencode.json
(or opencode.jsonc if that's the file you already have) — one-time, every
project picks it up, no per-project init. You get the 5 core tools, keyword
auto-capture, and first-turn context injection. (A config file with comments is
left untouched — init prints the line to add by hand.)
Both opencode generations are supported from the same install: init writes
the opencode 1 spelling ("plugin") and the opencode 2 spelling ("plugins")
— each host reads its own key. Opencode 1 needs version 1.18.29 or newer
for this. open-memex doctor tells you if the wiring and the installed host
version don't match.
opencode (as a plain MCP consumer):
open-memex init --client opencodeWrites a project-level opencode.jsonc with the MCP server. Only needed if you
prefer plain MCP over the native plugin — you give up keyword capture and
built-in injection.
Claude Code (from your project root):
claude mcp add open-memex -- open-memex mcp
# …or print the config snippet: open-memex mcp --print-config claudeVisual Studio (from your solution directory):
open-memex init --client visualstudioWrites solution-level .mcp.json. Requires Visual Studio 2022 17.14+ or Visual
Studio 2026 (Windows-only). Visual Studio also auto-discovers .vscode/mcp.json
and .cursor/mcp.json, so the VS Code setup above works too.
Codex: no init client yet — add the server manually via
open-memex mcp --print-config as a starting point ([mcp_servers] in
config.toml, or codex mcp add).
One-time setup for all projects (VS Code / Cursor)
open-memex init --client vscode --global --yesTwo different "globals" — don't mix them up.
npm install -g open-memexinstalls the package globally: it puts theopen-memexcommand on your PATH.
init --globalwrites the editor config at user level instead of the project: init once, the wiring works in every project. It works the same whether the package was installed globally or run via npx.
The --global form writes the server entry to the editor's user-level MCP
config (%APPDATA%\Code\User\mcp.json on Windows,
~/Library/Application Support/Code/User/mcp.json on macOS,
~/.config/Code/User/mcp.json on Linux; ~/.cursor/mcp.json for Cursor)
instead of the project — init once, the server starts in every project.
A per-project .vscode/mcp.json still wins if a project defines its own.
If the user-level file has comments in it (editors accept JSONC), init leaves
the file untouched and prints the exact snippet to paste in by hand.
init behavior notes
Existing config files are merged, never overwritten — re-running
initis safe.--forcerewrites our entries.With no durable
open-memexonPATH(e.g. one-shot npx),initwrites annpx -y open-memex mcpserver command into the config so the setup keeps working.npm i -g open-memex+open-memex init --forceswitches to the faster direct command later.On an interactive terminal,
initshows the detected editors and asks you to confirm; scripts and CI never prompt and wire every detected editor.If you run bare
open-memexon a machine where init never completed, it offers to run it for you (interactive terminals only).
Remove the wiring
open-memex uninstall --yesReverses init — removes the MCP server entry, the opencode plugin line, the
Agent Skill, and the open-memex section of the editor instructions. With no
--client it cleans up every detected editor; --global limits the cleanup to
user-level wiring. Your memories are never touched.
What init changes on your machine
Everything init writes, in one place:
Memory data (created on first use, not by
inititself):%APPDATA%\open-memex\on Windows,~/.local/share/open-memex/on macOS/Linux — your memory files and the search index. Nothing here is ever modified byuninstall.Editor wiring (removed by
open-memex uninstall):opencode: a
"plugin"entry (opencode 1) and a"plugins"entry (opencode 2) merged into~/.config/opencode/opencode.json(or.jsonc). Stalemy-o-memoryentries from before the rename are removed at the same time.VS Code / Cursor: an
open-memexserver entry in the user-level or project-level MCP config, plus an open-memex section in the Copilot instructions (user-level~/.copilot/copilot-instructions.mdby default;--instructions projectwrites.github/copilot-instructions.mdin the repo instead, for teams where everyone uses open-memex).Visual Studio:
.mcp.jsonnext to your solution.Agent Skill: a
skills/open-memex/folder for VS Code (~/.copilot/skills/), Cursor (~/.cursor/skills/), or opencode in per-project MCP mode (~/.config/opencode/skills/).
Your repo: nothing. Files only appear in a repo when you explicitly run
submit(see Team workflow) — a local commit, never an automatic push.
Files with comments (JSONC) are never rewritten: init prints the exact
snippet to paste instead.
Capture: how memories get saved
Three ways memories get in:
Keyword triggers (opencode native plugin only): say
remember …,note that …,don't forget: …,TIL …,save this …— or in Chinese记住…/记一下…/记录一下…/别忘了:…— and the sentence is captured without any tool call. Captures land in the current project by default; phrases that signal "this is about me" —remember for me …,help me remember: …,记住我…,替我记…,帮我记…,我觉得…,我喜欢…— go to personal instead, and team-context phrases (我们决定…,帮我们记住…) stay in project. Two rules keep the noise down (D67): a trigger must be a statement to the store, so the narration forms记得…/remind me to…/别忘了带伞/don't forget the wifi passwordnever fire (add a separator —别忘了:…,don't forget: …— orthatto make it an instruction); and a captured body under 3 characters is rejected as a fragment rather than saved —capture --dry-runsays so instead of dropping it silently. A trigger also owns its own sentence: the plugin tells the agent what it just stored, and amemory_addthat re-saves the same words within the next few minutes is refused with the stored id (D73) — one thing you said is one memory, not three copies of it.The agent saves it: in any editor, ask your agent to remember something (or it saves on its own when you state a fact worth keeping) — it calls
memory_add. The routing above is a heuristic; you can always say "save this to my personal memory" or use the CLI with--scopeto be explicit.Checkpoint proposals: when a task wraps up, the agent proposes 1–3 short candidate memories distilled from the session — decisions and their reasons, conventions, gotchas, approaches tried and abandoned — and saves only the ones you approve. Nothing is written silently: no draft is created behind your back.
The CLI:
open-memex add "…"with optional--scope/--tag/--type/--aliases.
Aliases. Each saved memory can carry up to 4 alternate phrasings
(synonyms, another language's equivalent) that are indexed with it, so a
question worded differently still finds the memory — "vacation days" finds the
holiday policy. Always on — the agent may attach up to 4 per memory, and you
can pass your own via open-memex add --aliases.
Three ways to add them: open-memex add "text" --aliases "phrase one; phrase two" (semicolon-separated, up to 4); ask the agent ("remember: Fluffy is my
AI agent, alias it as Momo"); or edit the memory's aliases: frontmatter
directly — Markdown is the source of truth and sync picks it up.
Separately, a curated synonym/translation map is expanded into the index
automatically at write time (D80) — ship finds deploy even with no
aliases on the memory. Personal nicknames belong in aliases; shared
dev-domain vocabulary belongs in the curated map. See Retrieval: how
memories come back.
Redaction. Wrap anything sensitive in <private>…</private> and it is
stripped before saving. Recognized secrets (API keys, tokens, high-entropy
credentials) are masked in place — the first 4 characters are kept so you can
tell which key it was, the rest is replaced — and the memory is still saved.
Preview exactly what a message would capture, safely, any time:
open-memex capture --dry-run "…"If a secret slips through anyway, open-memex forget <id> deletes the memory.
Tools the agent gets
The MCP server exposes eleven tools; the opencode native plugin exposes the five core ones (marked ●). The other six are the team-review workflow tools — they only matter once you share memories through Git.
Tool | What it does |
● | Save a fact, preference, decision, note |
● | Keyword search (BM25) across project + personal memories |
● | List memories in a scope ( |
● | Replace a memory with a newer version (keeps a supersede chain) |
● | Delete a memory by id ( |
| Show the sync queue: outbox drafts, repo review states, uncommitted files |
| Move named drafts into the repo memory dir (local branch + commit) |
| Copy personal memories into the project scope as review candidates |
| Advance |
| List conflicted memory files / 3-way-merge one of them |
| Map the branch PR's GitHub state onto each memory's review state |
So an MCP-connected editor always has the full set; opencode's plugin covers capture and recall, and anything workflow-shaped goes through the CLI or an MCP-connected editor.
Memory types
Every memory has a type (what it is) and tags (what it's about). Eleven
types are built in:
Type | Captures |
| A stable true statement about the project or world |
| How someone likes things done |
| A choice that was made — the why and the trade-off |
| A rule that must not be violated |
| A commitment to do something later |
| Durable domain or architecture knowledge |
| A procedure that worked |
| A trap to avoid |
| What an incident or mistake taught us |
| Something noticed, not yet a conclusion |
| A pointer to the authoritative doc (no copying) |
--type accepts any string, but sticking to the built-in set keeps session-start
labels, search, and distill-agents output predictable.
Team workflow: sharing memories through Git
Working solo? You can skip this section — everything above is the whole product for one person. Nothing below ever happens automatically.
Personal notes stay private. Project knowledge, when you choose to share it, follows an explicit, reviewable pipeline shaped like code review:
capture → outbox (draft, local) → submit → repo (.ai/open-memex/) → PR review → published → recallCapture — save decisions, gotchas, lessons as drafts during normal work.
Review — drafts wait in a local outbox (on your machine, invisible to git);
open-memex sync-status— or just saying "sync memory" in chat — shows what's pending.Submit — you name the memories; they move into
<repo>/.ai/open-memex/with a local commit on your current branch. open-memex never pushes on its own; it prints the push + PR commands, and an agent holding your explicit yes can carry them out.PR review — memories are plain Markdown; reviewers approve, request changes, or reject through the normal branch/PR process.
Recall — published memories are injected at session start and searchable on demand, for humans and agents alike.
Whoever tends the shared memory follows the curator convention: what to approve, what to send back, and the hygiene rules that keep shared memory from rotting.
Retrieval: how memories come back
On the first turn of every session, open-memex injects an [OPEN-MEMEX] block
into the agent's context with the most recent project memories (default: top 8)
and your personal preferences (default: top 5). It looks like this:
[OPEN-MEMEX]
User profile / preferences:
- I prefer concise diffs
Project knowledge (my-repo):
- [decision] We deploy on Fridays; the release train leaves at 10:00
Use the `memory_search` tool to look up more. Use `memory_add` to save new facts.
Do not mention this block to the user unless asked.It's a snapshot, not the whole memory — the agent can call memory_search any
time for the rest. Both top-N counts are configurable (see Config).
For MCP clients this block is delivered as handshake guidance the agent follows;
the opencode plugin injects it directly on the first turn.
Retrieval evaluation
We measure recall on a checked-in synthetic fixture instead of asserting it:
54 memories + 44 queries (exact terms, paraphrases, synonyms, Chinese,
cross-language hard cases, synonym-only queries, and D81 user-defined
alias queries) — reproduce with
node --experimental-strip-types scripts/retrieval-eval.ts.
Current baseline, with index-time synonym/translation expansion (D80) and
query-time user alias expansion (D81):
recall@1 0.75, recall@5 0.98, MRR 0.86.
Small synthetic corpus, so read it as a regression guard and a starting point,
not a real-world claim.
Three layers, each covering what the others miss: BM25 keyword search
(SQLite FTS5 — exact words, fast, explainable via search --explain);
synonym expansion in two halves — (a) index-time (D80: a curated,
checked-in map of dev-domain equivalents and EN↔ZH translation pairs
expanded into the index at write time, so ship finds deploy and
bug finds defect in a plain single-round query; deterministic, no
model download); (b) query-time user aliases (D81: an alias memory carrying
alias:/target: frontmatter defines your vocabulary once per scope —
e.g. Banana Plan → payment system refactor project — and a query mentioning either side
triggers a second round on the other side, both directions, merged evenly
with round one so alias hits are never down-weighted; no reindex when the
alias changes); and semantic vectors
as an opt-in experiment (local multilingual embeddings measured at R@5 92.7%
on the cross-lingual fixture slice — see docs/retrieval-ablation-study.md
§4.7; no embedding model is ever downloaded without your explicit opt-in).
External check on public data: the same pipeline scores recall@5 97.0% /
MRR 0.909 on LongMemEval-S (470 questions, retrieval stage only — no answer
generation, no judge model; this is not the official LongMemEval score). For
reference, agentmemory's published numbers on the same protocol are 86.2% /
0.715 (BM25-only) and 95.2% / 0.882 (BM25+vector). A 22k-memory pooled stress
run drops recall@5 to 40.6% — the lexical ceiling, measured rather than
asserted. Reproduce with
node --experimental-strip-types scripts/bench-longmemeval.ts --data <path>
(dataset: xiaowu0162/longmemeval-cleaned, MIT).
Security & data
Local-first: everything lives on your machine (
%APPDATA%\open-memexon Windows,~/.local/share/open-memexon macOS/Linux) plus the repos you choose. Zero cloud calls, zero accounts, zero third-party APIs, zero telemetry.Secrets stay out:
<private>…</private>spans are stripped; detected API keys/tokens are masked in place before saving. Preview withopen-memex capture --dry-run "…".Personal never syncs: the
personalscope is this machine only — excluded from export by default and can never enter a repo.Auditable sharing: team memories move only by explicit
submit, travel through branch/PR review, and everypromotetransition is appended to the memory'sreview_history(who / when / why).You own the files: Markdown is the source of truth — inspect, edit, or delete anything by hand; the SQLite index rebuilds from the files.
Limitations
Honest edges, so nothing surprises you:
Keyword search, not semantic. Retrieval is BM25 keyword matching, plus a curated synonym map expanded into the index at write time (
shipfindsdeploy,bugfindsdefect). Paraphrases outside the curated map don't match — that's what the opt-in semantic layer is for. (Plain questions are fine — "how do we…" / "请问…" wording is filtered out before matching, so asking naturally doesn't dilute the results.) No embedding model is ever downloaded without your explicit opt-in. (Synonym expansions live in their own index column, separate from your own aliases — but a query matching only via an expansion can still rank below direct matches; that's inherent BM25 length-norm behaviour, not a bug.)One machine. Editors on the same machine share memory; there is no cross-machine sync.
export/importbundles (below) move memory between machines manually.A snapshot, not everything. Session-start recall is a top-N snapshot (8 project + 5 personal by default); older memories are one
memory_searchaway, but they are not all in context at once.MCP guidance is advisory. Outside opencode, proactive capture and recall depend on the agent following the handshake instructions — there is no hard session-start hook in MCP. The tools themselves always work when called.
Capture routing is a heuristic. Personal-signal phrases (
remember for me …,我喜欢…) go to personal; everything else defaults to the current project. When it guesses wrong, say the scope out loud or use--scopein the CLI.
Upgrading
npm install -g open-memex@latest # or @alphaYour editor configs point at the installed open-memex command, so upgrades
need no re-wiring. After a major upgrade, run open-memex init --force once to
refresh the installed Agent Skill and instruction files with the latest wording.
If you installed from source or moved the package, --force also re-points the
opencode plugin path.
What changed in each version: see the CHANGELOG.
Storage layout
%APPDATA%\open-memex\ (Windows)
~/.local/share/open-memex/ (macOS/Linux; $XDG_DATA_HOME if set)
├── index.db # SQLite FTS5 index (rebuildable)
└── memories/
├── personal/
│ └── <id>.md
└── project__<name>__<hash12>/
└── <id>.mdEach .md file is one memory: YAML frontmatter (id, scope, type, tags, created_at, schema_version, …) followed by the content. You can edit them by
hand — the index re-syncs from the files, and Markdown is always the source of
truth (open-memex reindex rebuilds the index from scratch).
Once you submit, project memories also live as Markdown files under
<repo>/.ai/open-memex/ (configurable via memoryDir), where they travel with
branches and PRs like any other file.
Config
Settings live in ~/.config/opencode/open-memex.jsonc — the opencode in the
path is historical; this one file is shared by every client. Override the config
path with OPEN_MEMEX_CONFIG and the storage root with OPEN_MEMEX_HOME
(the pre-rename MY_O_MEMORY_CONFIG / MY_O_MEMORY_HOME names are still
honored as fallbacks).
Defaults:
{
"maxProjectMemories": 8, // top-N project memories injected on first turn
"maxProfileItems": 5, // top-N personal items injected on first turn
"injectOnFirstTurn": true, // [OPEN-MEMEX] system-prompt block
"keywordCaptureEnabled": true,
"logLevel": "info", // info | debug
"memoryDir": ".ai/open-memex" // in-repo project-memory dir, relative to repo root
}open-memex config prints the effective config (defaults + file). Change a
setting after install:
open-memex config set keywordCaptureEnabled false
open-memex config set maxProjectMemories 12
open-memex config set sync.autoPull true # best-effort pull at MCP session startSettable keys: maxProjectMemories, maxProfileItems, injectOnFirstTurn,
keywordCaptureEnabled, captureAliases, logLevel, memoryDir, and sync.autoPull (a dotted
key that writes into the nested sync object). Full design:
docs/V2-DESIGN.md.
CLI reference
Setup & health:
open-memex init [--client vscode|cursor|opencode|visualstudio]
[--instructions personal|project] [--global] [--force] [--yes]
open-memex uninstall [--client vscode|cursor|opencode|visualstudio] [--global] [--yes]
open-memex config # print effective config
open-memex config set <key> <value> # change a setting
open-memex doctor # environment health check (incl. plugin entry)
open-memex audit # memory health check (duplicates, stale, broken chains)
open-memex capture --dry-run "remember that I like concise answers" # preview keyword capture
open-memex mcp --print-config vscode|cursor|claude|opencode|visualstudio
open-memex --help # this reference
open-memex <command> --help # help for one command
open-memex --version # installed versionMemory operations:
open-memex add "This repo uses better-sqlite3" --type fact
open-memex search "auth flow"
open-memex search "auth flow" --explain # show FTS expression, scores, lifecycle-hidden counts
open-memex list --scope project
open-memex list --scope both # each scope's newest under its own header
open-memex list --include all # audit view: superseded versions, retracted, archived
open-memex supersede <id> "Updated content"
open-memex status <id> deprecated
open-memex forget <id>
open-memex forget <id> --soft # hide instead of delete (retracted; one-way)
open-memex inventory # everything remembered, as readable text
open-memex inventory --format json # the same data, for agents
open-memex inventory --format html # the same data as a local page (writes <data dir>/inventory.html)
# Personal + current project, outbox drafts in their own section, hidden
# history counted. Refuses to write a personal-bearing report inside a
# git working tree unless you pass --allow-personal.
# `list` numbers every entry in one listing and says how many it left out.Team review workflow (two homes, one per stage):
Project drafts live in the appdata outbox (git-invisible, branch-independent);
only drafts you approve move into <repo>/.ai/open-memex/, where they follow
branches and PRs. Nothing moves without you naming it. In an AI chat with the
MCP server connected, just say "sync memory" (or "同步记忆") — the agent
runs the status check, summarizes the outbox drafts, and asks which ones to
sync. The server also tells the agent on its own: at session start the
handshake reports how many drafts are waiting, and every memory-changing tool
result carries the current count when it is non-zero.
open-memex sync-status
# show when the index was last synced (and what triggered it), the outbox
# (pending sync), the repo review states
# (draft / proposed / approved / published / rejected),
# and any uncommitted repo memory files.
open-memex submit <id...> [--branch <name>] [--base <branch>]
# move your named drafts into .ai/open-memex/ as "proposed":
# copies, flips review_state, local git commit ON THE CURRENT BRANCH.
# Never creates a branch on its own — branch creation is your call
# (or the agent's, only with your explicit approval for the full chain).
# All-or-nothing; conflicts (same id, different content) abort cleanly.
# Prints the push + gh pr commands; an agent holding your Yes carries
# through push/PR itself. --branch <name> creates the branch first
# (agent full-chain path). Default PR base is the current branch (memory
# PRs stack onto your working branch); --base redirects it to main or
# wherever you review.
open-memex pr-status [--apply]
# read the branch's GitHub PR and map its state onto each in-repo memory:
# merged PR → published, PR approval → approved (approved_by = reviewer),
# changes-requested → suggestion only. Report by default; --apply performs
# the mapped transitions locally (no push).
open-memex pull
# pull shared memories from the git remote: fetch + fast-forward ONLY.
# A diverged branch fails with a clear message — open-memex never
# force-merges; resolve it by hand, then pull again. On success the
# local index re-syncs. Pulls are explicit by default; set
# `open-memex config set sync.autoPull true` for a best-effort pull
# at MCP session start (a failed pull never blocks the session).
open-memex push
# push the current branch (with its submitted memories) to the git remote.
# Explicit only — open-memex never pushes on its own.
open-memex export [--scope project|personal|both] [--type T] [--tag t] [--all] [-o <file>]
# bundle memories into a portable .tar.gz (markdown + manifest.json) for
# moving to another machine or another app. Excludes visibility:private
# memories by default; --all / -a includes everything (full migration).
open-memex import <bundle.tar.gz> [--dry-run]
# restore a bundle: personal memories go to the personal dir; project
# memories are re-keyed to the current project and land in the outbox as
# drafts. Identical ids are skipped; conflicting ids are reported,
# never overwritten.
open-memex distill-agents [--scope project|personal] [--type t1,t2] [--limit N] [-o <file>]
# propose an AGENTS.md snippet distilled from project memories
# (decisions, constraints, lessons, gotchas, howtos). Prints markdown;
# -o writes it to a file. You review and merge by hand — open-memex
# never rewrites your AGENTS.md on its own. The snippet ends with a
# "memory hygiene" section so agents reading AGENTS.md learn to propose
# distilled captures when a task ends.
open-memex propose <id...> --to project [--local-approve]
# propose one or several personal memories at once (one branch, one PR);
# each is copied with its own new id. All-or-nothing: a bad id aborts the
# whole batch, never a half-proposed one.
# copy a personal memory into the project scope as a review candidate
# (never moves — the personal original stays). Result lands in the outbox;
# run sync-status / submit when you're ready to put it in the repo.
open-memex promote <id> [--reject] [--resubmit] [--note "..."] [--by NAME]
# advance one step: proposed → approved → published (or reject with a note).
# Every transition is appended to the memory's review_history (who/when/why).
# A rejection never deletes the file — your call: accept it (close the PR,
# delete the branch), revise + --resubmit for another round, or keep it as
# a [rejected] record.
open-memex resolve [id-or-path]
# list conflicted memory files, or field-level 3-way merge one of them.
# Semantic conflicts are reported, never auto-resolved.Whoever tends the shared memory follows the curator convention —
docs/CURATOR.md: what to approve, what to send back, and the hygiene
rules that keep shared memory from rotting.
Maintenance:
open-memex where # show storage + config paths
open-memex scopes # list project scopes with memory counts
open-memex reindex # rebuild the SQLite index from markdown
open-memex audit # memory health: duplicate pairs, stale memories, broken chains
open-memex migrate --to-v2 [--dry-run] # v1 data → v2 (renames user scope to personal)The CLI runs under Node 22. From a source checkout it uses the built-in
experimental TypeScript loader (no build step); the published npm package ships
pre-compiled JS (npm run build at publish time). From a source checkout,
prefix every command with node --experimental-strip-types src/cli.ts (or
npm run cli -- <command> for simple cases — npm swallows unknown --flag
args, so prefer direct node).
MCP server
The same memory tools over the Model Context Protocol, via a stdio server — no host-specific plugin needed. Any MCP client can use open-memex.
open-memex mcp # after a global install
npx -y open-memex mcp # no install neededThe project scope is resolved from the process working directory, so configure
the server with cwd set to your project root (init handles this for you).
Note: MCP is request/response — it gives the agent tools, not the opencode plugin's automatic keyword capture or first-turn injection. Proactive memory use depends on the agent's instructions: the server sends session-start guidance in the MCP handshake
instructions(including the live outbox draft count at session start, plus the pending count appended to memory-changing tool results when non-zero), andinitwrites the fuller version into the editor's instruction files. Both are advisory — no MCP consumer offers a hard session-start hook.
Scopes, in detail
project — scoped to the current repo, keyed off the git origin URL hash (so clones of the same repo share a scope), or off the cwd path if there is no remote. Default for new memories.
personal — global across all your projects, this machine only, never synced. Use for personal preferences. (v1 called this
user;migrate --to-v2renames it.)
See docs/SCOPES.md for the full scope model: key derivation, migration, visibility, reserved names. The concept guide walks through the mental model end to end.
Troubleshooting
Every command dies with no output, or the process crashes (exit 139,
0xC0000005, "Segmentation fault").
Your Node is older than 22.14 and the bundled SQLite driver cannot load on
it. better-sqlite3 13 is compiled against Node-API 10, which Node only gained
in 22.14.0; on anything older require() succeeds and then the first database
open segfaults the process with no diagnostic. open-memex now refuses to load
the driver and says so, but anything already crashing was almost certainly this.
Check with node -v, then either upgrade Node (nvm install 22.14 && nvm use 22.14, or any current 22.x/24.x) or pin the driver down with npm install better-sqlite3@^12.11.1. open-memex doctor reports both the Node floor and a
live driver probe. Known upstream: WiseLibs/better-sqlite3#1514.
open-memex is not recognized / command not found.
A global npm install -g puts the open-memex launcher in npm's global bin
folder. If your terminal can't find it, that folder isn't on your PATH:
Find the folder:
npm config get prefixWindows: the launcher (
open-memex.cmd) sits directly in that folder, e.g.C:\Users\<you>\AppData\Roaming\npmmacOS / Linux: it's in
<prefix>/bin, e.g./usr/local/binor~/.nvm/versions/node/v22.x.x/bin
Add it to
PATH:Windows: Settings → System → About → Advanced system settings → Environment Variables → add the folder to the User
Path→ restart the terminal. Verify withwhere open-memex.macOS / Linux: add
export PATH="$(npm prefix -g)/bin:$PATH"to~/.zshrc(or~/.bashrc), restart the shell, verify withcommand -v open-memex.
No admin rights / don't want to touch
PATH? Use the npx form —npx -y open-memex <command>resolves the package itself and needs noPATHchanges.
EBUSY / EPERM on better_sqlite3.node (Windows).
On Windows a loaded DLL is locked: if the open-memex MCP server is running
(VS Code MCP panel, Cursor, etc.), npm install -g open-memex cannot replace
better_sqlite3.node and fails with EBUSY / EPERM. Stop the MCP server
first (or quit the editor), then re-run the install. If it still fails, delete
node_modules/open-memex and any node_modules/.open-memex-* temp folders
under your global npm root and install again.
init says it left a config file untouched.
Your editor config has comments (JSONC) or invalid JSON, and open-memex never
rewrites files it can't parse safely. init printed the exact snippet to add
by hand — paste it in, and you're done. The same applies to the opencode
config: if it has comments, add the "plugin" line manually.
Something's off — run open-memex doctor.
Checks the Node version, config source, scope resolution for the current
directory, and storage writability; verifies VS Code hasn't disabled MCP;
then boots a real MCP server and runs initialize + tools/list against
it — all eleven tools must show up. It also reports pre-rename my-o-memory
leftovers if any editor config still references the old package name.
FAQ
Do I need git?
No. Capture and recall work in any folder — without a git repo the project
scope simply keys off the folder path. Git is only needed for the team
workflow (submit / PR review), which is optional.
I use several editors. Do they really share one memory? Yes — on the same machine. Every wired editor reads and writes the same local memory; see the capability matrix for what each editor gets. A decision captured in VS Code is respected in opencode.
I work on two computers (office + home). Does memory sync?
Not automatically — memory is per-machine by design, and your personal scope
never leaves the machine it was created on. To move memory manually, use
open-memex export on one machine and open-memex import on the other.
Project memories shared through Git (Team workflow) travel with the repo, so
cloning the repo on the second machine brings the published project memories
along — your personal ones stay behind, on purpose.
Is it really free? Do I need an account? Free and open source (Apache-2.0). No account, no sign-up, no telemetry, no cloud calls. If it can't phone home, there's nothing to phone home to: the only network open-memex ever touches is your own git remote, when you explicitly push.
I accidentally pasted a secret into a memory. What now?
open-memex search "<part of it>" to find the memory, then
open-memex forget <id> to delete it. To prevent it next time, wrap sensitive
text in <private>…</private> (stripped before saving) — recognized API keys
and tokens are also masked automatically. Preview any message safely with
open-memex capture --dry-run "…".
Do I need to run init for every project?
No. The data layer needs nothing — the project scope is derived automatically
from your cwd's git remote or path, so memories are namespaced per project
with zero setup. The editor wiring is one open-memex init per machine
(user-level wherever the editor supports it). Run it again only after
upgrading (--force) or if you switch editors.
Does opencode need init?
Two paths. Recommended: open-memex init --client opencode --global — it
merges the native open-memex plugin into ~/.config/opencode/opencode.json
for you. One-time setup, applies to all projects, and additionally enables
keyword auto-capture and first-turn memory injection. Prefer to do it by hand?
Add "plugin": ["file:///absolute/path/to/open-memex/src/index.ts"] (the
installed package's path) to that file instead. As a plain MCP consumer:
open-memex init --client opencode writes a project-level opencode.jsonc
(no hooks). If your user-level config has comments, init leaves it
untouched and prints the manual step.
VS Code — run init once, or per project?
Once. Plain open-memex init auto-detects VS Code and writes the MCP server
entry to VS Code's user-level mcp.json (%APPDATA%/Code/User/mcp.json on
Windows, ~/Library/Application Support/Code/User/mcp.json on macOS,
~/.config/Code/User/mcp.json on Linux), so the server starts in every
project. A per-project .vscode/mcp.json still wins when present, and the
entry keeps cwd=${workspaceFolder} so project-scope resolution keeps
working per window. If your user-level mcp.json has comments (VS Code
accepts JSONC), init leaves it alone and prints the exact snippet to add by
hand. An empty file is treated as blank and written to directly.
How do I remove the editor wiring?
open-memex uninstall reverses init: it removes the MCP server entry, the
opencode plugin line, the Agent Skill directory, and the open-memex section of
the Copilot instructions. With no --client it cleans up every detected
editor; --global limits the cleanup to user-level wiring. Your memories are
never touched.
I upgraded Node, or switched versions with nvm. Do I need to reinstall?
The package itself doesn't care: its SQLite driver is a Node-API prebuild, so
it loads on any supported Node (≥ 22.14) with no recompiling, and your
memories live outside the install. But version managers (nvm and friends)
keep a separate global package folder per Node version, so after a switch
open-memex may simply be "not found". Run npm install -g open-memex once
under the new Node, then open-memex doctor to confirm the driver loads.
Project status
open-memex is stable and in daily use; the current stable line is published on
npm as latest, with alpha builds for testers. Release history lives in
GitHub Releases; design
decisions are recorded in the append-only log at
docs/V2-DESIGN.md.
On the horizon (no version promises): native agent plugins for more editors as enhancements over the same MCP tools; local embeddings as an opt-in experiment (no model is ever downloaded without asking); an org layer only if real multi-repo sharing, ACL, or compliance needs demand it.
License
Available Tools
11 toolsmemory_addA
Save a fact, preference, decision, or note to persistent local memory. Call this PROACTIVELY whenever the user shares something worth remembering across sessions — project conventions, tool choices, personal preferences, decisions made, error fixes and their causes. Worth saving: decisions and their reasons, preferences, conventions, gotchas, approaches tried and abandoned. Not worth saving: one-off task details or anything re-derivable from the code. Do not wait to be asked. For facts you infer yourself rather than the user stating, propose them first and save only on approval. Keep each memory to one self-contained statement; attach aliases when the parameter is available. If a note tells you the user's own wording was already stored verbatim this turn, that statement is already saved: do not retry it in a rewording — save only what that text does not contain, or use memory_supersede on the given id. Default scope is the current project; use the personal scope for facts about the user that apply across all projects. Returns the new memory's id; an identical fact already stored returns that id instead of duplicating.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Optional tags for filtering. | |
| type | No | Category of memory. Default: fact. | |
| scope | No | Memory scope. `project` = tied to this repo. `personal` = global across all your projects. Default: project. | |
| source | No | Where this memory came from. Default: tool. Pass 'inference' for agent-proposed captures (V2-DESIGN §3.5). | |
| aliases | No | Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match. Only used when the install has capture aliases enabled (init default). Send at most 4; extras and blanks are dropped silently, never an error. | |
| content | Yes | The fact to remember. One idea per memory. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly=false, destructive=false, openWorld=false. The description goes well beyond that: idempotent dedup behavior (an identical fact returns the existing id), the return value, default scope semantics, alias indexing behavior (max 4, silently dropped extras), and a no-retry rule for verbatim-stored content. Rich behavioral context the annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and most sentences earn their place, but the definition is dense and the clause about content 'already stored verbatim this turn' is convoluted enough to slow an agent down. Slightly long, though not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description states what is returned (the new memory's id, or the existing id on a duplicate), covers scope selection, the propose-on-approval rule for inferences, and alias handling. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already documented, including the scope and aliases semantics. The description reinforces the scope default and alias attachment but adds little syntax or format detail beyond the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource ('Save a fact, preference, decision, or note to persistent local memory') and even enumerates the kinds of content it stores. It also differentiates from a sibling by naming memory_supersede for the verbatim-duplicate case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('PROACTIVELY whenever the user shares something worth remembering'), when not to ('one-off task details or anything re-derivable from the code'), the propose-first condition for inferred facts, and routes the duplicate case to memory_supersede. This is about as complete as usage guidance gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_forgetADestructive
Delete a memory by id. Use when the user asks to forget something. To replace an outdated fact with a corrected one instead of deleting it, use memory_supersede. Deletion is permanent: before deleting, restate the memory's content to the user and get a confirmation. With soft=true the memory is hidden instead (retracted: out of lists and search, file kept, one-way).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| soft | No | D68: hide instead of delete. The memory is retracted — excluded from lists and search — but its file stays. Retraction is one-way (D64): it does not come back; to restore the fact, save it again as a new memory. Offer `soft` when the user is unsure about deleting. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds materially more: deletion is permanent, the agent must restate content and obtain confirmation first, and soft=true produces a one-way retraction (out of lists/search, file retained, not reversible without re-saving). These are workflow and irreversibility details annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core action, then the sibling routing, then the safety workflow, then the soft-mode variant. Every sentence carries distinct, non-redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter destructive tool with no output schema, the description covers action, alternative, irreversibility, a required confirmation step, and the soft-retraction variant. Nothing an agent needs in order to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (the `id` param has no schema description), so the description carries part of the burden; it does explain `soft` semantics in prose (hidden, retracted, file kept, one-way). The `id` parameter itself gets no format or sourcing detail, so it doesn't fully compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Delete a memory by id") and explicitly distinguishes itself from the nearest sibling, memory_supersede, which handles the replace-not-delete case. An agent can route between the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ("Use when the user asks to forget something") plus the alternative and the condition that selects it ("To replace an outdated fact with a corrected one instead of deleting it, use memory_supersede"). It also advises offering soft mode when the user is unsure, which is real routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_listARead-only
List memories in a scope, newest first, as a numbered inventory. Each line keeps the raw fields — [type] id=… created=… source=… — say them back to the user in plain words (source=user → 'you told me this'; inference → 'I inferred this, check me'; keyword → 'caught from your own wording'), never read the raw id aloud unless they ask. When the user asks 'what do you remember about me?', use scope=both and present the inventory conversationally. The user may point at an entry by its number ('delete #3'): numbers are only valid for the listing you just produced — re-run memory_list, read the candidate back in full, and get a confirmation before calling memory_forget (deletion is permanent). include=all is the audit view (superseded versions, retracted, archived also shown). type filters to one memory type; limit caps how many entries come back.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Only list memories of this type (e.g. decision, preference, gotcha). | |
| limit | No | Max entries to list, newest first (default 20). | |
| scope | No | Which scope(s) to list. `project` = tied to this repo. `personal` = global across all your projects. `both` lists each scope's newest. Default: project. | |
| include | No | D68: `active` (default) shows what is currently remembered — newest version of each fact, retracted/archived hidden. `all` is the audit view: every stored row including superseded versions and hidden ones. The default CHANGED in D68: superseded versions no longer appear unless include=all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and openWorldHint=false, and the description does not contradict them. It adds genuinely non-obvious behavioral context beyond the annotations: entry numbers are ephemeral to the last listing, and the default now hides superseded versions. It stops short of describing volume/performance characteristics, but with annotations covering the safety profile this is a solid contribution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and output format, then moves to presentation and deletion-safety rules. The quoted phrasing guidance ('source=user → "you told me this"') is chatty and slightly crowds out tool behavior, but each sentence carries actionable instruction rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing the return value, and it does: a numbered inventory with per-line raw fields and an explanation of what each source value means. Combined with the include=all audit behavior and the deletion safety loop, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds usage-conditional meaning the schema lacks: scope=both is the right setting for recall-style questions, and include=all is framed as 'the audit view'. The type and limit mentions largely restate the schema, so the gain is real but partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List memories in a scope, newest first, as a numbered inventory') and even specifies the output shape, so an agent knows exactly what it gets. It does not explicitly distinguish itself from memory_search or memory_status, so sibling differentiation is only implied by 'inventory' vs. a search tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit triggering conditions ('When the user asks "what do you remember about me?", use scope=both'), names the audit-view condition for include=all, and routes to memory_forget with a required re-list-and-confirm precondition. It also warns that numbers are only valid for the most recent listing, which is exactly the kind of usage constraint an agent would otherwise get wrong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_promoteA
Advance a project memory one step up the review ladder (proposed → approved → published), or reject it with a note. Rejected memories are never deleted — they can be revised and resubmitted. One step per call; an unknown id or a memory already published errors. Pass by to record the reviewer when it should differ from the default (e.g. approving on the strength of someone else's review). For brand-new outbox drafts, memory_submit is the entry point. (MCP server and the open-memex promote CLI; the opencode native plugin does not expose this tool.)
| Name | Required | Description | Default |
|---|---|---|---|
| by | No | Reviewer name override. | |
| id | Yes | Project memory id. | |
| note | No | Review note recorded on reject. | |
| reject | No | Reject instead of advancing. | |
| resubmit | No | Move rejected back to proposed for another round. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only declare this is a non-read-only, non-destructive mutation), the description discloses meaningful behavior: exactly one step per call, error on unknown id or already-published memory, and the key non-obvious guarantee that rejected memories are never deleted and can be revised/resubmitted. It also explains the reviewer-override semantics of `by`.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and state ladder, then supporting constraints. Every sentence carries information, though the trailing parenthetical about MCP server / CLI / plugin surfaces is meta-info that slightly dilutes focus.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter mutation tool with no output schema, the description covers the transition, reject path, error conditions, and resubmission well. It omits what a successful call returns (e.g. the memory at its new state) and any permission/authorization requirements, which would round it out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds intent beyond the terse schema strings: it explains why `by` exists (recording a reviewer that differs from the default, e.g. approving on another's review) and ties reject+note and resubmission behavior to the relevant flags.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb (advance/promote) and resource (project memory) plus the exact state transition (proposed → approved → published). It also names the sibling that handles the adjacent case (memory_submit for brand-new drafts), so an agent can distinguish it from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear when-to-use context (advancing a memory one rung, or rejecting with a note) and explicitly routes the new-draft case to memory_submit. It does not, however, address relationships to other review-lifecycle siblings like memory_propose or memory_resolve, so the alternative coverage is partial rather than exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_proposeA
Copy personal memories into the project outbox as review drafts. The personal originals stay put. Use this when personal knowledge should enter a project's review flow; memory_submit then moves the drafts into the repo, and memory_promote advances drafts already there. (MCP server and the open-memex propose CLI; the opencode native plugin does not expose this tool.)
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Personal memory ids to copy into the project outbox. | |
| localApprove | No | Single-developer shortcut: mark the copies approved immediately. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=false and readOnlyHint=false, so the write-but-safe profile is covered. The description adds real value on top: it clarifies that this is a copy (originals remain) rather than a move, and discloses surface availability (MCP server and CLI, not the opencode native plugin). It does not describe the resulting draft state in detail, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the usage rule, then the alternative routing, all in three compact sentences. The trailing parenthetical on server/CLI availability is useful but slightly tangential; nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-destructive write tool with full schema coverage and no output schema, the description covers action, safety semantics, lifecycle position, and environment availability. Minor gaps remain about what a draft looks like and where the outbox lives, but nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, including a description for localApprove, so the schema carries both parameters fully. The description adds no syntax or format detail beyond what the schema provides (the word 'copy' loosely implies ids), so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb and resource: 'Copy personal memories into the project outbox as review drafts,' plus the clarifying clause that originals stay put. It explicitly distinguishes itself from memory_submit (moves drafts into the repo) and memory_promote (advances drafts already there), so an agent can route between the three without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the selecting condition explicitly ('Use this when personal knowledge should enter a project's review flow') and names the two adjacent alternatives with their distinct roles. This is a complete when/when-not map for the promote/submit/propose cluster.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_pr_statusA
Read the current branch's GitHub PR and map its review state onto each in-repo memory: merged PR → published, PR approval → approved (approved_by = reviewer), changes-requested → suggestion only. Report by default — that mode changes nothing; apply=true writes the mapped transitions to the local files (still no push). (MCP server and the open-memex pr-status CLI; the opencode native plugin does not expose this tool.)
| Name | Required | Description | Default |
|---|---|---|---|
| apply | No | Perform the mapped review transitions locally (no push). Default: report only. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the default report mode is a no-op, that apply=true writes only to local files, and that even then no push occurs — an important blast-radius limit that openWorldHint=false/destructiveHint=false cannot express. readOnlyHint=false is consistent with the documented apply=true write path, so there is no contradiction; the only gap is upstream behavior such as missing-PR or auth handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and then the mode semantics before the parenthetical deployment note. It is dense but largely earns its length; the trailing note about the MCP server/CLI/native plugin is tangential to invoking the tool and is the one part that dilutes focus.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-param tool with no output schema, it covers the essential invocation semantics: what is read, how state maps, and when writes happen. The only shortfall is that the shape of the 'report' output is never sketched, leaving the agent to infer what the default mode returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema coverage is 100%, so the schema already documents 'apply' fully. The description reinforces the default and adds the 'still no push' nuance, but adds little syntax or meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('read the current branch's GitHub PR and map its review state onto each in-repo memory') and then spells out the exact mapping rules (merged → published, approval → approved, changes-requested → suggestion). The mapping semantics make it immediately distinguishable from the plain memory_* siblings, which none of them do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clarifies the two modes ('report by default; apply=true writes'), which is genuine usage guidance for the one parameter. However, it never names when to prefer this over siblings like memory_promote or memory_status, which also touch memory state, so the agent must infer the routing itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_resolveA
List git-conflicted memory files, or attempt a field-level 3-way merge of one. Semantic conflicts are reported, never auto-resolved. Run it when a git pull or merge leaves memory files conflicted; the merged file is written in place (undo with git if the merge is wrong). For PR review state rather than file conflicts, use memory_pr_status. (MCP server and the open-memex resolve CLI; the opencode native plugin does not expose this tool.)
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | Memory id or file path to resolve. Omit to list conflicts. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: the merge is field-level 3-way, semantic conflicts are reported and never auto-resolved, the merged file is written in place, and recovery is via git. The write-in-place behavior is consistent with readOnlyHint=false and destructiveHint=false (reversible, undoable). It also discloses environment availability (MCP server and CLI, not the opencode native plugin), which annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the two modes, then trigger, then alternative, then availability. Nearly every sentence earns its place, though the trailing parenthetical about server/CLI/plugin exposure reads as a footnote and slightly dilutes the core instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description covers both operational modes, the non-auto-resolution policy for semantic conflicts, the in-place write and its undo path, the sibling alternative, and runtime availability. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already states "Omit to list conflicts," so the baseline is 3. The description adds the mode semantics behind each branch — omitting lists conflicted files, supplying a target attempts a merge — which clarifies the parameter's effect rather than just its type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States two specific verbs on one resource (list git-conflicted memory files; attempt a field-level 3-way merge of one), and the branch condition is tied to the single `target` parameter. It explicitly names memory_pr_status as the sibling for a different conflict domain, so an agent can route without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ("Run it when a git pull or merge leaves memory files conflicted") plus an explicit exclusion and alternative ("For PR review state rather than file conflicts, use memory_pr_status"). Both when-to-use and when-not-to-use are stated outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_searchARead-only
Search persistent memory by keyword (BM25 full-text). Returns matching memories from the current project and/or personal scope. Call before asking the user about past decisions, conventions, or preferences they may have told you before. Search well: break the question into its concepts and try 2–3 phrasings per concept — synonyms, the user's other language, shorter keyword forms — and check the other scope too, before concluding nothing is stored. Results are ranked by BM25 within review tiers — reviewed (approved/published) project memories come first. limit caps how many come back (default 8) and type restricts to one memory type.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Restrict to memories of this type (e.g. decision, preference, gotcha). | |
| limit | No | Max results to return (default 8). | |
| query | Yes | Free-text query. File paths, error strings, identifiers work well. | |
| scope | No | Which scope(s) to search. Default: both. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context: results are ranked by BM25 within review tiers and reviewed (approved/published) project memories come first, plus the default result cap of 8. It does not discuss latency or result volume beyond the limit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and return behavior, then usage and search strategy. Every sentence is functional, though the search-strategy sentence is dense and could be tightened slightly without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers scope of results, absence of output schema is compensated by 'Returns matching memories,' and ranking/default behavior is explained. An agent has everything needed to decide to call it and to call it well.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining how to phrase the `query` effectively (concepts, synonyms, shorter keyword forms) and reiterating the `limit` default and `type` restriction in context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (search persistent memory) and the retrieval method (BM25 full-text). It also scopes results to 'current project and/or personal scope,' which lets an agent separate it from memory_list or memory_forget without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear trigger condition: call before asking the user about past decisions, conventions, or preferences. Adds concrete search strategy (break into concepts, try 2-3 phrasings, check the other scope). It does not name which sibling to use instead when memory is absent, so it stops short of the top tier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statusARead-only
Show the project memory sync pipeline: drafts waiting in the outbox (appdata), memories in the repo awaiting review or published, and any repo files not yet committed. Call this at session start, when the server reports drafts waiting for review, or when the user says 'sync memory' (or '同步记忆'); then ask the user which drafts to sync. For the memories themselves use memory_list; for PR review state use memory_pr_status. (MCP server and the open-memex sync-status CLI; the opencode native plugin does not expose this tool.)
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=false, so the safe-read profile is already covered; the description adds genuinely useful context beyond that — next-step workflow and deployment scope (MCP server and CLI expose it, the opencode native plugin does not). It stops short of describing output shape or any rate/limit behavior, but for a zero-param status read that is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what the tool shows, then triggers, then alternatives. Dense but every sentence carries routing or behavioral value; the trailing parenthetical about which surfaces expose the tool is the only slightly expendable part, though it does prevent an agent from hallucinating availability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and no output schema, the description carries the burden of explaining what comes back, and it does by enumerating the three pipeline categories and the required follow-up (ask which drafts to sync). Complete enough to call correctly, though it could note whether the result is grouped or how to interpret an empty pipeline.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool applies. No misleading or missing parameter guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Show the project memory sync pipeline') and enumerates exactly what it surfaces: outbox drafts, repo memories awaiting review or published, and uncommitted repo files. This is clearly distinguishable from the siblings that manage memories rather than report pipeline state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger conditions (session start, when the server reports drafts awaiting review, when the user says 'sync memory'/'同步记忆') and names the alternatives for adjacent needs: memory_list for the memories themselves and memory_pr_status for PR review state. It even specifies the follow-up action (ask the user which drafts to sync).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_submitA
Move outbox drafts into the repo memory dir for review: copies the drafts in as proposed (or keeps a local approval), commits locally on the current branch, and moves the outbox originals out. Never creates a branch on its own — pass branch= only with the user's explicit approval for the full chain. Prints the push and PR commands — those need the user's explicit approval and are never run automatically. (MCP server and the open-memex submit CLI; the opencode native plugin does not expose this tool.) Unknown ids or a failed local commit abort the submit with the reason; nothing is published automatically.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Outbox draft ids to submit. | |
| base | No | PR base branch override. Default: the branch the submit ran on. | |
| branch | No | Create this branch and submit onto it. If omitted, submit stays on the current branch — branches are never auto-created. Only pass this when the user explicitly approved the full chain (branch + push + PR). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the flat safety flags; the description adds substantive behavior: local commit on the current branch, moving outbox originals out, aborting with a reason on unknown ids or failed commit, and no automatic publishing. This is rich disclosure well beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and tightly packed, though the parenthetical about MCP/CLI/opencode scope and the approval caveats make it longer than strictly necessary. Every sentence still carries useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by explaining what gets printed (push and PR commands) and the failure modes. For a multi-step mutation tool it covers everything an agent needs to call it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents ids, base, and branch (including the branch-approval caveat), making 3 the baseline. The description reinforces the approval semantics but adds no syntax or format detail the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource — moving outbox drafts into the repo memory dir — and enumerates the exact chain (copy in, commit locally, move originals out). An agent can distinguish this submit operation from sibling tools like memory_propose or memory_promote without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states explicit when/when-not conditions: pass branch= only with the user's explicit approval for the full chain, never auto-create branches, and push/PR commands require explicit approval and are never run automatically. It even notes the tool is exposed via MCP/CLI but not the opencode plugin.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_supersedeA
Replace an existing memory with a newer version. The old memory is kept as history (status: superseded) and retrieval returns the new one. Use when a saved fact becomes outdated and should be replaced rather than duplicated. Only active memories can be superseded; the new memory inherits type, tags, and aliases unless you pass replacements. An unknown id is reported back as a failure; nothing is written.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ID of the memory being replaced. | |
| tags | No | Optional tags for the new memory. | |
| type | No | Category of the new memory. Defaults to the old memory's type. | |
| aliases | No | Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match. Only used when the install has capture aliases enabled (init default). Send at most 4; extras and blanks are dropped silently, never an error. | |
| content | Yes | The new, corrected content. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the non-destructive history model (status: superseded), retrieval precedence, the active-only precondition, field inheritance for type/tags/aliases with override behavior, and failure semantics (unknown id reported as failure, nothing written). The destructiveHint=false annotation is corroborated rather than merely repeated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each carrying distinct information: purpose, when-to-use, precondition plus inheritance, and failure behavior. Nothing is redundant and the primary purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description covers failure behavior and history retention but does not state what a successful call returns (e.g., the new memory's id or status). For a mutation tool that is a small but real gap rather than a serious omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds inheritance semantics the schema does not spell out: the new memory inherits type, tags, and aliases unless replacements are passed. It doesn't clarify the aliases cap or indexing behavior beyond the schema text, so it stops short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (replace an existing memory) plus a distinct scope: the old memory is retained as history while retrieval returns the new one. It explicitly contrasts with the duplication route (memory_add) via 'replaced rather than duplicated', letting an agent separate it from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear condition for use ('when a saved fact becomes outdated and should be replaced rather than duplicated') and a precondition ('only active memories can be superseded'). It implies memory_add is the alternative but never names it or states when replacement should be avoided, so no explicit when-not rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.7.3- Changed
memory_add2 fields changed- changed
Input schema / properties / scope / descriptionPrevious value: -"Memory scope. `project` = tied to this repo. `personal` = global across all your projects. `user` is a deprecated alias of `personal`. Default: project."New value: +"Memory scope. `project` = tied to this repo. `personal` = global across all your projects. Default: project." - changed
Input schema / properties / scope / enumPrevious value: -[ - "project", - "personal", - "user" -]New value: +[ + "project", + "personal" +]
- Changed
memory_list3 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Max entries to list, newest first (default 20)." - changed
Input schema / properties / scope / enumPrevious value: -[ - "project", - "personal", - "user", - "both" -]New value: +[ + "project", + "personal", + "both" +] - added
Input schema / properties / type / descriptionAdded value: +"Only list memories of this type (e.g. decision, preference, gotcha)."
- Changed
memory_search3 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Max results to return (default 8)." - changed
Input schema / properties / scope / enumPrevious value: -[ - "project", - "personal", - "user", - "both" -]New value: +[ + "project", + "personal", + "both" +] - changed
Input schema / properties / type / descriptionPrevious value: -"Restrict to memories of this type."New value: +"Restrict to memories of this type (e.g. decision, preference, gotcha)."
11 tool updates
- First observed
memory_add - First observed
memory_forget - First observed
memory_list - First observed
memory_pr_status - First observed
memory_promote - First observed
memory_propose - First observed
memory_resolve - First observed
memory_search - First observed
memory_status - First observed
memory_submit - First observed
memory_supersede
TDQS
Scored across 11 tools
Most tools target a distinct action or lifecycle stage, but the sync/review tools (memory_status, memory_submit, memory_propose, memory_promote, memory_pr_status) are conceptually adjacent and require reading cross-references to select correctly. The descriptions explicitly disambiguate key pairs such as memory_forget vs memory_supersede and memory_status vs memory_pr_status, keeping confusion limited.
All 11 tools follow the same memory_ prefix with snake_case suffixes (memory_add, memory_search, memory_list, memory_forget, memory_supersede, etc.). The pattern is predictable and consistent throughout, including compounds like memory_pr_status.
At 11 tools, the set is well-scoped for a persistent memory server that includes core CRUD, search, and a review/sync pipeline. Each tool maps to a distinct operation and earns its place without bloat.
Core memory lifecycle is covered: add, search, list, forget, and supersede, plus review progression (propose, submit, promote), status inspection, conflict resolution, and PR-state mapping. Minor gaps exist (no direct edit/update of memory content or metadata besides supersede, no explicit get-by-id), but agents can work around them via search/list.
Maintenance
Related MCP Connectors
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Hosted MCP memory for coding agents: persistent across sessions, editable markdown, team sharing.
Long-term memory for AI coding agents: durable project facts, recalled by every MCP client.
shared AI-context layer for teams — persistent memory your agents search and update over MCP
Related MCP Servers
- AlicenseAqualityAmaintenanceMCP-native, local-first memory for coding agents that turns real sessions into reusable decisions, gotchas, and domain knowledge.1757 PyPI7MIT
- AlicenseAqualityAmaintenanceLocal, searchable project memory for AI coding agents. Markdown source of truth, MCP interface, safe structured updates315Apache 2.0
- AlicenseNot gradedqualityAmaintenanceLocal-first, file-based memory layer for AI agents — one shared Markdown vault across Claude, Codex, Gemini, Cursor and any MCP client. Provides read/write memory tools with an audit trail, per-agent trust levels, and Git sync; no cloud and no lock-in.2MIT
- FlicenseNot gradedqualityCmaintenanceLocal-first cross-agent memory for AI coding agents. Persistent, shared memory over MCP — what you tell one agent can be recalled by another — with all data stored in a single local SQLite file, no cloud and no API keys.-