Skip to content

Releases

v2.0.1

Choose a tag to compare

@cioffiAI cioffiAI released this 13 Oct 10:05
1ed08b7

Fixes

  • Projects below the git root. OpenCode reports snapshot.files and vcs.status relative to the repository root, so in a project that is a subdirectory of the repository the touched files, the handoff file statuses and the anchor candidates offered to DREAM were wrong. They are now resolved against the worktree root and mapped to project-relative paths; files outside the project are dropped.

See CHANGELOG.md.

v2.0.0 — rem-memory

Choose a tag to compare

@cioffiAI cioffiAI released this 13 Oct 10:00
d9aa9ce

@cioffi_ai/opencode-memory continues as rem-memory 2.0 (OpenCode V2 only).

Highlights

  • Code-anchored memories: project facts can point at path#symbol; state (fresh / drifted / broken) is derived on every read, broken anchors are not surfaced, memory_inspect({ show: "stale" }).
  • Session handoff: a mechanical "where were we" note on session completion, enriched by DREAM at no extra model call, injected once on the next session's first request; new memory_handoff tool and /memory resume.
  • Built-in /memory command (no manual copy); command: false to keep a custom one.
  • DREAM works on OpenCode's free tier: internal generation moved from generate.text (rejected there) to session.generate, with system prompt and conversation stripped; tools are never executed.
  • Host-neutral engine (src/engine) behind a Host interface, ready for other agents.

Breaking

  • Package renamed to rem-memory; OpenCode V1 adapter removed.
  • REM_MEMORY_* env vars (OPENCODE_MEMORY_* still read with a deprecation warning).
  • Default dir ~/.local/share/rem-memory, one-time copy of the old store (old dir untouched).
  • Store schema v3 (1.7.3 refuses it instead of reading it as empty).

See the upgrade guide in the README and CHANGELOG.md.

Verification

  • bun run check: 252 tests pass; retrieval benchmark (dev + held-out) byte-identical to 1.7.2.
  • verify:package against the real OpenCode 2.0.18 CLI with a local mock model.
  • End-to-end with the free muse-spark-1.3 model: anchors fresh/drifted/broken, mechanical + DREAM-enriched handoff, first-request injection, /memory resume (11/11).

v1.7.3 — final 1.x release

Choose a tag to compare

@cioffiAI cioffiAI released this 13 Oct 10:00

Final release of @cioffi_ai/opencode-memory. The package continues as rem-memory 2.0 (OpenCode V2 only); see the upgrade guide.

Fixes

  • A store written by rem-memory 2.x (schema version 3 or later) is no longer read as an empty store, which let the next write overwrite every fact. 1.x now refuses to read or write it and reports an error instead.

Stay on 1.7.3 only if you still run OpenCode V1.

v1.7.2

Choose a tag to compare

@cioffiAI cioffiAI released this 30 Sep 09:03
22e5744

Fixes

  • #11 — Parallel memory writes: distinct explicit facts no longer overwrite one another because of similar wording. Jack's exact Promise.all example now preserves both preferences. Identical text still refreshes an entry; use memory_update by ID for corrections.
  • Mutations queue across plugin instances sharing a directory, avoiding local lock-retry timeouts while retaining cross-process filesystem locking.

