Memory is retrieved by project instead of pasted into every prompt
OpenCode Memory stores durable facts in local Turso/libSQL databases and uses native vector indexes to find relevant entries. Project memories can hold decisions, failed approaches, or recurring bug patterns. A separate user profile summarizes preferences across projects. The plugin can inject a small number of matches into the first message or during compaction, leaving stable rules in AGENTS.md where every agent should see them.
Manual tools cover add, search, list, forget, profile, export, import, and shard migration. Automatic capture runs after a session becomes idle and asks a configured model to extract technical context. Users can browse the combined prompt and memory timeline in a web interface on port 4747. This is more inspectable than an invisible summary, though the usefulness still depends on what the extraction model chooses to save.
Automatic capture sends context to the provider you configure
Search, manual additions, and listing can work without an auto-capture provider. Automatic extraction and profile learning cannot. The recommended setup points at a provider and model already available in OpenCode; a fallback can call an OpenAI-compatible service. Local embeddings use @huggingface/transformers and download the chosen model on first use, while remote embeddings need a URL, model name, and Bearer key.
This split is good for privacy decisions. Embeddings may stay on the machine while a conversation summary still goes to Anthropic, OpenAI, or another configured model. Teams should identify which text each background request sends and whether source code, customer data, or secrets can enter it. Disabling automatic capture keeps manual memory useful and offers a safer evaluation path before any provider policy is accepted.
What happened when we ran it
Our run cloned commit d1d0eb0 into a fresh unprivileged Node 22 container with 3 CPUs, 8 GB of RAM, and no secrets. Bun installed 128 packages in 58 seconds and used 510 MB on disk. The build then failed with exit 1 after 8 seconds. TypeScript could not resolve React, React DOM, Vite, Tailwind's Vite plugin, clsx, tailwind-merge, JSX runtime, or the CSS side-effect import.
Tests also exited 1 after 332 seconds. Bun reported 435 passing tests, 9 failures, 1 skipped test, 1 error, and 1,075 expectations across 71 files. The tail says one test exceeded its 5,000 ms timeout. It does not identify all 9 causes in the supplied lines, so the result supports no broader diagnosis. A large green majority still leaves the default command red.
The 3.2 MB checkout contained 226 files and roughly 35,195 lines of source. Our scan found 3 CI workflow files, no Dockerfile, and a tests directory. That contrasts with the local failure and suggests platform or dependency-path differences deserve investigation. It does not make the sandbox result disappear: contributors on this measured setup could install, but they could neither produce the build nor finish with a passing suite.
Migration favors recovery over an in-place gamble
The storage design takes model and path changes seriously. Legacy SQLite shards are backed up before conversion, progress is tracked per shard, and a global marker appears only after verification. Lock files block concurrent migrations and writes during sensitive operations. If embedding dimensions become incompatible, writes stop instead of quietly mixing vectors with different shapes. The web UI can build and verify a replacement before swapping it into place.
Moving a repository can change its identity and leave the old shard orphaned. The plugin can list shards, preview a migration, move by old path or hash, and retain timestamped backups. Export and import support cross-machine transfers, with embeddings recomputed under the destination model. Export files are plaintext and can include memory text, identity data, repository URLs, and absolute paths, so they need the same handling as source-bearing backups.
Nested repositories can share one logical memory by placing an .opencode-mem-project marker at the workspace root. That is useful for Android-style or multi-repo trees, but it widens retrieval scope deliberately. Put the marker only where every child repository is allowed to share context, since project boundaries are part of the privacy model as well as search quality.
DiskANN growth can turn hundreds of memories into hundreds of megabytes
Issue 277 reports that version 2.22.2 produced a 542 MB shard for about 656 memories with 2,048-dimensional embeddings. The reporter attributes 98% of the file to 2 DiskANN shadow tables and says a tuned index rebuild reduced the shard to 73.3 MB. The issue says the behavior likely extends through v2.25.0, but it remains a reporter's finding rather than a fix shipped in the reviewed release.
That report is specific enough to test. Create a disposable shard with your chosen dimensions, add a representative number of memories, inspect file growth, and verify retrieval before committing. Smaller default embeddings may behave differently. Changing the model or dimensions can also trigger re-embedding, so record the model, dimensions, memory count, and database size as the store grows. Local does not automatically mean small or maintenance-free.
Loopback is the safe default for the memory browser
The web server defaults to 127.0.0.1. Binding to 0.0.0.0 or another non-loopback address requires an API token for /api/* calls, and the README also documents Basic Auth for the UI. Secrets can come from environment variables or protected files rather than literal config. These controls matter because the timeline can reveal prompts, project decisions, user preferences, and paths.
Release v2.25.0 arrived on 2026-08-25, the same day as the last repository push, and GitHub listed 8 open issues and pull requests combined. Its release notes include data-integrity, ANN query-plan, Windows locking, provider-error, and orphaned-memory fixes. That is useful maintenance on the risky parts of the product. It also argues for pinning: memory storage deserves staged upgrades and a checked backup, even when migration code promises recovery.

