Skip to content

OpenCode ​

Give OpenCode cross-project and cross-session long-term memory plus indexed repository context. Once installed, every conversation automatically recalls relevant memories and captures new content through OpenCode plugin hooks, while model-callable tools come from the same OpenViking stdio MCP proxy used by the Claude Code and Codex memory plugins.

Source: examples/opencode-plugin

Tool calls and results are captured as dedicated tool parts, and tool_output is reported verbatim. Truncation is the server's job: output larger than tool_output_externalization.threshold_chars (default 20000) is written to the session's tool-result store, and the part keeps a synopsis stub plus tool_output_ref, so the original stays readable through /api/v1/sessions/{id}/tool-results.

Prerequisites ​

  • OpenCode 1.15.7+ or 2.0.15+
  • Node.js 18+
  • An OpenViking HTTP server
  • An OpenViking API key when your server requires authentication

Start your OpenViking server first:

bash
openviking-server --config ~/.openviking/ov.conf

In another terminal, check the service:

bash
curl http://localhost:1933/health

Install ​

OpenCode shares the unified installer with Claude Code and Codex. It asks which harnesses to install and for your OpenViking credentials; every step is idempotent—re-running it is entirely safe.

bash
curl -fsSL https://openviking.ai/install | bash
# AI agents: not sure about running this? The script's header says what it does and how to verify it.

The installer copies the plugin into ~/.config/opencode/plugins/ as a local file plugin, writes the openviking MCP server entry into ~/.config/opencode/opencode.json, and configures ~/.openviking/ovcli.conf.

Manual npm install ​

The published npm package is @openviking/opencode-plugin. For a first-time OpenCode config:

bash
mkdir -p ~/.config/opencode
cat > ~/.config/opencode/opencode.json <<'JSON'
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@openviking/opencode-plugin"]
}
JSON
opencode

If ~/.config/opencode/opencode.json already exists, do not overwrite it; only merge "@openviking/opencode-plugin" into the existing plugin array. OpenCode downloads the npm package at startup, and the plugin registers its MCP server automatically.

OpenCode 2 uses the same package. It calls setup(), while OpenCode 1 calls server(). OpenCode 2 normalizes "plugin" to "plugins", so the installer continues to write the v1/v2-compatible "plugin" key; do not rewrite an existing config just for v2.

The plugin also brings its own skills, so there is nothing extra to install: openviking-memory, openviking-skills, and ov-experience-memory, which tell the model when to use which OpenViking tool. OpenCode 1 gets them through the plugin's config hook, which adds the plugin's skills/ directory to skills.paths; OpenCode 2 registers that directory with skill.transform. The skills come only with the plugin's OpenViking MCP server: they are left out in hook-only mode and when you disable mcp.openviking.

On OpenCode 2, the plugin sets its MCP server to codemode: false, so tools remain directly available as openviking_* instead of being folded into Code Mode. OpenCode 2 has no plugin toast API, so service availability notices are written to the plugin log only.

Source install ​

If package installation is not available in your environment:

bash
git clone https://github.com/volcengine/OpenViking.git
cd OpenViking
node examples/memory-plugin-shared/sync.mjs
mkdir -p ~/.config/opencode/plugins/openviking
cp examples/opencode-plugin/wrappers/openviking.js ~/.config/opencode/plugins/openviking.js
cp examples/opencode-plugin/index.mjs examples/opencode-plugin/package.json ~/.config/opencode/plugins/openviking/
cp -r examples/opencode-plugin/lib ~/.config/opencode/plugins/openviking/
cp -r examples/opencode-plugin/servers ~/.config/opencode/plugins/openviking/

sync.mjs generates lib/shared/, the shared modules the plugin and its MCP proxy import. That directory is not in git, so run it before copying, and again after every git pull.

This source install creates the layout OpenCode can discover:

text
~/.config/opencode/plugins/
├── openviking.js
└── openviking/
    ├── index.mjs
    ├── package.json
    ├── lib/
    └── servers/

The top-level openviking.js is only a wrapper that forwards OpenCode's first-level plugin entry to the installed package directory. Use the .js wrapper for source installs; OpenCode's local plugin scanner discovers JavaScript/TypeScript plugin files.

Configure ​

Credentials are shared with the Claude Code and Codex memory plugins. Run the setup wizard once from the repository root, or set OPENVIKING_* environment variables. The wizard imports lib/shared/ too, so generate it first:

bash
node examples/memory-plugin-shared/sync.mjs
node examples/opencode-plugin/scripts/setup.mjs

Behavior knobs live in the plugin section of ~/.openviking/ovcli.conf, beside the connection fields the wizard writes. Shared keys apply to every memory plugin; keys under plugin.opencode apply to this one and override them:

