memsearch OpenCode Plugin

May 28, 2026 · View on GitHub

Semantic memory search for OpenCode — gives your AI assistant persistent memory across sessions with zero user intervention.

Features

  • Auto-capture: Summarizes each conversation turn and saves to daily .md files
  • Semantic search: Hybrid search (BM25 + dense vectors + RRF) via Milvus
  • Three-layer recall: Search → Expand → Transcript (progressive detail)
  • Cold-start context: Injects recent memories into new sessions automatically
  • Per-project isolation: Each project gets its own Milvus collection
  • ONNX embeddings: CPU-only bge-m3 model, no API key required

Quick Start

Prerequisites

# Install memsearch with ONNX embeddings
uv tool install 'memsearch[onnx]'
# or: pip install 'memsearch[onnx]'
// In ~/.config/opencode/opencode.json
{
  "plugin": ["@zilliz/memsearch-opencode"]
}

Windows note: the current plugin shells out to bash and python3 helper scripts. Plain Windows installs are not supported yet; use WSL2 (recommended) or a POSIX-compatible shell such as Git Bash. See issue #387.

Install from Source (development)

# Clone the repo
git clone https://github.com/zilliztech/memsearch.git
cd memsearch

# Run the installer
bash plugins/opencode/install.sh

Manual Install

# 1. Symlink the plugin
mkdir -p ~/.config/opencode/plugins
ln -sf /path/to/memsearch/plugins/opencode/index.ts ~/.config/opencode/plugins/memsearch.ts

# 2. Symlink the skill (optional, for !memory-recall)
mkdir -p ~/.agents/skills
ln -sf /path/to/memsearch/plugins/opencode/skills/memory-recall ~/.agents/skills/memory-recall

Architecture

OpenCode Session
    ├── chat.message hook ──→ Detect turn completion
    │                              │
    │                              ├── Extract last turn from SQLite
    │                              ├── Persist turn metadata to .memsearch/opencode-turns.db
    │                              ├── Summarize via LLM (third-person notes)
    │                              └── Append to .memsearch/memory/YYYY-MM-DD.md
    │                                     │
    │                                     └── memsearch index (background)

    ├── system.transform hook ──→ Inject recent memories

    └── Tools
        ├── memory_search ──→ memsearch search (hybrid BM25+dense)
        ├── memory_get    ──→ memsearch expand (full context)
        └── memory_transcript ──→ parse-transcript.py (SQLite reader)

Verify It Works

After restarting OpenCode, chat for a few turns in a project and confirm memory capture is happening:

ls .memsearch/memory/
cat .memsearch/memory/$(date +%Y-%m-%d).md

If the plugin is active, daily markdown files should appear and grow as conversations finish.

Recall Memories

Manual invocation — explicitly invoke the skill with a query:

/memory-recall what was the auth approach we discussed?

Auto invocation — just ask naturally, the LLM auto-invokes memory tools when it senses the question needs history:

We discussed the authentication flow before, what was the approach?

Tools

ToolDescription
memory_searchSemantic search over past memories. Returns ranked chunks.
memory_getExpand a chunk hash to see the full markdown section.
memory_transcriptRead original conversation from OpenCode SQLite DB, optionally centered on a turn cursor.

<project>/.memsearch/opencode-turns.db stores derived capture checkpoints and turn ordering only. It is rebuildable state, not the source of truth for transcript recall.

Memory Files

Memory is stored as markdown in <project>/.memsearch/memory/:

.memsearch/
└── memory/
    ├── 2026-03-25.md
    └── 2026-03-26.md

Each file contains timestamped entries with bullet-point summaries:

# 2026-03-26

## Session 14:30

### 14:30
<!-- session:ses_abc123 turn:msg_123abc db:~/.local/share/opencode/opencode.db -->
- User asked about the authentication flow.
- Assistant explained the OAuth2 implementation in auth.ts.
- Assistant modified the token refresh logic in refresh.ts.

Configuration

The plugin uses ONNX embeddings by default (no API key needed). To use a different provider:

memsearch config set embedding.provider openai
# Set the API key in your environment
export OPENAI_API_KEY=sk-...

To override only the OpenCode native capture summarization model:

memsearch config set plugins.opencode.summarize.model anthropic/claude-haiku

To use a memsearch-managed API provider instead:

memsearch config set llm.providers.openai.type openai
memsearch config set llm.providers.openai.model gpt-5-mini
memsearch config set llm.providers.openai.api_key env:OPENAI_API_KEY
memsearch config set plugins.opencode.summarize.provider openai

Leave plugins.opencode.summarize.provider empty or set it to native to keep the current small_model / plugin default behavior. This setting does not fall back to llm.model.

How It Works

  1. Capture: After each conversation turn, the plugin extracts the user+assistant exchange, summarizes it via LLM, and appends to a daily markdown file.

  2. Index: The markdown files are indexed by memsearch into a Milvus collection (Milvus Lite by default, runs in-process).

  3. Recall: When the assistant needs historical context, it calls memory_search to find relevant chunks. Results can be expanded with memory_get or drilled into with memory_transcript, which reads the original transcript from OpenCode SQLite.

  4. Cold-start: At session start, recent memory bullets are injected into the system prompt so the assistant has immediate context.

Differences from Other Plugins

FeatureClaude CodeOpenCodeOpenClaw
Session storageJSONLSQLiteJSONL
Hook systemShell scriptsTypeScript hooksJS API
Summarizerclaude -p --model haikuopencode promptopenclaw agent
Context injectionSessionStart hooksystem.transformbefore_agent_start
Skill contextcontext: forkN/A (no fork)N/A