Summary controls (#12)

  • Set summary: false in plugin options or OPENCODE_MEMORY_SUMMARY=0 to hide the stored summary from model context and memory_read, and prevent DREAM from generating or updating it.
  • memory_clear({ summaryOnly: true }) erases only the shared summary, retaining all facts. Do not combine it with scope.
  • Disabling the summary preserves it on disk. If summary/DREAM remains enabled, a later consolidation can generate it again after clearing.

Both OpenCode V1 and V2 adapters support these changes.

Verification

199 tests passed; 2 existing live-server tests skipped. Typecheck, build and clean packed-package checks passed for both adapters. Real OpenCode V2 2.0.18 checks passed with a local deterministic model, including Code Mode parallel writes, summary controls, DREAM, context injection, store migration and local-only privacy. Real V1 CLI coverage was unavailable; V1 adapter and isolated-package checks passed.

Install or update to @cioffi_ai/opencode-memory@1.7.2 and restart OpenCode.

v1.7.1

Choose a tag to compare

@cioffiAI cioffiAI released this 29 Sep 08:15
5bcde46

What's new

  • DREAM and SURFACE can be switched off independently while explicit memory tools remain available (#8).
  • Every memory setting can be configured in opencode.jsonc for OpenCode V1 and V2. Plugin options take precedence over environment variables and are isolated per plugin instance (#9).
  • Existing environment switches keep their 1.7.0 behavior.

Verification

  • 181 tests passed; typecheck and build passed.
  • The npm tarball installed and exercised the V1 and V2 adapters in an isolated directory.
  • OpenCode V2 2.0.18 passed live checks with automatic memory active and with DREAM/SURFACE disabled through opencode.jsonc using a local mock model.

OpenCode V1 was checked through the adapter and isolated package tests; a real V1 CLI was not available for this release.

v1.7.0 — OpenCode V2 compatibility

Choose a tag to compare

@cioffiAI cioffiAI released this 28 Sep 11:05
876d8e1

OpenCode V2 can now load @cioffi_ai/opencode-memory without the default-export error reported in #6. The same package retains the OpenCode V1 adapter for 1.18.29+.

Highlights

  • Native V2 id/setup adapter registers all nine memory_* tools, context hooks and event handling.
  • DREAM handles V2 session.execution.* completion events. V2 internal generation runs without helper sessions or exposed tools; V1 keeps its existing allow-none child sessions.
  • The package also exposes ./server for V2 directory loading and cleans up registrations on unload.

Install

For OpenCode V2 2.0.18+, add @cioffi_ai/opencode-memory@1.7.0 to the plugins array and restart OpenCode. OpenCode V1 1.18.29+ uses the singular plugin key.

Verification

The published npm package is byte-identical to the files and built bundle from merge commit 876d8e1. bun run check passed (168 tests; 2 live-server tests skipped). The downloaded package passed V1/V2 adapter checks: nine tools, V2 read/write, legacy store migration, context injection and cleanup. See CHANGELOG.md for details.

v1.6.0 — Retrieval Evaluation / Relevance

Choose a tag to compare

@cioffiAI cioffiAI released this 18 Sep 07:29

[1.6.0] — 2026-09-18

Retrieval Evaluation / Relevance. Retrieval semantics change (user-visible);
API compatible. No new features; no new packages (the plugin's runtime
dependency is now declared correctly, see below).

Fixed

  • memory_read multi-term queries (issue #4). readQuery keeps the
    legacy contiguous substring match and adds an all-terms whole-token path:
    coffee morning matches "coffee in the morning" (any order,
    non-contiguous) while short and technical terms are not dropped (AI,
    UI, DB, C, R, no, C++, C#, Node.js, .NET). No stemming,
    synonyms or accent folding; scope/category filters, score ordering and the
    privacy policy are unchanged. Covered by tests/read-query.test.ts.
  • Identifier tokenization is symmetric in memory_read. Query and memory
    go through the same word grammar: a camelCase identifier matches its compact
    form OR all of its case-boundary parts, so JavaScript matches both
    "JavaScript" and "javascript"/"java script" and userStore matches
    "user store" (one half alone never satisfies it; query casing cannot change
    the outcome). Same coverage in tests/read-query.test.ts.
  • Unsafe substring matching removed. The matcher now respects token
    boundaries: use no longer matches user, test no longer matches
    pytest/greatest, red no longer matches redesign. Confirmed by the
    v1.5.1 evidence file bench/evidence/v1.5.1-fp-taxonomy.json.
  • Synonym groups restricted to substitutable terms. Opinion/preference
    verbs were removed from the color group (they bridged "color" queries to
    unrelated "favorite X" facts); design and project families are split;
    the standalone Italian word banca no longer expands to database terms;
    the dead phrase member "sistema operativo" was dropped.
  • camelCase identifiers tokenize correctly: the boundary splitter only
    splits at lowercase→uppercase transitions ("RAM", "GB" stay whole;
    "userStore"/"JavaScript" produce both parts and the whole form).
  • Runtime dependency declared (issues #2/#3). @opencode-ai/plugin is
    imported at load time by the published dist/index.js, so it moved from
    devDependencies to dependencies: a clean install of the tarball now
    resolves it. New release gate bun run verify:package (wired into
    prepublishOnly) builds, packs, installs the tarball outside the checkout,
    imports it by package name, asserts the nine memory_* tools are
    registered and calls dispose() to release the timers.

Changed

  • Candidate generation is separated from surfacing relevance.
    retrieve() returns high-recall candidates; a named single-source
    relevance gate (passesRelevanceGate) decides what enters the injected
    block, shared by the plugin and the benchmark harness.
  • Every match carries provenance (keyword, kind
    exact/inflection/category, direct, via query term):
    bun run bench --explain-negatives [--heldout] [--fp-only] emits the full
    machine-readable taxonomy of what surfaced and why.
  • Morphology is explicit: plural s/es/ies, gerund -ing and participle -ed
    match in both directions; nothing else does.
  • Reranker extracted to src/rerank.ts with an injectable client:
    abstention, invalid-answer fallback, timeout fallback, per-query caching,
    zero-tool containment propagation and local-only filtering are unit-tested
    with deterministic fakes (tests/reranker.test.ts). Behavior unchanged.
  • Benchmark: added Recall@1, entry-level surface precision with pooled
    counts, false-abstention rate on positives, memory-level FP counts,
    negative-outcome breakdown (abstained / core-only / non-core surfaced),
    Wilson 95% confidence intervals, average memories surfaced; separate
    HELD-OUT evaluation set (bench/scenarios-heldout.ts, --heldout)
    written before the fixes and not iterated against.

Measured (lexical pipeline, reranker disabled)

metric v1.5.1 v1.6.0
Recall@5 (dev) 100% 100%
MRR (dev) 95.2% 95.2%
Surface precision macro (dev) 65.8% 63.2%
FPR negative queries (dev) 39.5% (15/38) 34.2% (13/38)
FPR held-out 46.7% (7/15) 26.7% (4/15)
False abstentions (dev) 26.0% (20/77) 31.2% (24/77)

The four new false abstentions (kw-02, pa-10, co-05, ob-05) all relied on the
removed substring behavior: use matching inside the universal "user" token
(kw-02, co-05, ob-05) and uni matching inside "university" (pa-10).
All 13 remaining dev-set failures are exact-token or true-translation matches
whose intent differs — documented as the lexical ceiling; embeddings are NOT
yet justified by this evidence.

v1.5.1 — Trust Boundaries

Choose a tag to compare

@cioffiAI cioffiAI released this 26 Aug 12:37

Trust-boundaries hardening release. No new features; every change tightens an
existing guarantee.

Fixed

  • Project isolation enforced end-to-end. memory_read previously returned
    project-scoped entries of ALL projects (no directory filter); the project
    inspector view listed other projects' entries; memory_clear(scope="project")
    deleted every project's memories, not just the current project's;
    memory_update / memory_forget / feedback tools could mutate another
    project's entries by id or text match. All lookups now go through a single
    visibility policy (readableEntries / readQuery / clearProjectEntries in
    core.ts): global + current project only. Regression-tested with two
    distinct directories plus global entries.
  • DREAM cross-project contamination. Consolidation dedup searched the whole
    store: a fact extracted in project A could refresh/rewrite project B's
    dreamed entry, be suppressed by B's explicit entry via similarity or topic
    clash, or update/supersede/flag entries it was never shown. All consolidation
    lookups are now restricted to the consolidating session's visible set.
  • memory_write rewrite targeting. A write with an explicit scope could
    overwrite a semantically similar entry from a DIFFERENT scope/project;
    rewrite-dedup is now same-scope + same-project only (global and equivalent
    project facts coexist by design).
  • Relevance gate silently defeated. The word "user" (and "utente") was not
    in the retrieval stopword list while nearly every stored fact contains it, so
    any query mentioning "user" matched every entry and the keyword relevance
    gate introduced in 1.5.0 never actually gated anything. Found by the new
    falsifiable benchmark (negative-query FP rate dropped from 76.3% to 39.5%
    after the fix, Recall unchanged at 100%).

Changed

  • Surfacing no longer refreshes recency. Automatic exposure used to bump
    lastSeen, letting frequently surfaced memories stay artificially fresh
    (a self-reinforcing retrieval loop, immortal under pruning). Exposure is now
    recorded separately (lastSurfaced, surfacedCount) and never affects the
    score; only explicit confirmation (memory_useful, writes,
    consolidation refreshes) resets decay. Negative feedback never touches
    recency.
  • Semantic reranker can abstain. With OPENCODE_MEMORY_RERANK=1 the
    reranker may answer {"order":[]} when no candidate answers the question;
    abstention surfaces nothing beyond the core slot instead of forcing a
    ranking. Unparseable output still falls back to the deterministic lexical
    order. Rerank orphan children are now garbage-collected like consolidation
    ones.
  • Falsifiable benchmark. bench/run.ts rewritten around a pure harness:
    the old "false-surface rate" counted unsupported surfacing AFTER the keyword
    gate had already filtered those entries (0.0% by construction). The suite now
    has 38 negative scenarios across six categories that can genuinely fail
    (clean no-match, hard lexical negatives, semantic distractors, cross-language
    collisions, project-isolation negatives, core-only queries) and reports
    separately candidate quality (Recall@5, MRR), surface precision, false-
    positive / abstention rate and context overhead. Positive scenarios are
    unchanged.

Security

  • DREAM child sessions run with zero tools. The headless consolidation,
    semantic-dedup and rerank sessions previously disabled only the five memory
    tools by name — shell, filesystem, network fetch, MCP and subagent tools
    remained available to a session processing untrusted conversation text.
    They are now created with a single wildcard denial (tools: {"*": false}),
    verified against OpenCode server source v1.18.0–v1.18.20 to remove the
    entire toolset from the model-visible request (allow-none). Crash recovery,
    orphan GC and at-least-once semantics are unchanged. A contract test pins
    the deny-all shape so per-tool enumerations cannot creep back.
  • Honest local-only privacy contract. The previous claim "never leave
    the machine" was not enforceable: memory_read returned local-only entries
    as tool output (which reaches the provider), and the DREAM dedup prompt
    included them among existing entries. Local-only entries are now excluded
    from EVERY model-visible path: SURFACE injection, DREAM entries and dedup
    prompts, rerank candidates, all tool responses (memory_read,
    memory_why, memory_inspect) and all mutating tools. The documented
    access path is direct human inspection of OPENCODE_MEMORY_DIR; remaining
    limitations (the write call itself, prior transcript exposure, summary
    generation by the provider) are documented in the README threat model.

v1.5.0

Choose a tag to compare

@cioffiAI cioffiAI released this 11 Aug 14:30

Local-first persistent memory for OpenCode — decay fix, provenance, contradiction lifecycle, memory tiers, hybrid retrieval, per-fact privacy and an evaluation suite.

What's new in 1.5.0

  • Decay fix: time-based decay now applies exactly once in score() (from lastSeen); weight is a static importance baseline, so forgetting no longer depends on how often pruning runs.
  • Provenance: dreamed facts record their source session, messages, extraction time and confidence; new memory_why tool audits where a memory comes from and why it ranks where it does.
  • Contradiction lifecycle: conflicting explicit facts are flagged CONFLICTED (never silently overwritten) and resolved via memory_update/memory_write; replaced dreamed facts become SUPERSEDED tombstones.
  • Memory tiers: core (always surfaced) / archival (on relevance) / temporary (auto-expiry) / pinned (never decays), with automatic v1 → v2 store migration.
  • Hybrid retrieval: lexical pipeline (scope filter + bilingual keyword expansion + time score) with optional semantic reranking stage (OPENCODE_MEMORY_RERANK=1); off-topic queries surface only the core slot.
  • Retrieval feedback: memory_useful / memory_irrelevant tune ranking from real usage.
  • Per-memory privacy: sensitivity: "local-only" facts never leave the machine — not surfaced to providers, not sent during consolidation.
  • Memory Inspector: /memory with stats, conflicts, project scope and "why was this surfaced" breakdown.
  • Evaluation suite: bun run bench — 90 scenarios across 13 failure modes (paraphrase, IT/EN cross-language, synonyms, distractors, contradictions, duplicates, isolation, obsolete, false positives, none, feedback, multi-expected).

Benchmark (lexical pipeline, suite of 90)

Recall@5:         100.0%
MRR (first hit):    95.0%
False-surface rate:  0.0%
Context overhead:   13.8 tokens/query

Install: add @cioffi_ai/opencode-memory to plugin in ~/.config/opencode/opencode.json(c) (or update your cached version to 1.5.0).

v1.1.0

Choose a tag to compare

@cioffiAI cioffiAI released this 06 Aug 14:06

Local-first persistent memory for OpenCode.

  • WRITE → DREAM → SURFACE lifecycle
  • Local JSON storage with file locking, no external database
  • Headless child-session consolidation (at-least-once, crash recovery)
  • Cross-language semantic deduplication with explicit-wins source hierarchy
  • Topic-aware retrieval with bilingual (EN/IT) synonym expansion
  • Orphan child-session GC
  • Privacy: data stays on disk; only DREAM processing goes through your configured provider

Install: add @cioffi_ai/opencode-memory to plugin in ~/.config/opencode/opencode.json(c).