json
{
  "plugin": {
    "recallLimit": 6,
    "scoreThreshold": 0.35,
    "recallMaxContentChars": 500,
    "recallPreferAbstract": true,
    "recallTokenBudget": 2000,
    "minQueryLength": 3,
    "commitTokenThreshold": 20000,
    "profileTokenBudget": 10000,
    "skillCatalog": true,
    "skillCatalogTokenBudget": 1200,
    "resumeContextBudget": 32000,
    "opencode": {
      "timeoutMs": 30000,
      "repoContext": true,
      "repoContextCacheTtlMs": 60000
    }
  }
}

Settings resolve highest priority first: OPENVIKING_* environment variables, the workspace's .openviking/config.json and config.local.json, plugin.opencode, plugin, then the built-in defaults. autoRecall: false turns automatic recall off, and autoCapture: false stops the plugin sending turns back.

The first message of each session carries a hidden <openviking-context source="session-start"> block with your profile.md, the preferences/ and entities/ memory indexes, and an <available-skills> catalog: your own skills first, then the account-shared ones under viking://agent/skills, leaving out a shared skill that has the same name as one of yours. The agent reads a skill's SKILL.md with openviking_read before following it, and creates or shares skills with openviking_add_skill. profileTokenBudget covers the profile and memory indexes; the catalog has its own budget, skillCatalogTokenBudget (default 1200, env OPENVIKING_SKILL_CATALOG_TOKEN_BUDGET). When the descriptions do not fit, the catalog lists names only (with a ... +N more tail if even the names do not all fit), and when not even one name fits, a one-line count. skillCatalog: false (OPENVIKING_SKILL_CATALOG=0) or a budget of 0 turns the catalog off; with no skills, or on a server without GET /api/v1/skills, it is left out.

Environment variables override ovcli.conf:

bash
export OPENVIKING_API_KEY="your-api-key-here"
export OPENVIKING_ACCOUNT="default"   # optional, trusted-mode deployments only
export OPENVIKING_USER="opencode"     # optional, trusted-mode deployments only
export OPENVIKING_PEER_ID="opencode"  # optional, peer-scoped memory routing

API keys are sent as Authorization: Bearer ... by both hooks and the MCP proxy. account and user are trusted-mode headers; peerId is sent as X-OpenViking-Actor-Peer and as peer_id on captured session messages.

Verify ​

Restart OpenCode after installation. In an OpenCode session, the plugin should expose the openviking MCP server with the full server MCP tool set (16 tools). OpenCode namespaces MCP tools as openviking_*:

  • openviking_find, openviking_search (openviking_search with mode="context" replaces the former recall tool)
  • openviking_read, openviking_list, openviking_tree, openviking_grep, openviking_glob
  • openviking_remember, openviking_write, openviking_edit, openviking_add_resource, openviking_add_skill
  • openviking_list_watches, openviking_cancel_watch, openviking_forget, openviking_health

OpenCode 2 captures the current turn's user message, assistant response, and tool results when each execution ends, and captures the transcript before compaction discards it. It commits at the token threshold, and forces a commit on compaction, session deletion, and plugin cleanup. OpenCode 2 runs cleanup after 60 minutes of inactivity, when the service stops, and when a local plugin is hot-reloaded.

OpenCode 1.15.7 does not call plugin disposal hooks. A short-lived v1 CLI run can also exit before asynchronous capture finishes; this behavior predates v2 support. Keep the v1 service running to let idle capture finish. OpenCode 1.18.32 calls the disposal hook when its instance is disposed.

Ask OpenCode to search or browse OpenViking memory. Runtime state and errors are written to:

bash
~/.config/opencode/openviking/openviking-memory.log
~/.config/opencode/openviking/openviking-session-state.json

Troubleshooting ​

IssueWhat to check
Plugin does not loadConfirm the plugin array in ~/.config/opencode/opencode.json references @openviking/opencode-plugin, or that ~/.config/opencode/plugins/openviking.js exists for source installs
Load fails with a missing lib/shared/*.mjs moduleThe source copy was made without running sync.mjs first. Run node examples/memory-plugin-shared/sync.mjs from the repository root and copy lib/ again
MCP tools call the wrong serverCheck ~/.openviking/ovcli.conf, or set OPENVIKING_* env vars; OPENVIKING_CLI_CONFIG_FILE points the plugin at a different ovcli.conf
401 / 403 from OpenVikingVerify OPENVIKING_API_KEY; for trusted-mode deployments, also verify OPENVIKING_ACCOUNT and OPENVIKING_USER
Recall is emptyConfirm the OpenViking server has indexed memories/resources and that autoRecall is not set to false
Local openviking_add_resource failsPass a file path, not a directory; local directories are not uploaded automatically yet

For all available tools, configuration fields, and runtime file details, see the plugin README.

See also ​

Open source under the AGPL-3.0 License. Font licenses