docs/integrations/opencode.mdx
Add persistent memory to OpenCode with the Mem0 plugin. Your agent forgets everything between sessions — Mem0 fixes that by storing decisions, preferences, and learnings so they carry over automatically.
A Mem0 API key (starts with m0-):
Add it to your shell profile so it persists across sessions:
echo 'export MEM0_API_KEY="m0-your-api-key"' >> ~/.bashrc && source ~/.bashrc
opencode plugin @mem0/opencode-plugin
Or let your agent do it — paste this into OpenCode:
Install @mem0/opencode-plugin by following https://raw.githubusercontent.com/mem0ai/mem0/main/integrations/mem0-plugin/.opencode-plugin/README.md
This adds the plugin to your ~/.config/opencode/opencode.json. Restart OpenCode — you get the native memory tools, lifecycle hooks, and all /mem0-* slash commands. The memory tools are registered by the plugin itself via the mem0ai SDK — no MCP server to configure.
If you only need the memory tools without the plugin's hooks or skills, point OpenCode at Mem0's hosted MCP server directly. Add this to your opencode.json (project-level or global at ~/.config/opencode/opencode.json):
{
"mcp": {
"mem0": {
"type": "remote",
"url": "https://mcp.mem0.ai/mcp/",
"headers": {
"Authorization": "Token {env:MEM0_API_KEY}"
},
"oauth": false
}
}
}
| Component | Plugin (A) | Standalone MCP (B) |
|---|---|---|
| 9 memory tools | Native (SDK) | Remote MCP server |
| Lifecycle Hooks | Yes | No |
| 9 Skills | Yes | No |
| Tool | Description |
|---|---|
add_memory | Save text or conversation history for a user/agent |
search_memories | Semantic search across memories with filters |
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 | Delete a user/agent/app/run entity and its memories |
list_entities | List users/agents/apps/runs stored in Mem0 |
search_memories, get_memories, add_memory, and delete_all_memories accept an optional scope that controls how widely they read or write:
| Scope | Reads | Writes |
|---|---|---|
project (default) | this repo (user_id + app_id) | this repo |
session | this run only (+ run_id) | this run |
global | all your projects in the workspace (app_id: "*") | user-wide |
Just ask naturally — e.g. "search my memories across all my projects" — and the agent passes scope: "global". For normal questions it stays scoped to the current project automatically.
To change the default scope (used when no scope is passed), run the /mem0-scope skill:
/mem0-scope # show the current default scope + identity
/mem0-scope global # save & search across all your projects by default
/mem0-scope project # back to repo-only (the 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 always requires an explicit scope: "global" to delete user-wide, so changing the default can't trigger a cross-project wipe.
The project id (app_id) is derived from your git remote (owner-repo), falling back to the git repo's root directory name, then the current directory. Launch OpenCode from inside your repo so memories scope to the project rather than your home directory.
The plugin uses the mem0ai TypeScript SDK directly — pure TypeScript, no Python, no shell scripts.
| OpenCode Event | Hook | What happens |
|---|---|---|
config | Config | Registers the /mem0-* slash commands (config.command) and adds the plugin's own opencode-skills/ dir to OpenCode's skills.paths for in-place skill discovery (no copying) |
chat.message | Chat message | Searches prior memories on session start, searches relevant memories before each prompt, auto-captures learnings periodically |
tool.execute.before | Pre-tool | Blocks MEMORY.md writes, steering them to the add_memory tool |
tool.execute.after | Post-tool | Scans Bash errors and pre-fetches related error memories |
experimental.chat.messages.transform | Messages transform | Injects memory context (session memories, search results, error lookups) into the prompt |
experimental.session.compacting | Compaction | 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 all shell executions |
The plugin can automatically consolidate stored memories — merging duplicates, dropping stale/sensitive entries, and rewriting vague ones — so your memory set stays clean over time. It runs at most once per session, and only when all gates pass:
minHours (default 24) since the last consolidationminSessions (default 5) sessions since thenminMemories (default 20) stored for the projectA filesystem lock (~/.mem0/mem0-dream.lock) keeps two sessions from consolidating at once. Tune the thresholds with a dream block in ~/.mem0/settings.json, or disable entirely with MEM0_DREAM=false:
{
"dream": { "enabled": true, "auto": true, "minHours": 24, "minSessions": 5, "minMemories": 20 }
}
If auto-dream hasn't run yet, it's almost always because a gate hasn't been met (most often too few memories). Run /mem0-status to see the exact gate progress (e.g. sessions 2/5, memories 3/20), /mem0-dream to consolidate now regardless of the gates, or lower the thresholds above.
echo $MEM0_API_KEYopencode plugin @mem0/opencode-plugin again, then restart/mem0-status to see which gate is blocking, or /mem0-dream to consolidate now./mem0-status.