Skip to content

Releases: stoneskin/open-memex

v0.7.2

Choose a tag to compare

@stoneskin stoneskin released this 04 Oct 21:06

Listed in the official MCP Registry

  • Added: open-memex is now published in the official MCP Registry as io.github.stoneskin/open-memex, so MCP clients and directories can discover and install it from the registry. The npm package declares the matching mcpName in package.json (the registry verifies package ownership against it), and the repo carries server.json with the registry metadata; its version fields move in step with package releases.
  • Release runbook: commands are now given one per step with explicit stop-and-check gates, including "wait for npm to propagate before mcp-publisher publish".
  • Added docs/release-runbook.md: the maintainer release checklist (version sync points, preflight, npm alpha/stable publish, MCP Registry publish, Node 22.14 floor notes).

v0.7.1

Choose a tag to compare

@stoneskin stoneskin released this 04 Oct 15:02

The Node floor is 22.14, because the driver says so (D74)

  • Fixed: every command could die with no output on Node older than 22.14. better-sqlite3 13 (the D72 N-API line) is compiled against Node-API 10, which Node only gained in 22.14.0. Below that, require() succeeds and the first new Database() segfaults the process - no message, no stack, exit 139 on macOS/Linux and 0xC0000005 on Windows. Reproduced on win32-x64 with Node 22.12.0; Node 22.23.3 and 24.20.0 are fine, and Node 20 can never work with v13 (upstream WiseLibs/better-sqlite3#1514, open). open-memex now refuses to load the driver below the floor and says exactly what to do (upgrade Node, or pin better-sqlite3@^12.11.1) instead of dying.
  • engines.node corrected to >=22.14.0. It claimed >=22.6, which was the --experimental-strip-types floor - a different constraint that predates the driver bump, and wrong for the driver.
  • open-memex doctor gained a sqlite driver check that loads the driver and opens an in-memory database in a child process (a segfault cannot be caught in-process) and reports the exit code or signal. It resolves the driver from this package's own directory, so it works when doctor runs with cwd set to a user project.
  • Both READMEs gained a troubleshooting entry for the crash signature (exit 139 / 0xC0000005 / "Segmentation fault"). No protocol, schema, or data change.

v0.7.0

Choose a tag to compare

@stoneskin stoneskin released this 04 Oct 07:39

One thing you said is one memory (D73)

Saying "remember ." used to save the same statement up to three times: the keyword hook stored your sentence verbatim with no agent in the loop, then the agent - which could see the chat but not the store - saved its own paraphrase beside it, and memory_add's near-duplicate check scored the two too far apart (0.21-0.38 against a 0.80 bar) to notice. open-memex audit reported zero near-duplicates while three copies sat in the folder, and search returned all of them.

  • The agent is told what was already stored. When the keyword hook captures a sentence, the plugin records it against the session and the next system context carries a short note naming the stored memory. Do not save that text again in any rewording; save only what it does not contain, or memory_supersede it. Delivered once per capture, in memory only (nothing new is written to disk).
  • memory_add refuses the echo anyway. A write that overlaps a memory captured from your own words in the same scope within the last 10 minutes is refused with the stored id, as a deterministic backstop for when the note is not enough. The bar is deliberately high (0.28 token overlap) and never applies to the agent's own inferences - a distinct fact the same sentence carried still saves normally. A refusal is recoverable: supersede the stored one, or re-save with only the new information.
  • Reports nothing and changes no data: existing memories are not merged or rewritten, and the near-duplicate notice for ordinary agent saves is unchanged.

Node 24 CLI aborts: SQLite driver moves to the N-API line (D72)

  • Fixed: CLI processes intermittently aborted on Node 24.19+. better-sqlite3 11 could finalize a prepared statement from a garbage-collection callback after Node's environment was gone (RemoveEnvironmentCleanupHook ... Assertion failed), killing the process with SIGABRT and losing its output even though the memory work had already landed. The driver is now better-sqlite3 13 (the N-API rewrite; Node �22 unchanged) - same API surface, no protocol or data change. If you build from source on Node 24.19+, reinstall dependencies so the new driver is picked up.

Non-git folders shared one scope bucket (D71)

  • Fixed: every non-git folder on a drive shared a single project scope. OpenCode v1 reports the filesystem root (C:\, /) as the project worktree when the opened folder is not a git repo, and the plugin seeded its scope on that root — so unrelated folders like C:\temp and C:\scratch all wrote to one project__workspace__… bucket. The scope now seeds on the folder actually opened (pickScopeRoot in src/scope.ts); real repo worktrees are unchanged. Memories already saved under the shared bucket are not moved automatically: run open-memex scopes to spot it, then open-memex migrate --from <old-key>.

Visibility follow-ups: one number, one guard, one truth (D70)

Review of the D68/D69 inventory surfaces — each was honest on its own, and they disagreed with each other:

  • open-memex list no longer truncates silently: it renders the same structured line the agent sees and says how many entries it left out (20 of 25 used to look like all 25).
  • Numbers are unique within one listing. memory_list(scope: both) and the text report restarted the counter per scope, so a single listing held two #1s and "delete #3" was a guess.
  • Hiding an in-repo memory now says what the delete path already said: the retraction is a local working-tree edit until you commit and push it — until then the team still sees the memory.
  • The report's worktree guard fails closed (it used to skip the check when the output directory did not exist yet), explains a missing directory instead of dying with a raw ENOENT, and is shared by all three formats instead of existing twice.
  • inventory --format json is now open-memex-inventory/2: the absolute file path is gone — that artifact is meant for an agent, and it carried your home directory with it.
  • An empty scope is reported as (0) rather than disappearing; only the HTML audit view loads the hidden rows themselves; the page enforces its "no network requests" promise with a default-src 'none' CSP.

Inventory HTML report (D68 follow-up)

  • open-memex inventory --format html renders the same data layer as the text/JSON formats into a single local page: current memories grouped by scope, outbox drafts in their own section, and the replaced/hidden history folded at the bottom with supersede-chain pointers. All content is escaped; the filter box is local show/hide only. Default output is <data dir>/inventory.html; the worktree refusal (--allow-personal) applies here too. Sections fold when the store grows past 50 current entries.

Memory visibility: see it, hide it, delete it (D68)

Group 3-C — the surface a user reads to learn what the store actually remembers:

  • memory_list is now a numbered inventory. Lines are structured ([type] id=… created=… source=…), keep the raw provenance, and every listing states its true total — a truncated list says how many entries it is not showing instead of quietly looking complete. New input include: "active" | "all" (default active): behavior change — superseded versions, retracted and archived memories no longer appear unless you pass include=all (the audit view). The CLI gains the matching list --include flag.
  • open-memex inventory renders the same data as readable text (default) or JSON (--format json, format open-memex-inventory/1) — personal plus the current project, outbox drafts in their own section, hidden history counted rather than silently dropped. A report containing personal memories refuses to be written inside a git working tree without --allow-personal.
  • Hide instead of delete: memory_forget gains soft=true (CLI: forget --soft) — the memory is retracted: out of lists and search, file kept. Still one-way (D64): bringing the fact back means saving it again.
  • Guidance kept in one voice: the tool descriptions, the MCP session-start instructions, SKILL.md and the distill-agents AGENTS.md snippet all teach the same flow — answer "what do you remember?" conversationally from the inventory, re-list before acting on a number, read an entry back before deleting it.

Keyword capture: what counts as a trigger (D67)

The D66 review left two questions open and introduced one regression. Ruled, not deferred:

  • Fixed a regression: D66's separator boundary was one notch too strict — it also demanded a separator after a complete verb phrase, so 帮我记一下这个配置, 帮我记住这个配置, 替我记一下我住在杭州 and 帮我们记一下这个约定 stopped matching. The boundary now guards the bare verb only, so 帮我记得… still can't produce mid-word garbage.
  • The ≥3-character body floor stays, but is no longer silent. 记住:这个 is a fragment, not a memory, so it isn't captured — but open-memex capture --dry-run now says why, and logLevel: debug logs it. A rejected personal match also keeps its line, so 记住我:OK can no longer fall through to the generic 记住 and be saved as 我:OK.
  • Narration is not a trigger. 记得…, remind me to… and friends stay out on purpose (a false trigger writes unreviewed memory; a missed one costs a sentence). The ambiguous forms already in the list now need an explicit marker: 别忘了:…, don't forget: … and don't forget that … capture; bare 别忘了带伞 and don't forget the wifi password do not. The note family is unchanged.
  • Test tooling: the stale-dist/ guard is now a content fingerprint (scripts/build-stamp.mjs) instead of mtimes, which a branch switch could defeat; the agent-facing memory_status cap (20 per section + a "full list" pointer) is pinned again after D66's test replaced that coverage.

Review follow-ups (D66)

Fixes from the follow-up review of the D63–D65 stack:

  • Keyword patterns: 请帮我记住… works (the D65 pattern had missed its 请 prefix), 帮我记录一下:… / 替我记录一下:… capture cleanly instead of saving mid-word garbage, 帮我记得… no longer fires, and help me remember: … routes personal like remember for me.
  • open-memex sync-status (the CLI) shows the full list again — the 20-per-section cap now applies only to agent tool results, whose "… and N more" line points at the CLI. open-memex list --scope both matches the memory_list tool.
  • open-memex status --help documents that retraction is one-way.
  • The full test suite is Windows-safe now (file:// probe imports, USERPROFILE-aware uninstall test) and refuses to run against a stale dist/ build.

Keyword capture gaps (D65)

The most natural phrasings were the ones that fell through:

  • 帮我记住… / 帮我记一下… now capture (personal scope, same 我-rule as 替我记; 帮我们记住… still routes project).
  • A leading 请 no longer defeats capture: 请记住我…, 请记住(个人)…, and 请记住:… all work.
  • English remember to … no longer leaves a stray "to" at the front of the captured body.

Patterns are code defaults, so these apply automatically on upgrade — unless you hand-customized keywordPatterns / keywordPersonalPatterns in your config, in which case your lists win and you can port the additions by hand.

P1 fixes: stale answers and stranded files (D64)

Second batch from the whole-project review — the index, the files, and the guidance can no longer quietly disagree:

  • The opencode plugin now re-syncs the index before every tool call (previously only at startup): memories added via the CLI or another client are visible right away instead of after a restart.
  • Superseding a published memory re-enters review as proposed instead of a stranded draft no command could advance; promote can move it forward again.
  • All memory-file rewrites are atomic (tmp + rename), not just creates.
  • A retracted memory can't be flipped back to active via status changes — save a new memory if the content is valid again.
  • Proposed copies of personal memories are visibility: internal (was: `priva...
Read more

v0.6.2

Choose a tag to compare

@stoneskin stoneskin released this 03 Oct 16:38

Doctor patrols the plugin entry (D59)

  • open-memex doctor gains an opencode plugin check: it reads the user-level opencode configs, attributes the open-memex plugin entry, and fails when the target file no longer exists (naming the open-memex init --client opencode --global --force re-point command) or when the plugin's import closure runtime-imports the host SDK. That second failure is exactly what silently killed the plugin in D58 — it now shows up in a check instead of surfacing as missing tools.

Notes

  • 0.6.1 contained D56–D58 but was published before this check landed; 0.6.2 is the recommended upgrade for everyone on the 0.6.x line.

v0.6.1

Choose a tag to compare

@stoneskin stoneskin released this 03 Oct 16:06
d6c971f

Question-shaped search, host parity said out loud (D56)

  • Search no longer feeds whole questions straight into full-text: query construction filters English/CJK function words, dedupes terms, and caps them — asking "how do we configure…" or "中文记忆怎么检索" now ranks the right memory first instead of matching everything
  • The six MCP-only tools now say so in their own descriptions and name the CLI equivalent, so opencode plugin users see the asymmetry is by design instead of assuming breakage
  • init's closing lines state the privacy model in plain words: memories live only on this machine, personal ones never leave it, nothing is uploaded

Search explainability and memory audit (D57)

  • open-memex search "deploy" --explain shows the constructed FTS expression, per-hit scores, and how many matches lifecycle hid (superseded vs retracted/archived) — a miss is now diagnosable
  • New open-memex audit (read-only; doctor checks the environment, this checks the memories): near-duplicate active pairs, memories untouched for 90+ days, broken supersede chains, personal files found inside the repo memory dir, index/file drift
  • Concurrency posture measured and hardened: WAL everywhere, busy_timeout unified at 5s across backends (the opencode plugin's bun:sqlite defaulted to 0 — any overlapping write failed instantly), memory files written via tmp+rename, lock timeouts reported in one plain line, doctor reports the live locking settings

Critical fix: opencode plugin silently dead on global installs (D58)

  • After a global npm i -g open-memex, the opencode plugin was configured but silently inactive — no memory tools, no error, nothing in the log. Root cause: the plugin runtime-imported the host SDK (@opencode-ai/plugin is a devDependency; nothing resolves it from a global install, and opencode skips the plugin without a trace). The import is gone — the SDK helper is a runtime identity, now a local stand-in. If your opencode shows no memory tools, update to 0.6.1.

v0.6.0

Choose a tag to compare

@stoneskin stoneskin released this 02 Oct 03:23
6c18e7f

First-run onboarding (D50, D51, F28)

  • open-memex init is now a guided first run: the postinstall note points at init, every CLI entry prints a one-line stderr nudge until init has run or been declined (stderr keeps the MCP stdio protocol intact), and init ends with a next-step hint (open-memex add + ask the agent what it remembers)
  • Bare open-memex on a machine where init never completed offers to run it on a TTY; init/uninstall maintain a .init.json first-run marker so the offer is asked once

Agent prompt clarity (D52)

  • MCP tool descriptions rewritten for clarity

Push-not-poll outbox (D53)

  • New project memories land in a local outbox (invisible to git); open-memex sync-status shows drafts waiting and open-memex submit publishes them — the agent checks on demand instead of polling

Agent Skills (D54, D55)

  • New bundled open-memex skill (skills/open-memex/SKILL.md): teaches skill-aware agents the CLI (save/search/scope rules/outbox flow), preferring MCP tools when available; init installs it per editor, uninstall removes it
  • opencode with the native plugin wired no longer gets the skill — the plugin already provides memory tools, and the duplicated guidance made the agent chatty

Rename leftovers swept (F30)

  • The my-o-memory → open-memex rename left editor configs loading the OLD plugin/server, silently splitting memories across two data dirs; init/uninstall now drop stale my-o-memory entries wherever they touch a config, and doctor reports leftovers via a read-only legacy my-o-memory check

Fixes (F29)

  • Copilot review fixes, package-lock.json repair, Visual Studio onboarding strings

v0.5.1

Choose a tag to compare

@stoneskin stoneskin released this 01 Oct 01:52
044945a

Docs review (F1–F27)

  • Full documentation pass: stale versions corrected (README now shows 0.5.0), roadmap extended with 0.5.0 (D45–D49), branch rules updated after the V2 branch retirement, MCP server tool count fixed to 11, USER-GUIDE cleaned of V2-dev leftovers

mcp --help accuracy (F27)

  • --help now states the MCP server exposes 11 tools (a superset of the opencode plugin's five memory_* tools); install hints point at the stable line instead of @alpha

doctor: VS Code MCP-disabled check

  • open-memex doctor now fails with a clear message when VS Code has MCP disabled — via chat.mcp.enabled: false in user/project settings.json, or a Windows registry policy (HKLM/HKCU\SOFTWARE\Policies\Microsoft\VSCode)

v0.5.0

Choose a tag to compare

@stoneskin stoneskin released this 30 Sep 02:48

One config for every project (D45)

  • open-memex init --global: writes editor wiring once at user level — one setup, every project covered
  • npm install -g open-memex puts the command in your PATH; init --global wires your editors. README install chapter rewritten to keep the two straight

Smarter init (D46 / D47)

  • Bare open-memex init auto-detects installed editors and wires all of them — no more "which client?" for every project
  • Non-strict-JSON configs (JSONC comments, trailing commas): init leaves the file untouched and prints a ready-to-paste snippet instead

uninstall (D48)

  • New open-memex uninstall [--client ...] [--global] [--yes]: removes wiring symmetrically with init, never touches memory data

Empty-file fix (D49)

  • Empty or whitespace-only config files are treated as blank, not corrupt — init writes into them directly (previously refused with "not valid JSON")

Docs

  • FAQ merged into the bilingual README (EN + zh-CN); install chapter rewritten; full init synopsis documented

0.4.0

Choose a tag to compare

@stoneskin stoneskin released this 29 Sep 14:52
f7baf5e

Team sync via git

  • Draft outbox (appdata project/) → sync-status → submit → promote / resolve: shared memory flows through git branches and PR review, just like code
  • Fast-forward-only pulls, no auto-push — conflicts stop and ask, never overwrite
  • memory_status checkpoints: after commits, work chunks, and memory actions

Portable archives

  • export / import: .tar.gz + manifest.json; visibility: private excluded by default, --all for full migration

Capture loop closed (D42/D43)

  • §3.5 checkpoint distillation taught in the MCP handshake instructions and init-written instruction files: the agent proposes 1–3 distilled captures at checkpoints, nothing saved without approval
  • distill-agents output now ends with a "Memory hygiene" section, so opencode users reading AGENTS.md get the checkpoint habit too

Also in this release

  • 11 memory types (fact preference decision constraint todo knowledge howto gotcha lesson observation reference)
  • README overhaul, fully bilingual (EN + zh-CN): why open-memex, 11 tools, architecture diagram, stable vs @alpha install channels
  • MCP server: 11 tools, re-synced per request; CLI: 26 commands, each with full --help

Install: npm install -g open-memex