Skip to content

yeyan00/opencode-memory

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenCode Memory

Local-only memory for OpenCode. The plugin extracts durable facts from conversations, stores them as Markdown files on your machine, injects relevant memories back into future OpenCode sessions, and provides a local Web UI for manual memory management.

中文文档

What It Does

  • Stores memories locally as human-readable Markdown.
  • Uses OpenCode's configured model path for automatic extraction.
  • Keeps system memory instructions stable and injects dynamic memory through OpenCode's message transform hook.
  • Starts a local Web UI automatically at http://127.0.0.1:3765.
  • Avoids mem0, hosted vector stores, external databases, and provider-specific API keys.
  • Keeps the agent-facing memory tool disabled by default.

Install Into OpenCode

This repository includes a prebuilt plugin bundle at dist/index.js, so non-developers can install it without compiling TypeScript. Copy dist/index.js into one of OpenCode's plugin directories.

Developers can rebuild the bundle from source when needed:

bun install
bun run build

Project-local install

Use this when only one project should load the memory plugin:

mkdir -p .opencode/plugins
cp dist/index.js .opencode/plugins/opencode-memory.js

On Windows PowerShell:

New-Item -ItemType Directory -Force -Path ".opencode/plugins"
Copy-Item -LiteralPath "dist/index.js" -Destination ".opencode/plugins/opencode-memory.js" -Force

Global install

Use this when every OpenCode project should load the memory plugin:

mkdir -p ~/.config/opencode/plugins
cp dist/index.js ~/.config/opencode/plugins/opencode-memory.js

On Windows PowerShell:

New-Item -ItemType Directory -Force -Path "$HOME/.config/opencode/plugins"
Copy-Item -LiteralPath "dist/index.js" -Destination "$HOME/.config/opencode/plugins/opencode-memory.js" -Force

Restart OpenCode after copying the bundle. Running OpenCode processes do not reload plugin files automatically.

Memory Storage

Memories are stored under the first available location:

  1. OPENCODE_MEMORY_DIR
  2. $XDG_DATA_HOME/opencode/opencode-memory
  3. ~/.local/share/opencode/opencode-memory

The store is split by scope:

global.md
users/default.md
projects/<project-key>.md
sessions/<session-id>.md

Each Markdown file contains readable memory content plus HTML-comment metadata:

<!-- memory
id: mem_global_no_push
tags: git, safety
source: manual-seed
createdAt: 2026-06-23T13:04:17.240Z
updatedAt: 2026-06-23T13:04:17.240Z
-->
Do not push to git remotes unless the user explicitly asks.

The metadata is not injected into the agent prompt. It is used by the store and Web UI for IDs, tags, source tracking, and sorting. Writes use per-file lock directories and same-directory atomic rename to reduce lost updates when multiple OpenCode processes are running.

No secrets should be stored as memories.

Memory Design

Scopes

Scope File Injection behavior
Global global.md Always injected. Use for cross-project rules and durable preferences.
User users/default.md Always injected. Use for user-level preferences.
Project projects/<project-key>.md Injected when relevant to the latest prompt.
Session sessions/<session-id>.md Injected only for the matching session and only when relevant.

Update flow

  1. OpenCode emits chat.message; the plugin records the latest user prompt for that session.
  2. OpenCode emits experimental.text.complete; the plugin records the assistant response.
  3. The plugin asks OpenCode's own session API to run extraction in a separate internal extraction session.
  4. The extraction result is parsed with Zod.
  5. Empty, duplicate, malformed, low-confidence, or failed extraction results are ignored.
  6. Valid memory additions are written to the scoped Markdown store.

The extraction session is marked internal so the plugin skips its hooks and avoids recursive memory extraction.

Injection flow

  1. OpenCode calls experimental.chat.system.transform before sending the prompt to the model.
  2. The plugin appends only stable memory instructions to the system prompt.
  3. OpenCode calls experimental.chat.messages.transform with the outgoing message list.
  4. The plugin loads local memories from the Markdown store and groups them by scope.
  5. The plugin inserts an advisory synthetic memory context message containing the <opencode-memory> block.

Example injected memory context:

<opencode-memory>
These memories are durable background context. Do not repeat these memories unless useful; current user message wins; compacted conversation/history may overlap.

## Global Memory
- Do not push to git remotes unless the user explicitly asks.

