Your OpenCode agents remember everything. No more re-explaining.
Persistent cross-session memory via agentmemory — 95.2% retrieval accuracy on LongMemEval-S.
npx @agentmemory/agentmemoryThe server starts on http://localhost:3111.
Add to ~/.config/opencode/opencode.json or your project's .opencode/opencode.json:
{
"mcp": {
"agentmemory": {
"type": "local",
"command": ["npx", "-y", "@agentmemory/mcp"],
"enabled": true
}
}
}Add to ~/.config/opencode/opencode.json:
{
"plugin": ["./plugins/agentmemory-capture.ts"]
}Copy the plugin file from this repo:
mkdir -p ~/.config/opencode/plugins
cp plugin/opencode/agentmemory-capture.ts ~/.config/opencode/plugins/Copy the commands into your project or global .opencode/commands/ directory:
mkdir -p ~/.config/opencode/commands
cp plugin/opencode/commands/recall.md ~/.config/opencode/commands/
cp plugin/opencode/commands/remember.md ~/.config/opencode/commands/Restart OpenCode or open a new session. The plugin auto-captures everything.
| Event | Hook | agentmemory API |
|---|---|---|
| Session start | session.created |
POST /session/start |
| Idle → summarize | session.idle + session.status (idle) |
POST /summarize |
| Status transitions | session.status (idle/busy/retry) |
POST /observe |
| Compaction | session.compacted |
POST /summarize + POST /observe |
| Metadata updates | session.updated |
POST /observe |
| Code change tracking | session.diff |
POST /observe |
| Session delete | session.deleted |
POST /session/end |
| Session error | session.error |
POST /observe |
| Event | Hook | agentmemory API |
|---|---|---|
| User prompt (rich) | chat.message |
POST /observe |
| User prompt metadata | message.updated (user) |
POST /observe |
| Assistant response | message.updated (assistant) |
POST /observe |
| Message removed (undo) | message.removed |
POST /observe |
| Event | Hook | agentmemory API |
|---|---|---|
| Subagent start | message.part.updated (subtask) |
POST /observe |
| Tool completed | message.part.updated (tool completed) |
POST /observe |
| Tool error | message.part.updated (tool error) |
POST /observe |
| Step finish (cost/tokens) | message.part.updated (step-finish) |
POST /observe |
| Reasoning trace | message.part.updated (reasoning) |
POST /observe |
| Patch applied | message.part.updated (patch) |
POST /observe |
| Auto/manual compaction | message.part.updated (compaction) |
POST /observe |
| Agent selection | message.part.updated (agent) |
POST /observe |
| API retry | message.part.updated (retry) |
POST /observe |
| Event | Hook | agentmemory API |
|---|---|---|
| File tool params | tool.execute.before → stash paths |
— |
| File edited | file.edited → stash paths |
— |
| File part attached | message.part.updated (file) → stash paths |
— |
| Enrichment inject | experimental.chat.system.transform |
POST /enrich → output.system[] |
| Memory context inject | experimental.chat.system.transform |
POST /context → output.system[] |
| Event | Hook | agentmemory API |
|---|---|---|
| Permission prompt | permission.updated |
POST /observe |
| Permission reply | permission.replied |
POST /observe |
| Event | Hook | agentmemory API |
|---|---|---|
| Task tracking (w/ priority) | todo.updated |
POST /observe |
| Command executed | command.executed |
POST /observe |
| Event | Hook | agentmemory API |
|---|---|---|
| LLM parameters | chat.params |
POST /observe |
| Config loaded | config |
POST /observe |
| Compaction (WIP) | experimental.session.compacting |
POST /context → output.context[] |
experimental.chat.system.transform fires before every LLM call and injects two layers of context:
-
Memory context (once per session): calls
/agentmemory/contextand injects project profile, recent session summaries, and important past observations into the system prompt. This is the OpenCode equivalent of Claude's MEMORY.md bridge — instead of syncing to a markdown file, context is injected directly into the system prompt. -
File enrichment (every turn with stashed files): calls
/agentmemory/enrichwith files stashed bytool.execute.before,file.edited, andmessage.part.updated(file parts). File-specific context (past observations, related bugs, semantic search) is injected into the system prompt.
System prompt = [OpenCode instructions] + [memory context] + [file enrichment] + [user message]
^ ^
first turn only every file-touching turn
Differences from Claude's PreToolUse:
| Dimension | Claude (PreToolUse) | OpenCode (two-hop pipeline) |
|---|---|---|
| Injection mechanism | stdout → context window | output.system[] → system prompt |
| Timing | Same turn (parallel with tool) | Next turn (before next LLM call) |
| File set | Per-tool (immediate) | Batched (all files since last enrichment) |
| Coverage | Edit/Write/Read/Glob/Grep only | Edit/Write/Read/Glob/Grep only |
| What gets injected | <agentmemory-file-context> + bug memories |
Identical /enrich response |
Claude Code and OpenCode take fundamentally different approaches to injecting memory context into the agent's system prompt.
agentmemory ──write──▶ MEMORY.md ──read──▶ Claude system prompt
- The
claude-bridge/syncendpoint serializes agentmemory observations into aMEMORY.mdfile in the project root - Claude Code reads
MEMORY.mdon session start and prepends it to the system prompt - Sync is periodic — sessions only get fresh context when the bridge last ran (session end, pre-compact)
- Coupling: memory data lives in a git-trackable file, visible to CI, team members, and other tools
agentmemory ──push──▶ OpenCode system prompt
experimental.chat.system.transformcalls/contextat runtime and pushes the response directly intooutput.system[]- Always current — context is fetched at session start (once) and before file-touching turns (per-batch)
- No file intermediary — no stale copies, no merge conflicts, no disk I/O
AGENTS.mdis a static instruction file for project conventions, coding standards, and tool guidance — agentmemory does not read or write it
| Dimension | Claude (MEMORY.md bridge) | OpenCode (direct injection) |
|---|---|---|
| Freshness | Stale between syncs | Always current (fetched at call time) |
| Visibility | Human-readable file in repo | In-memory injection only |
| Simplicity | Two moving parts (bridge + file) | One step (API → system prompt) |
| Team sharing | File is git-trackable, CI-friendly | Memory shared via agentmemory server API |
| Integration | Any tool can read MEMORY.md | Requires OpenCode plugin SDK |
agentmemory already persists everything in SQLite (data/state_store.db). Adding an intermediate MEMORY.md file would duplicate data, introduce sync lag, and require the model to re-parse structured context from markdown. Direct injection delivers the same data with lower latency and zero staleness — the agent always sees what agentmemory knows right now.
/recall <query>— Search past observations and lessons/remember <text>— Save an insight to long-term memory
Agentmemory usage instructions are injected into the system prompt on the first turn of every session via experimental.chat.system.transform (alongside memory context from /context). This is functionally equivalent to Claude Code's skills mechanism — the agent learns which agentmemory_memory_* tools to use and when, without needing separate skill invocations.
| Claude feature | Reason |
|---|---|
| SubagentStop | OpenCode's SubtaskPart type has no completion/result fields; subtask lifecycle ends are not exposed as distinct events in the OpenCode SDK |
| TaskCompleted | No team/teammate concept in OpenCode; todo.updated captures task state changes as a partial equivalent |
| Stop | session.compacted event handler exists; experimental.session.compacting injection hook defined in SDK but Go binary (v1.14.41) doesn't wire it — will auto-activate when upstream implements it |
| Skills (remember/recall/forget/session-history) | Covered by injected system instructions via experimental.chat.system.transform — agent receives usage guidance on first turn |
| Consolidation pipeline (crystals/auto + consolidate-pipeline) | Now called on session.deleted — mirrors Claude's CONSOLIDATION_ENABLED=true behavior |
| Claude MEMORY.md bridge | OpenCode-specific; OpenCode uses its own AGENTS.md mechanism, not Claude's MEMORY.md |
All other Claude Code hooks have direct or pipeline equivalents in this plugin. 12 of 12 Claude hook types covered.