Persistent memory for OpenCode. Your agent remembers decisions, preferences, and learnings across sessions automatically.
This is a minimal self-host fork of Mem0's official OpenCode plugin. It keeps the official plugin's hooks, prompt/context injection, tool names, slash skills, and memory scope model, but replaces the Mem0 Cloud SDK client with a small REST client for a self-host Mem0 server.
Fork base: mem0ai/mem0 commit 6ddf1669f4f6ea408dca0b7f497af0cb8523cced, source path integrations/mem0-plugin/.opencode-plugin/.
Set these environment variables before starting OpenCode:
export MEM0_SELF_HOST_URL="http://localhost:8888"
export MEM0_API_KEY="your-self-host-api-key"
export MEM0_USER_ID="ldfc-mem0-<eval_id>-<app_slug>"
export MEM0_APP_ID="<app_slug-or-project-id>"MEM0_HOST is also accepted as an alias for MEM0_SELF_HOST_URL. If neither is set, the client defaults to http://localhost:8888.
MEM0_APP_ID is not sent as a first-class self-host entity because the self-host API only supports user_id, agent_id, run_id, and metadata. This plugin stores app_id in memory metadata and uses it for client-side project scoping. For LDFC eval isolation, prefer a MEM0_USER_ID such as ldfc-mem0-<eval_id>-<app_slug> and put any extra eval_id or case_id values in tool metadata.
Build the plugin:
cd /Users/zhangyiming/My_Documents/My_Code/opencode-mem0-selfhost-plugin
npm install
npm run buildThen add the built plugin to ~/.config/opencode/opencode.json or a project opencode.json:
{
"plugin": [
"file:///Users/zhangyiming/My_Documents/My_Code/opencode-mem0-selfhost-plugin/dist/index.js"
]
}Restart OpenCode. The plugin registers its memory tools and skills itself; there is no MCP server to configure.
| Component | Description |
|---|---|
| 9 Native Memory Tools | add_memory, search_memories, get_memories, update_memory, delete_memory, and more, registered as OpenCode tools and backed by self-host Mem0 REST |
| Lifecycle Hooks | Auto-search on session start and every prompt, error memory lookup, compaction context, secret redaction |
| 9 Skills | /mem0-remember, /mem0-tour, /mem0-search, /mem0-status, /mem0-scope, /mem0-dream, /mem0-forget, /mem0-pin, /mem0-context-loader, discovered in place from the plugin via OpenCode's skills.paths |
Pure TypeScript. Memory operations are native OpenCode tools backed by POST /memories, POST /search, GET /memories, GET /memories/{id}, PUT /memories/{id}, and DELETE /memories/{id} on the self-host REST server.
| Hook | Event | What it does |
|---|---|---|
| Config | config |
Registers the /mem0-* slash commands (via config.command) and adds the plugin's own opencode-skills/ dir to OpenCode's skills.paths for in-place skill discovery — no copying into ~/.config/opencode/skills |
| Chat message | chat.message |
Loads prior memories on session start, searches relevant memories before each prompt, auto-captures learnings periodically |
| Pre-tool | tool.execute.before |
Blocks MEMORY.md writes, steering them to the add_memory tool |
| Post-tool | tool.execute.after |
Scans bash errors and pre-fetches related memories |
| Messages transform | experimental.chat.messages.transform |
Injects memory context (session memories, search results, error lookups) into the prompt |
| Compaction | experimental.session.compacting |
Stores session state memory, then injects prior memories into compaction context so nothing is lost |
| Shell env | shell.env |
Exports MEM0_USER_ID, MEM0_APP_ID, MEM0_SESSION_ID, and MEM0_BRANCH to shell |
| Tool | Description |
|---|---|
add_memory |
Save text or conversation history |
search_memories |
Semantic search across memories |
get_memories |
List memories with filters and pagination |
get_memory |
Retrieve a specific memory by ID |
update_memory |
Overwrite a memory's text by ID |
delete_memory |
Delete a single memory by ID |
delete_all_memories |
Bulk delete all memories in scope |
delete_entities |
Compatibility stub; self-host REST does not expose entity deletion |
list_entities |
Compatibility stub; self-host REST does not expose entity listing |
get_event_status |
Compatibility stub; self-host REST writes are synchronous |
Every memory tool accepts an optional scope, and you can set the default
scope (used when none is passed) with the /mem0-scope skill:
| Scope | Reads | Writes |
|---|---|---|
project (default) |
this repo (user_id + metadata app_id) |
this repo |
session |
this run (user_id + metadata app_id + run_id) |
this run |
global |
user-wide where supported | user-wide |
/mem0-scope # show the current default scope
/mem0-scope global # save & search across all your projects by default
/mem0-scope project # back to repo-only (default)
The default persists in ~/.mem0/settings.json (default_scope) and is read
fresh on each memory operation, so a change applies immediately — no restart.
delete_all_memories lists matching memories and deletes them one by one. This avoids calling the self-host server's admin-only bulk delete endpoint with a first-class user_id and accidentally ignoring metadata app_id.
- No Mem0 Cloud SDK dependency and no calls to
https://api.mem0.ai. - Auth uses
X-API-Key: $MEM0_API_KEY. app_idis stored in metadata because self-host Mem0 has no first-classapp_id.- Official Cloud-only project categories are best-effort no-ops.
get_event_statusis a compatibility no-op because self-host writes are synchronous.delete_entitiesandlist_entitiesreturn unsupported messages because the self-host REST API does not expose entity endpoints.
Start OpenCode and ask: "Search my memories for recent decisions"
If the mem0 tools respond, you're all set.
| Problem | Fix |
|---|---|
| No tools appearing | Restart OpenCode after installing |
| 401 Unauthorized | echo $MEM0_API_KEY must print the API key accepted by your self-host server |
| Connection refused | Check MEM0_SELF_HOST_URL or MEM0_HOST; default is http://localhost:8888 |
| Plugin not loading | Run npm run build, then verify the file:// path points to dist/index.js |
Apache-2.0