## Project Memory
- This project stores memories in split Markdown files.
</opencode-memory>

The block is advisory. The current user request still has priority over memory content.

Prompt-cache behavior

The system prompt contains only stable memory instructions. Dynamic memory content is inserted later through experimental.chat.messages.transform, which keeps the provider-cache-friendly system prompt prefix stable across sessions. The plugin also keeps same-session memory rendering stable with a per-session render cache and filters project/session memories by relevance.

Web UI

The plugin starts a local Web UI automatically when it loads:

http://127.0.0.1:3765

Features:

  • List memories across all scopes.
  • Search memory content.
  • Add new memories manually.
  • Edit memory content and tags.
  • Delete memories.
  • Filter by global, user, project, or session scope.

Configuration:

Variable Default Description
OPENCODE_MEMORY_WEB_HOST 127.0.0.1 Host for the local Web UI. Keep localhost unless you understand the security risk.
OPENCODE_MEMORY_WEB_PORT 3765 Port for the local Web UI.
OPENCODE_MEMORY_WEB_AUTOSTART enabled Set to 0 to disable automatic Web UI startup.

Multiple OpenCode processes share one local UI instance. The plugin checks /health, uses runtime metadata under .runtime/web, and hands ownership to another process when the current owner exits or becomes unhealthy.

There is no /open-memory or /show-memory command. OpenCode command templates route through the agent, so the UI is opened directly in the browser instead.

Agent-Facing Memory Tool

The agent-facing memory tool is disabled by default. Automatic extraction writes memories internally, and users manage memories through the Web UI.

Enable it only when needed:

Value Behavior
unset / off Default. No agent-facing memory tool.
read-only Register memory for search only.
full Register memory for add, search, list, and delete.
OPENCODE_MEMORY_AGENT_TOOL=read-only opencode

Architecture Diagrams

Runtime lifecycle

flowchart TD
  A[OpenCode starts] --> B[Load opencode-memory plugin]
  B --> C[Resolve memory directory]
  C --> D[Start or reuse local Web UI]
  B --> E[Register OpenCode hooks]
  E --> F[Capture user prompts]
  E --> G[Capture assistant responses]
  E --> H[Transform system prompt]
  E --> I[Transform chat messages]
Loading

Memory update pipeline

sequenceDiagram
  participant U as User
  participant O as OpenCode
  participant P as Memory Plugin
  participant X as Internal Extraction Session
  participant S as Markdown Store

  U->>O: Send prompt
  O->>P: chat.message
  P->>P: Save latest prompt
  O->>P: experimental.text.complete
  P->>P: Save assistant response
  P->>X: Extract durable memory with OpenCode model policy
  X-->>P: JSON operations
  P->>P: Parse, dedupe, confidence filter
  P->>S: Write scoped Markdown memory
Loading

Memory injection pipeline

sequenceDiagram
  participant O as OpenCode
  participant P as Memory Plugin
  participant S as Markdown Store
  participant M as Model

  O->>P: experimental.chat.system.transform
  P-->>O: System prompt plus stable memory instructions
  O->>P: experimental.chat.messages.transform
  P->>S: Load all scoped memories
  S-->>P: Memory records
  P->>P: Always include global and user memories
  P->>P: Filter project and session memories by relevance
  P-->>O: Messages plus synthetic opencode-memory context
  O->>M: Send transformed prompt
Loading

Storage layout

flowchart LR
  R[opencode-memory directory] --> G[global.md]
  R --> U[users/default.md]
  R --> P[projects/project-key.md]
  R --> S[sessions/session-id.md]
  R --> W[.runtime/web]
Loading

Development Verification

Run the full local gate:

bun run test
bun run typecheck
bun run build

bun run test is preferred over naked bun test because the repository contains ignored reference projects under ref/.

Why No mem0 Runtime Dependency

This plugin intentionally does not depend on mem0, Supermemory, hosted vector stores, or provider-specific SDKs for runtime behavior:

  • Memory data stays local.
  • Markdown is the canonical store.
  • Extraction uses OpenCode's configured model flow.
  • No separate OpenAI, Anthropic, Gemini, Ollama, or cloud memory credentials are required.

Related projects inspired parts of the prompt and UI direction, but runtime behavior is OpenCode-native and local-first.

About

Local-first memory plugin for OpenCode with Markdown storage and a built-in Web UI.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors