All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.9.7 - 2026-09-28
- Add conventional server and TUI entrypoints so OpenCode 2 loads the plugin when configured as a local package directory, including an installed tarball.
- Exercise packed V1 hooks, assets, and TUI loading plus V2 tool schemas and execution; verify real V2 host activation without optional SDK peers.
- Require runtime dependencies except explicitly host-provided modules, preserve the smoke subprocess's isolated memory root, and check probe exit status.
- Run the isolated smoke install even when the outer package command is a dry run.
0.9.6 - 2026-09-28
- Install
zodwith the plugin so V1 tool definitions and V2 tool adapters load in a standalone OpenCode plugin cache.0.9.5declaredzodas an optional peer that the plugin cache never installs, so loading it failed.
0.9.5 - 2026-09-28
- OpenCode 2 consolidation no longer fails with
Permission denied: editwhen the global memory home sits inside the session or project directory, such as running OpenCode in the user home. Helper sessions now also allow the session-relative form of their one memory root;external_directorystays absolute and traversal above the root stays denied. Memory remains global. Reported in #7.
0.9.4 - 2026-09-27
- Codex memory exchange runs for each active writer. A Memory V2 writer receives the same copies under its extensions folder and folds them into the summary. It does not create a handbook. Export from Memory V2 offers a valid summary only.
0.9.3 - 2026-09-27
- Codex memory exchange follows
$CODEX_HOME/config.tomlmemories.version. Memory V2 importsmemory_summary.mdonly and does not treat a leftovermemories/handbook as the live store. Export lands in that same store.
- Consolidation regression coverage for failed and interrupted host turns, incomplete replies, tool continuations, and legitimate completed no-ops in both memory versions. Investigation prompted by Tony-ooo's report in PR #6. Completion remains based on host lifecycle state, matching Codex, rather than requiring artifact changes or a special no-op acknowledgement.
0.9.2 - 2026-09-26
- OpenCode 2 memory tool metadata is normalized to JSON before returning it to the host. Optional search fields no longer prevent success events from being persisted, leaving tool calls running with no output for the next turn.
- Removed context-hook re-execution of unanswered memory calls. Request preparation no longer reads disabled memory, replaces historical results, or advises retrying a write whose outcome is unknown.
0.9.1 - 2026-09-26
- OpenCode 2 memory tools stay on the normal tool list. They were only inside
Code Mode
execute, so the agent often reported that memory tools were not in the runtime and skipped them.
0.9.0 - 2026-09-23
- OpenCode 2 no longer shuts memory down in every project when one idle project is unloaded. Memory panel toggles survive other projects starting and apply to all open projects.
- OpenCode 2 stops consolidation helpers in the process that runs them before deleting them through the registered service, so a helper cannot keep editing after its lease is released.
- Secret redaction matches codex for values on the line after
password:/token =style keys. - Notes added while consolidation runs are consolidated on the next run instead of being folded into the baseline unseen.
- A consolidation lease is released as orphaned only when its owner is on this host, its process is gone, and its heartbeat is stale, so sandboxed peers sharing the memory database keep their lease. The sweep also runs before each consolidation attempt, not only at startup.
- OpenCode 2 keeps the HTTP status of failed extraction requests, so provider 429s trigger the quota backoff instead of burning retries.
- A request too large for the model's per-minute or context limit is no longer treated as a quota outage. It uses the normal retry budget instead of retrying forever and pausing all other extraction each time. Errors that merely mention "quota" are no longer classified as capacity failures.
- Extraction stops 10 minutes before its job lease expires, so another process cannot reclaim the job mid-run and discard the finished result.
- Claude Code import streams session transcripts to find a project's directory instead of loading each whole file into memory.
- Closer codex parity: marking a consumed session as polluted re-queues
consolidation right away instead of waiting out a retry backoff; compaction
summaries no longer duplicate conversation in extraction input; raw
memories sort by session id in byte order and pruning breaks ties like
codex; the V1 extraction schema allows a null
rollout_slug; the Memory V2 read-path prompt keeps codex's explicit remember/forget/correction trigger for notes. - The memory summary cache also notices rewrites that keep the same modification time. Freed database pages are returned after pruning. Helper sessions are no longer tracked forever on hosts that cannot confirm deletion.
- Builds start from a clean
dist/, so stale compiled files no longer ship in the npm package (0.8.4 included an unusedlocal-session-times.js). - OpenCode 2 without a registered service reads transcripts from the compacted session context; extraction now keeps the compaction summary there instead of silently losing everything before it.
- OpenCode 2: a text part that contained only a citation block is dropped
instead of being sent to the model empty; title requests also have citation
markup stripped. IPv6 loopback services (
[::1]) are recognized as local. The event stream is re-subscribed if the host ends it, and shutdown no longer waits out a pending retry delay. Aborted extraction requests no longer leave listeners behind, and bursts of status updates are coalesced.
memory_resetasks you to approve the wipe; the model'sconfirmargument alone no longer erases memory. Re-enabling a session that was excluded for external context also needs approval.- On OpenCode 2, which cannot ask for approval from plugin tools, the agent no
longer gets
memory_reset. The memory panel has a Reset memory control with a second-press confirmation instead.
0.8.4 - 2026-09-22
- The OpenCode 2 memory panel separates extraction retries from queued consolidation and its normal cooldown, labels recap counts as total stored, and shows extraction failure reasons. Retry status includes both active learning pipelines during dual-write.
0.8.3 - 2026-09-22
- OpenCode 2 service discovery uses the current
/api/infoendpoint, with legacy readiness routes retained for older hosts. Removed/api/statusroutes no longer silently restrict extraction to locally observed sessions. memory_inspectand the OpenCode 2 memory panel report degraded global discovery and its failure reason, clearing the warning after recovery.- OpenCode 2 extraction retains the requested JSON schema and restates the extraction task after historical conversation data, preventing replies that continue old user requests instead of extracting memories.
- Lifecycle tests retain their temporary memory root until background work finishes, preventing teardown from pruning the user's generated memory files.
0.8.2 - 2026-09-22
- The OpenCode 2 memory panel opens with
/memory-inspector Inspect memory in the command palette, replacing/memoryand/memory-status. - The sidebar distinguishes memory recall from background learning. Panel controls explain their scope, persistence, and availability.
- Memory panel keyboard navigation works inside the modal, including tab switching, control selection, activation, scrolling, and refresh.
- The panel adapts to smaller terminals with scrollable content and pinned navigation. Selection colors follow current and older OpenCode themes.
- Loading, pending changes, and rejected actions show explicit feedback. Connection failures retain the last known status and pause controls until recovery; late responses cannot overwrite newer status or reopen a closed panel.
- CI type checking no longer requires a prior build of the OpenCode 2 contract-check dependencies.
0.8.1 - 2026-09-21
- OpenCode 2 consolidation verifies the submitted turn's terminal outcome before accepting artifacts or clearing the workspace diff. Failed turns preserve pending notes and provider errors for retry handling.
- Claude import aborts pruning on discovery I/O errors and preserves scoped resources when the original project directory is unavailable.
- OpenCode 2 consolidation agents can read the memory root and use glob/grep. Search paths remain confined to each helper's assigned memory workspace.
- Reasoning variants resolve through the current OpenCode 2 model API, with compatibility for older catalogs and selectable model aliases.
- Failed OpenCode 2 service connections are rediscovered on subsequent calls, including after service restarts and credential rotation.
- Citation cleanup handles model-bound OpenCode 2 message shapes without double-counting durable citation usage.
- Toggling memory reading in OpenCode 2 refreshes the tool registry immediately and restores the previous setting if the refresh fails.
- Creating a test sandbox no longer triggers an implicit plugin build, preventing clean-checkout unit-test timeouts.
- Documentation starts with installation and working defaults, with separate configuration, usage, troubleshooting, and memory-version guides. The version guide explains the corresponding Codex origins of both memory implementations.
- Type checking now covers tests and scripts as well as shipped source files.
0.8.0 - 2026-09-20
- Codex memory V2: provenance-ranked extraction, bounded session recaps,
summary-only consolidation and recap-oriented retrieval in isolated
memories_v2/andmemory_v2.db. V1 remains the default. dual_writemigration mode runs both learning pipelines independently. Inspect and the OpenCode 2 memory UI report each pipeline and V2 readiness (valid summary plus a successful consolidation of 20 distinct sessions).- Explicit read-version cutover for new sessions; existing sessions retain their namespace for injection, tools, notes and citations across reloads.
- Both OpenCode hosts share pipeline scheduling with async-local namespace routing, independent DB handles and worker guards, and per-job memory-root permissions. Session exclusion metadata remains shared.
- Reset and session deletion cover both namespaces; reset also clears readiness progress and citation dedupe while preserving session modes and routing.
- Live e2e tests cover dual-write warmup and explicit V2 cutover on both hosts.
- Live e2e accepts a clean cooldown-pending Phase 2 as consolidated. A late
extraction may re-enqueue consolidation after a successful run, leaving the
job pending with no error; Codex treats the workspace diff as the dirty
check, so the harness no longer requires a literal
status=done.
0.7.7 - 2026-09-19
- OpenCode 2 extraction preserves reasoning variants when a complete model reference is available and avoids invalid variant-only model references.
- Sessionless OpenCode 2 extraction releases its synthetic helper locally, avoiding spurious host-session cleanup failures.
- Live e2e/readpath auth comes from
.env(OPENCODE_LIVE_API_KEY,OPENCODE_LIVE_BASE_URL,OPENCODE_LIVE_MODEL) and an OpenAI-compatibleliveprovider in the XDG sandbox. Host OpenCode sqlite /auth.json/ OAuth are not read.opencode servehealth probes/openapi.json. memory_inspectseparates live extraction failures from leftover exhausted jobs older thanmax_rollout_age_days, labels pending jobs whose retry window has elapsed asdue, and states Phase 2 idle/cooldown instead of a barepending. Discovery is this process's session list (not total chats) and no longer logs the same count on every cache hit.- Live tests load one explicitly configured plugin package on both host generations, verify that OpenCode 2 receives model options, and wait for completed replies to the current prompt. Permission grants remain scoped to the interactive agent so memory helpers retain their file-tool sandbox.
- Live e2e coverage verifies automatic learning from implemented tasks, fresh-session recall, citations, explicit "remember this" requests, and reset. Hard failures retain their sandbox for diagnosis; OpenCode 2 contract checks use an isolated host.
0.7.6 - 2026-09-19
- V2 citation instructions now require a blank line before the
memory-citationfence so markdown clients (OpenCode web) parse it as a code block instead of gluing it onto the last sentence.
0.7.5 - 2026-09-19
homeplugin option (andOPENCODE_CODEX_MEMORY_HOME) relocates onlymemory.db+memories/so a sandbox can mount memory without the rest of OpenCode's local database. Precedence:home(pinned; ignores OpenCode's data dir andXDG_DATA_HOME) →OPENCODE_CODEX_MEMORY_HOME→ OpenCode data dir (default; memory moves with that directory). Absolute path required (~ok).memory_inspectshows the resolved home.
0.7.4 - 2026-09-19
- OpenCode 2 inside an IDE/
serve --port 0host is not the registeredserve --serviceprocess. A healthy loopback service is still used for the global session list (shared database). Non-loopback PID mismatch is refused. If no service is registered, this process learns from sessions it has seen. Helper cleanup uses the local context, and consolidation no longer holds a one-hour lease after a helper interrupt.
0.7.3 - 2026-09-18
- Phase 2 no longer walks every file under
memories/.gitlooking for symlinks. A nested junction or symlink cycle (common on Windows) could hang consolidation as "in-flight" with no error. Only the.gitentry itself is checked. Git baseline/diff/reset also time out after 2 minutes.memory_inspectnow shows how long a running consolidation has been going and when its lease expires.
0.7.2 - 2026-09-17
- OpenCode 1.18.29+ loads
exports["./tui"]and requiresdefault.tui(). 0.7.x pointed that export at the OpenCode 2 sidebar, which imports@opencode/plugin/tui— missing on 1.x, so the TUI reported the plugin unable to load../tuiis now a dual-host wrapper: 1.x gets a no-optui(), OpenCode 2 still lazy-loads the sidebar viasetup().
0.7.1 - 2026-09-17
- OpenCode 2 background learning ships
@opencode/clientas a runtime dependency so the plugin cache can import it. Discovery still readsservice.jsonand probes/api/status(notService.discover(), which hits the 2.0.5-removed/api/health). Failures now surface the real error.
0.7.0 - 2026-09-16
- The plugin now runs on OpenCode 2 as well as 1.x. Pin
0.7.0and, on OpenCode 2, use thepluginspackage form. Same memory pipeline; V1server()is unchanged. OpenCode 2 also gets a Memory sidebar and/memory-status. Host limits (registered service, citations, models) are documented inARCHITECTURE.md.
0.6.5 - 2026-08-31
- Architecture writeup covering learning, remembering, and forgetting
(
docs/how-ai-memory-works.md), linked from the README.
- Memory is no longer injected into OpenCode's hidden session-title generator (same session ID as the real chat; the hook has no agent field, so the title prompt is detected instead).
0.6.4 - 2026-08-28
- Extraction still prefers low reasoning and consolidation medium (Codex), but if the configured model does not list that effort, the plugin picks the nearest listed level (equal distance → higher). Models with no effort variants keep the host default.
0.6.3 - 2026-08-21
- Finder metadata files such as
.DS_Storein the memories folder no longer abort consolidation.
0.6.2 - 2026-08-20
- Shortcuts in the memories folder that point at files elsewhere on disk are now removed, so memory cannot be redirected outside that folder. The real files those shortcuts pointed to are left alone.
0.6.1 - 2026-08-17
- Extraction jobs that fail because the model is out of quota stay retryable
instead of being permanently dropped after three attempts. Already-failed
quota jobs are reopened automatically;
memory_inspectlabels backoff vs quota vs other exhausted failures. - Reloading OpenCode finds leftover memory helper sessions across all pages of the host-wide session listing.
- Stuck OpenCode API calls abort instead of leaving background learning hanging.
- Time-only
memory_searchlistings paginate withcursorinstead of repeating the first page. - Consolidation skips sessions that no longer exist in OpenCode (same as a deleted-session forget) and backfills their slots with lower-ranked live sessions.
- Extraction uses low reasoning and consolidation uses medium, matching Codex.
0.6.0 - 2026-08-12
memory_listsupports integer-cursor pagination and listing a single file (Codex-aligned).memory_inspectreports effectivememorize/memorize-extractagent sandbox health (shipped vs user override, permission issues).- README section on backing up and restoring the memory database and
memories/tree (including WAL/SHM and git history).
- Background extraction/consolidation promises are tracked so test teardown can wait for them to finish.
- Agent health treats non-denied extra tool and
external_directorypermissions as unhealthy and keepssource=shippedacross config-hook re-injection. memory_listreports an exhausted page when a cursor equals the current result count instead of claiming the directory itself is empty.
0.5.0 - 2026-08-08
- Import memory from Claude Code (off by default). If you also use Claude
Code on the same machine, enable
claude_import: { "enabled": true }so OpenCode can pick up Claude's project memories on the next consolidation pass. Optionalprojectsallowlist andclaude_homeoverride. One-way only (nothing is written back to Claude). Turning it off stops further import without erasing what already merged; see the README for staging cleanup.
- README configuration for Codex CLI and Claude Code sharing is clearer: options tables, turn-off behavior, and how to remove local staging copies.
0.4.11 - 2026-08-08
- Session discovery no longer filters to the current project only. The host SDK injects a directory query on every GET; that made extraction miss idle sessions from other projects (memory is global).
0.4.10 - 2026-08-08
- Plugin reload while consolidation is running no longer races past an already aborted cancel signal (could leave the job hanging until timeout).
- Extraction also listens for plugin dispose (same cancel path as consolidation), so a reload mid-extract does not wait up to an hour for the host prompt.
0.4.9 - 2026-08-08
- Bearer-token redaction matches current codex: word boundary, space/tab only
(no newline match), trailing base64 padding, and runs before API-key patterns
so
Bearer sk-…is one redaction.
0.4.8 - 2026-08-08
- Reloading or restarting OpenCode no longer leaves memory learning stuck for up to an hour, or allows two background helpers to edit memory files at once.
- Background learning is less likely to skip sessions that just became eligible or to spam OpenCode with session lookups when nothing is ready to extract.
- Memory tools refuse to follow symlinks that could redirect reads or writes outside the memory folder.
memory_resetno longer gets immediately undone by a background consolidation pass that re-created the memory folder right after the wipe.
memory_inspectshows more of why memory is (or is not) building: extraction job status and recent errors, last session discovery, when sessions become eligible, recent pipeline events, and (if enabled) last Codex import/export file times.
- The consolidation helper is instructed to only edit files under the memory workspace, not your project source tree.
0.4.7 - 2026-08-06
- Memory extraction finds past sessions with one host-wide lookup instead of scanning each project separately — faster and less brittle when many projects are open.
- Automated live checks against the official OpenCode binary
(
bun run contract,bun run live:read,bun run live:e2e) for release verification.
0.4.6 - 2026-08-05
- Memory extraction/consolidation sub-sessions no longer inherit a deleted
project directory from the plugin host. OpenCode fails those turns with
UnknownError/ ENOENT when the path is gone; sub-sessions are now anchored on the memory workspace directory (always ours, already granted tomemorize).
0.4.5 - 2026-08-05
memory_inspectnow reports Phase 2 job status, last error, retry time, and last attempt finish time. After a failed consolidation the success watermark alone no longer looked healthy while the failure stayed invisible.
0.4.4 - 2026-08-05
- Memory consolidation now stops and closes its background helper immediately if it loses the job lock or can no longer refresh it. A reclaimed job can no longer overlap with an older helper that is still editing memory files.
- An unexpectedly empty session response no longer deletes memory previously extracted from that session. The extraction retries instead; genuinely empty new sessions and explicit no-memory results still behave as before.
- Memory tools, workspace updates, and consolidation diffs now refuse files that become symlinks while being opened, preventing redirected reads and overwrites outside the memory directory.
memory_inspectnow distinguishes the last successful consolidation watermark from the latest failed attempt, reports malformed option types, and shows clean defaults after configuration reloads.
0.4.3 - 2026-07-30
- Memory consolidation now waits for its background helper chat to be closed before it finishes. If the helper cannot be closed, the run keeps its lock until it expires instead of handing it over, so a second consolidation can never edit your memory files while the first one may still be writing.
0.4.2 - 2026-07-29
- A session that invokes an external-context tool is now excluded from memory
immediately. Failed or cancelled web/MCP calls can no longer slip through
when
disable_on_external_contextis enabled, and a stalled MCP status check can no longer block the tool itself. - Failed tool calls now reach memory extraction along with their error message; content OpenCode hides from the assistant is no longer mined.
- Secret redaction now preserves JSON and YAML structure around quoted, primitive, nested, multiline, and punctuation-bearing values instead of corrupting the surrounding tool payload or leaking part of the value.
- If the memory root or
memory_summary.mdis a symlink, the plugin no longer injects redirected content into new chats. The summary stays protected even if the file is swapped while it is being opened. - Timed-out background extraction/consolidation now aborts the model run with a bounded request instead of leaving it running indefinitely.
- After a plugin reload, live memory sub-sessions are recognized before hooks start. Cleanup uses a private ownership marker plus the generated title, so ordinary chats, renamed chats, and user forks cannot be deleted by mistake.
- Citation usage for several sessions is recorded in one database transaction, so a mid-batch interruption cannot update only some of them.
memory_inspectconfig warnings reset when options are re-applied, so fixed typos no longer linger.- Under heavy load, citation, idle, and turn trackers no longer forget long-lived sessions before short-lived ones.
- A burst of duplicate idle events can no longer keep extending the de-duplication window and delaying extraction on busy sessions.
0.4.1 - 2026-07-26
- Consolidation no longer reports success when OpenCode returns an assistant error inside an otherwise successful HTTP response. The job now retries and keeps its pending workspace diff instead of silently accepting stale memory.
- Failed extraction and consolidation jobs now release their leases even when the host rejects with a non-standard value, avoiding one-hour stalls.
- Memory writes now reject symlinked paths throughout the workspace, preventing notes and generated artifacts from being redirected outside the memory root.
- MCP-backed tool calls are classified from the live server list using
OpenCode's tool-name sanitization, so dynamically added or dotted server names
correctly exclude a session when
disable_on_external_contextis enabled. - A failed database open now closes its SQLite handle instead of leaking one on every later memory operation.
- Memory is no longer injected into OpenCode's sessionless agent-generation prompt; it remains limited to real conversation sessions.
0.4.0 - 2026-07-25
- Share memory with the Codex CLI (off by default). If you use both
OpenCode and Codex on the same machine, the plugin can now exchange
consolidated memories with Codex — in either or both directions, via
codex_interop: { "import": true, "export": true }. What one assistant learns, the other picks up with its next consolidation. Codex needs no configuration for this: its own files are never modified, and nothing is written until Codex's memory feature is actually in use. Imported content is tagged with its origin so memories don't ping-pong between the two systems. (#1) - Easier configuration checking:
memory_inspectnow shows the options that are actually in effect, flags unknown or malformed configuration keys, and reports the state of the Codex exchange — just ask the agent to run it.
0.3.1 - 2026-07-16
- Memory is now stored under opencode's own data directory on every platform.
If you set
XDG_DATA_HOME, memory now lives at$XDG_DATA_HOME/opencodeinstead of always under~/.local/share/opencode.
0.3.0 - 2026-07-15
- More reliable memory extraction — the background learning agent now returns its results in a structured format instead of having its reply parsed as text, so an occasional malformed response no longer causes a session's memory to be skipped.
0.2.1 - 2026-07-15
- Now requires opencode 1.18 or newer.
0.2.0 - 2026-07-12
- Consolidation works again on opencode 1.17+: opencode gates file tools
outside the session's project behind the
external_directorypermission, and the global memory workspace is always outside the project — the consolidator's wildcard deny blocked every memory read/write. The injectedmemorizeagent now carries anexternal_directoryallow scoped to the memory root. Verified end-to-end against opencode 1.17.18. - Transcript/DB errors no longer masquerade as an empty transcript (which finalized as a successful no-output extraction and deleted the previous extraction); they fail the job, which retries under its lease.
memory_resetpropagates deletion failures instead of reporting a successful reset while files survive, and refuses to run while a consolidation is in flight in the same process.- A symlinked memory root is rejected by every memory tool (previously only descendants were checked, and search/note-writing bypassed the guard).
- Phase-2 completion updates the job row and the selected-input retention flags in one transaction (codex parity); a crash between them could let pruning delete inputs backing the consolidated artifacts.
- Secret redaction catches quoted keys in JSON/YAML tool payloads
(
"password": "..."); the aws pattern no longer emits a literal$1. memory_readcan page past 256 KiB vialine_offset(the byte cap now applies to the windowed output); the workspace diff cap counts UTF-8 bytes instead of UTF-16 code units;memory_inspectreports the promised phase-2 success watermark; internal workspace walks no longer follow symlinked directories (a self-link looped forever).- Developer-role messages are excluded from extraction transcripts (codex
sanitize_response_item_for_memories).
- opencode data is read exclusively through the official API — transcripts
via
session.messages, cross-project session discovery viaproject.list+ per-projectsession.list(scope=project, roots=true).opencode.dbis never opened; the only SQLite left is the plugin's ownmemory.db. - The extraction agent has no tools (codex parity: stage-1 is a raw prompt with an inline transcript). Previously it could read/glob/grep the host project — a poisoned transcript could induce unrelated file reads.
memory_searchports codex's full search schema:queries[],match_mode(any/all_on_same_line/all_within_lineswith minimal-window pruning),pathscoping, integer-cursor pagination (next_cursor/truncated),context_lines, andnormalizedcomparison. Arg renames:query→queries,limit→max_results. Thesince/untiltime filter and no-query listing mode are unchanged.- Citations are recorded and stripped in the new
experimental.text.completehook, before the final text is persisted — neither the UI nor stored history shows citation markup anymore (matching codex). Older hooks remain as fallbacks for pre-existing history. - Memory mode is stamped and phase 1 pumped at the first
chat.messageof a session (codex stamps at thread creation);session.status {type: idle}is handled alongside the deprecatedsession.idleevent. - The manual write-pipeline test runs fully sandboxed (XDG overrides) and
drives triggers through a persistent
opencode serve—opencode runexits before the async extraction pass claims anything.
0.1.9 - 2026-07-11
disable_on_external_contextnow works: pollution marking moved to the realtool.execute.afterplugin hook (it previously listened for a nonexistent event-bus type and never fired).max_unused_daysis now honored by the phase-1 prune (it was hardcoded to 30 days there while phase-2 selection used the configured value, so raising it silently still pruned at 30).- Reasoning/chain-of-thought parts are excluded from extraction transcripts, matching codex's rollout policy.
- A failed workspace diff no longer looks like "no changes" and falsely marks
consolidation succeeded; the job now fails and retries (codex
failed_workspace_status). - A corrupt git baseline is recovered by re-initializing instead of failing
every consolidation run (codex
reset_git_repository_sync). - Stuck unowned phase-2 jobs are recovered by the failure path (codex
failed_if_unowned); the heartbeat no longer dies silently on store errors. - The stage-1 claim cap follows
max_rollouts_per_startup(1-128) instead of being silently limited to the execution concurrency of 8; the extraction timeout mirrors the 1h job lease so large transcripts cannot exhaust retries. - Session deletion no longer triggers a consolidation attempt while
generate_memoriesis off (the memorize agent is not registered then). - The consolidation prompt no longer instructs shell commands or file deletion
the sandboxed memorize agent cannot perform; stage-1 input restores codex's
"empty string when unknown" contract;
memory_searchflags capped result sets; transcript head/tail truncation uses codex's 50/50 split.
- README: clarified that no codex subscription or OpenAI account is needed,
documented the model-selection precedence chain and
dedicated_tools: falsebehavior, and corrected several claims (idle timing, read-only opencode.db access, redaction scope, sandbox wording, data layout). - With
dedicated_tools: falsethe injected memory guidance now uses codex's file-based wording instead of referencing unregisteredmemory_*tools.
0.1.8 - 2026-07-11
- Stage-1 output changes now enqueue global consolidation, so new extractions and deleted sessions trigger a phase-2 pass without waiting for the next session.idle. If phase 2 is already running, its lease is preserved and only the input watermark advances.
- Deleting a session whose stage-1 output was already consumed by phase 2 now enqueues a forgetting pass, so the diff drives removal of the stale memory.
- Shipped memory subagents (
memorize,memorize-extract) now default-deny unknown tools so IDE and MCP integrations cannot bypass the shell/network restrictions.
0.1.7 - 2026-07-10
- Phase 2 now validates consolidation artifacts like codex (#32193): early
no-diff succeed only when
MEMORY.mdexists andmemory_summary.mdstarts withv1; after the consolidator, invalid artifacts fail the job without resetting the git baseline so INIT/repair can run again. - Stage-1 extraction treats either empty
raw_memoryor emptyrollout_summaryas no-output (codex parity); previously only both-empty was discarded.
- Re-synced
stage_one_system.md,consolidation.md, andread_path.mdfrom codex HEAD (were ~half the upstream size), re-applying the port's platform adaptations on top: the<memory-citation>/<session_ids>citation contract thatcitation.tsparses,memory_search/memory_read/memory_add_notetool guidance (the memory dir lives outside the workspace), per-session markdown rollout summaries withsession_idmetadata (codex references raw.jsonlrollouts viarollout_path/thread_id), and codex's memory-extension prompt blocks now rendered bybuildConsolidationPrompt(prompts.rs parity).stage_one_input.mdstays platform-shaped. Newtests/prompts.test.tsguards the placeholder inventory and citation/tool contracts. Bumpedcodex_refincodex-map.yaml.
0.1.6 - 2026-07-10
- Published package was missing every runtime asset outside compiled JS:
tscdoes not copysrc/templates/*.mdintodist/, and the bundledopencode.jsonwas shipped at the package root whileinjectAgentDefinitionsresolves it relative todist/src/(dist/opencode.json). Memory extraction, consolidation, read-path injection, and agent auto-registration were all broken in the npm artifact (dev checkouts were unaffected). The build now copies templates todist/src/templates/andopencode.jsontodist/. - Added a
prepacksmoke test (scripts/smoke.ts) that loads the built entry the same way opencode does (V1 module ->server()-> hooks) and exercises template reads and agent injection, so this class of packaging bug failsnpm pack/npm publishinstead of shipping. Pattern borrowed from opencode-gemini-auth's prepack import smoke test.
0.1.5 - 2026-07-08
(No functional changes — release artifact only.)
0.1.4 - 2026-07-08
- Plugin was published as TypeScript source (
"main": "src/index.ts") with no compiled JavaScript output, so the opencode binary could not load or execute it even though it appeared in the plugin list. The package now compiles todist/withtsc, ships only compiled JS, and pointsmain/exportsatdist/src/index.js. tools/control.tsandtools/memory.tsused Bun path aliases (@/...) thattscdoes not rewrite; they now import from../src/*.jsso the compiled output resolves under Node/Bun module resolution.
0.1.3 - 2026-07-05
memory_resetno longer breaks memory until restart: it closed the SQLite handle while the plugin kept using a cached store, so every subsequent hook-driven DB operation failed silently. The DB now stays open across resets (matching codex, which only wipes directories) and the store is no longer cached.- Startup sub-session cleanup no longer can kill an in-flight consolidation: the cutoff was 30 minutes while consolidation is allowed 60; it is now 90 minutes.
- Internal cleanup: dead code removed,
node:cryptoshort hash for summary filenames (was hand-rolled base36), template fill viareplaceAll.
0.1.2 - 2026-07-04
- The
memorize/memorize-extractsub-agents register themselves via the pluginconfighook — no manualagentblock needed anymore. Definitions come from the bundledopencode.json; a user-defined agent with the same name always wins. Skipped whengenerate_memoriesis off.
0.1.1 - 2026-07-04
- Parity pass after a full subsystem audit vs codex (
codex-map.yamlnow records every remaining deliberate divergence, and the drift script watches the config/lifecycle/pollution files where past blind spots lived):ensureBaselineno longer commits over an existing baseline: the phase-2 diff now spans last-success → now, so manual edits toMEMORY.mdand ad-hoc notes actually reach consolidation instead of being silently baselined away.- Baseline reset re-initializes
.git(fresh single-commit history) andmemory_resetdeletes.gittoo — deleted/redacted memory content is no longer recoverable from git history, matching codex. - Ad-hoc notes are never pruned (they are explicit user requests; codex
keeps them permanently). The seeded instructions template regained
codex's never-delete rule,
[ad-hoc note]provenance tag, and prompt-injection warning. - Phase-2 retry semantics match codex: backoff (now 1 h) is enforced regardless of job status, the retry counter is no longer reset on claim, and retries never exhaust; stage-1 retry delay is 1 h; phase-2 lease 1 h; a failing consolidation no longer re-invokes the LLM on every idle event.
- Multi-process safety: claims run in immediate transactions with per-claim ownership tokens; all finalizers require ownership + running status (a zombie worker can no longer clobber a re-claimed job's output); phase 2 confirms ownership one final time before resetting the baseline; the DB opens with a 5 s busy timeout.
disable_on_external_contextnow covers MCP tools (matched viaclient.mcp.status()), as the README already claimed.- Extraction sees full tool payloads (previously sliced to 200/500 chars
per call) with a 600k-char (~150k-token) transcript budget, matching
codex's evidence budget;
rollout_slugis redacted; Bearer redaction is case-insensitive; injected AGENTS.md/<skill>blocks are excluded from extraction. - Path guard rejects symlinks per path component and hides dotfiles; the search walker skips symlinks and hidden files.
- Sessions seen while
generate_memories: falseare permanently stampeddisabled(codex stamps at thread creation) instead of being retroactively extractable after re-enabling; deleting a session now deletes its extracted memory and job (session.deleted). memory_resetpreserves per-session memory modes (disabled/polluted sessions stay excluded), matching codexclear_memory_data.- Summary truncation keeps head + tail with a marker instead of silently
dropping the end of
memory_summary.md.
- Phase 2 consolidation never actually ran: the git baseline was committed after the workspace rebuild, so the captured diff was always empty. The baseline is now established before the rebuild.
- Staging deleted files no longer throws (
isogit.add→isogit.remove); previously any pruned rollout summary permanently broke baseline commits and diff capture. - Stage 1 jobs stuck in
runningafter a crash are reclaimed once their lease expires. - Sessions with new activity after a successful extraction are re-extracted;
source_updated_atand the success watermark now use the session's realtime_updatedinstead of extraction wall-clock time. - Phase 2 input selection kept dropping old-but-actively-cited memories (recent activity or recent usage now qualifies), and
pruneStage1Outputsis now actually called each Phase 2 run. - Citation usage was counted once per streaming delta instead of once per message part, inflating
usage_count. - Template substitution no longer expands
$&/$'/$npatterns contained in transcripts or the memory summary. - The plugin's own sub-sessions are isolated: no memory prompt injection, no phase-1 triggering on their idle events, and excluded from session capture at the SQL level.
- Full codex config parity for plugin options, using codex's exact names and defaults so the two stay easy to compare and sync:
generate_memories,use_memories,dedicated_tools,disable_on_external_context,max_raw_memories_for_consolidation,max_rollouts_per_startupare now configurable (alongside the existingextract_model,consolidation_model,max_unused_days,max_rollout_age_days,min_rollout_idle_hours). Defaults now match codex (max_rollout_age_days10,min_rollout_idle_hours6,max_rollouts_per_startup2,max_raw_memories_for_consolidation256). One intentional divergence:dedicated_toolsdefaults totrue(codex:false) so the plugin ships its memory tools out of the box. memory_searchsupportssince/untilfor time-scoped recall over time-anchored files (rollout summaries, ad-hoc notes); with a window and no query it returns a chronological listing of that period's sessions/notes. Extends beyond codex.memory_listtool (port of codexmemories/list): sorted directory listings with entry types; hidden files and symlinks are skipped.memory_readsupportsline_offset/max_lineswith start-line reporting, sofile:linecitations work on large files.- Numeric plugin options are clamped to codex's valid ranges; unknown option keys log a warning;
use_memories: falsenow also hides the memory tools (codex extension gating). - Default model selection mirrors codex's split via opencode's own config: unset
extract_modeluses opencode'ssmall_model(codex:gpt-5.4-mini), unsetconsolidation_modeluses opencode's mainmodel(codex:gpt-5.4); both fall back to the session default when not configured.
- Renamed to
opencode-codex-memoryfor npm publishing (opencode-memexis taken by an unrelated plugin). Plugin id, log prefixes, baseline commit author/message, the test-root env var (OPENCODE_CODEX_MEMORY_TEST_ROOT), and the sub-session title prefix (codex-memory-) all follow. Sub-sessions titled with the old prefix are no longer auto-cleaned or excluded from capture — delete any stragglers from before the rename. - Behavior change (parity):
memory_searchis now case-sensitive by default (passcase_sensitive: falsefor the old behavior), searches all non-hidden files instead of only.md/.txt/.json, and returns results in(path, line)order with a default limit of 200. Ad-hoc note filenames use codex's hyphen layout (<timestamp>-<slug>.md) and never overwrite on collision. - Behavior change from new defaults: memory now waits longer before extracting a session (idle ≥6h, was ≥1h), only looks back 10 days (was 14), and processes at most 2 sessions per pass. Web/MCP sessions are no longer excluded from memory by default — set
disable_on_external_context: trueto restore that. - Renamed the
generate_memoryoption togenerate_memoriesto match codex; update youropencode.jsonif you set it. - Codex memory parity pass (breaking: reset local memory state — DB schema, summary filenames, and memory_summary schema all changed):
- All three prompt templates replaced with full adaptations of codex's memory prompts: stage-1 extraction (minimum-signal gate, task outcome triage, preference-signal extraction, task-grouped raw_memory format), Phase 2 consolidation (MEMORY.md Task Group schema,
v1memory_summary schema with User Profile / User preferences / General Tips / What's in Memory, skills format, diff-driven forgetting workflow), and the read path (decision boundary, budgeted quick memory pass, staleness guidance). - System/input prompt split for extraction (system via prompt body's
systemfield); all-empty output is a supported no-op that deletes any stale stage-1 row. - Rich citations:
citation_entrieswithfile:line-range|note=[...]plus asession_idsblock (legacy format still parses). - Forgetting: disabled/polluted sessions are excluded from Phase 2 selection so their workspace files disappear and the diff drives memory pruning;
selected_for_phase2snapshots are tracked and protected from retention pruning. - Job claiming mirrors codex: retry backoff respected, newer session activity overrides backoff and resets exhausted retries, leases cleared on completion/failure.
- Session
cwdcaptured and rendered through raw_memories.md and rollout summaries; summary files named<timestamp>-<shorthash>-<slug>.md; transcripts strip citation blocks and truncate head+tail. extensions/ad_hoc/instructions.mdseeded; resource pruning is filename-timestamp based and never touches notes or instructions;extract_modelandconsolidation_modelplugin options wired to sub-agent prompts.
- All three prompt templates replaced with full adaptations of codex's memory prompts: stage-1 extraction (minimum-signal gate, task outcome triage, preference-signal extraction, task-grouped raw_memory format), Phase 2 consolidation (MEMORY.md Task Group schema,
phase2_workspace_diff.mdnow matches codex's format: a## Statuslisting plus a## Diffsection with the real unified content diff since the last consolidation (per-file diffs rendered in full, total bounded at 4 MiB with a truncation marker). Previously the consolidation agent only got the file-status list. The artifact is removed before diffing and before baseline commits so it never enters baseline history.- Full implementation of the codex memory architecture as a standalone opencode plugin (
opencode-codex-memory). - Stage 0 (Read path MVP):
memory_summary.md(≤2500 tokens) is read from~/.local/share/opencode/memories/and injected into every system prompt viaexperimental.chat.system.transform. Byte-identical append → provider cache stable. - Stage 1 (Tools + Citations):
- Tools:
memory_read,memory_search,memory_add_note. - Citation parser for
<memory-citation><citation_entries>...</citation_entries></memory-citation>. - Citations are stripped from assistant output via
experimental.chat.messages.transform. - Usage recording stub (wired in Stage 2).
- Tools:
- Stage 2 (SQLite + Phase 1 extraction):
- Plugin-owned SQLite DB (
memory.db) withmemory_stage1_outputs,memory_jobs,memory_session_meta, and schema versioning. MemoryStorewith claim/lease/heartbeat, stage-1 CRUD, usage counters, session mode/pollution tracking.- Session capture via read-only access to
opencode.db+session.idletrigger. - Secret redaction before LLM calls and storage.
- Phase 1 extraction via
memorize-extractsub-agent over the HTTP API.
- Plugin-owned SQLite DB (
- Stage 3 (Phase 2 consolidation):
- Workspace management (
raw_memories.md,rollout_summaries/,skills/,extensions/). - Git baseline diffing inside the memories directory (bundled
isomorphic-git, no external binary). - Phase 2 orchestration with 6h cooldown, 90s heartbeat, and singleton job claim.
- Consolidation via the sandboxed
memorizesub-agent. - Ships
opencode.jsonwithmemorizeandmemorize-extractagent definitions (network/tools denied).
- Workspace management (
- Stage 4 (Control tools):
memory_reset(with symlink guard and confirm flag).memory_inspect(counts, token estimate, file listing).memory_mode(per-session enabled/disabled/polluted).
- Stage 5 (Polish):
- Rate-limit stub (
checkRateLimit). - Comprehensive unit tests (42 tests).
- Rate-limit stub (
- Basic read-path integration harness (
tests/integration.ts) and a detailed manual/agentic write-pipeline test procedure (tests/WRITE_PIPELINE_TEST.md) added. No automated Jest/Bun end-to-end harness yet.- Documentation:
README.md,RUNNING.md(official opencode + plugin install), implementation plan preserved. - Plugin renamed from its
opencode-memoryworking title.
- Documentation:
- All hooks are wrapped in try/catch with graceful degradation (plugin crash does not affect the host session).
- The workspace diff is truncated at 4 MiB with an explicit marker.
- Event handlers defensively catch per-operation errors (recordUsage, markPolluted).
- Sub-agents (
memorize,memorize-extract) havebash/webfetch/websearch/task/todowritedenied. memory_resetrefuses to run if the memories root is a symlink.- Aggressive secret redaction (OpenAI/Anthropic/AWS/GitHub/Slack keys, bearer tokens, private keys, password assignments) before any LLM call or storage.
- With
disable_on_external_context: true, sessions that used web or MCP tools are markedpollutedand excluded from extraction (off by default, matching codex).
0.1.0 - 2026-07-02
Initial public development release. All stages (0–5) implemented and tested. Ready for manual end-to-end testing against the official opencode release.