-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Description
Hi, Thanks for the ocv fork — the vim keybindings are great.
After the upstream anthropic legal request (PR #18186) removed built-in Anthropic OAuth, Pro/Max subscribers need the community opencode-claude-auth plugin to authenticate. It works on upstream opencode@1.2.27 but fails to load on ocv due to a version suffix mismatch.
Note: This issue was investigated with the help of Claude — analysis of the compiled binary strings, upstream source, and npm registry to trace the root cause.
Summary
The ocv fork uses a custom version string 1.2.27-vim.2 (with the -vim.2 suffix) as Installation.VERSION. The opencode plugin system uses this version verbatim to resolve the @opencode-ai/plugin SDK from npm. Since @opencode-ai/plugin is only published under upstream version numbers (e.g. 1.2.27), the resolution fails with a 404, breaking all plugin loading.
Plugins appear in /status (read from config) but never actually function.
Environment
| Component | Version | Install method |
|---|---|---|
| ocv | 1.2.27-vim.2 |
brew install leohenon/tap/ocv |
| opencode (upstream) | 1.2.27 |
brew install opencode |
| Plugin tested | opencode-claude-auth@0.5.5 |
npm i -g opencode-claude-auth |
| Platform | macOS arm64 | — |
Expected vs Actual
- Expected: Plugins load and function the same way as upstream
opencode, sinceocvis based on the same1.2.27codebase. - Actual: Plugin loading silently fails. The
-vim.2suffix causes the plugin system to request a non-existent package version from npm.
Root Cause
The version suffix "-vim.2" propagates into two functions in the plugin dependency resolution pipeline (packages/opencode/src/config/config.ts), both of which use Installation.VERSION directly.
1. Version hardcoded in the binary
# Extracted from the compiled ocv binary:
Installation.VERSION = "1.2.27-vim.2";
# Versus upstream opencode:
Installation.VERSION = "1.2.27";
2. needsInstall() uses strict equality
const targetVersion = Installation.isLocal() ? "latest" : Installation.VERSION
// ocv: targetVersion = "1.2.27-vim.2"
// ...
if (depVersion === targetVersion) return false // strict equality — no semver coercion
return true // triggers reinstallThe cached @opencode-ai/plugin is at version "1.2.27" (installed by upstream opencode or a previous successful install). The check "1.2.27" === "1.2.27-vim.2" fails, so it always triggers a reinstall.
3. installDependencies() writes the unresolvable version
const targetVersion = Installation.isLocal() ? "*" : Installation.VERSION
json.dependencies = {
...json.dependencies,
"@opencode-ai/plugin": targetVersion, // writes "1.2.27-vim.2"
}
// then runs bun install → tries to fetch @opencode-ai/plugin@1.2.27-vim.2 → 4044. The version does not exist on npm
$ npm view @opencode-ai/plugin@1.2.27-vim.2 version
npm error code E404
npm error 404 No match found for version 1.2.27-vim.2
npm error 404 The requested resource '@opencode-ai/plugin@1.2.27-vim.2' could not be found
Published versions (all upstream):
1.2.18, 1.2.19, 1.2.20, 1.2.21, 1.2.22, 1.2.23, 1.2.24, 1.2.25, 1.2.26, 1.2.27
Failure chain
ocv starts
→ Installation.VERSION = "1.2.27-vim.2"
→ Config.needsInstall()
→ depVersion ("1.2.27") !== targetVersion ("1.2.27-vim.2")
→ returns true → triggers install
→ Config.installDependencies()
→ writes "@opencode-ai/plugin": "1.2.27-vim.2" to ~/.cache/opencode/package.json
→ bun install → npm 404 → install fails
→ Config.waitForDependencies() completes (error caught silently)
→ Plugin loader attempts import → node_modules in broken/stale state → fails
→ Plugin visible in /status but non-functional
Secondary issue: shared cache conflict
Both opencode and ocv share ~/.cache/opencode/. They overwrite each other's @opencode-ai/plugin target version on every startup:
opencoderuns → writes"@opencode-ai/plugin": "1.2.27"→ bun install succeedsocvruns → writes"@opencode-ai/plugin": "1.2.27-vim.2"→ bun install failsopencoderuns → writes"1.2.27"again → succeeds- (repeat)
Suggested Fix
The -vim.2 suffix is a semver prerelease identifier. The plugin SDK version should be derived from the base upstream version that ocv is forked from, not the full fork version string.
Option A — Strip prerelease suffix for plugin resolution
semver is already imported in the codebase.
// In both needsInstall() and installDependencies():
import semver from "semver"
const baseVersion = `${semver.major(Installation.VERSION)}.${semver.minor(Installation.VERSION)}.${semver.patch(Installation.VERSION)}`
const targetVersion = Installation.isLocal() ? "*" : baseVersion
// "1.2.27-vim.2" → "1.2.27"Option B — Separate constant for upstream base version
Installation.VERSION = "1.2.27-vim.2" // display / user-agent
Installation.UPSTREAM_VERSION = "1.2.27" // plugin SDK resolutionUse UPSTREAM_VERSION in needsInstall() and installDependencies().
Option C — Separate cache directory (complementary)
// ~/.cache/ocv/ instead of ~/.cache/opencode/Prevents the shared-cache conflict when both binaries are installed, but still needs Option A or B to resolve the core 404 issue.
References
- Upstream plugin loader:
packages/opencode/src/plugin/index.ts - Upstream config + install logic:
packages/opencode/src/config/config.ts @opencode-ai/pluginon npmopencode-claude-authon npm
ocv version
1.2.27-vim.2
Steps to reproduce
- Install
ocv:brew install leohenon/tap/ocv
- Install a plugin globally:
npm i -g opencode-claude-auth
- Add the plugin to
~/.config/opencode/opencode.json:{ "plugin": ["opencode-claude-auth"] } - Run
ocvand open a session - Type
/status— plugin is listed under plugins - Verify it's non-functional — Claude credentials are not synced to
~/.local/share/opencode/auth.json
To confirm the version mismatch is the cause:
# The version ocv uses for plugin SDK resolution:
strings $(which ocv) | grep 'Installation.VERSION'
# → Installation.VERSION = "1.2.27-vim.2";
# That version does not exist on npm:
npm view @opencode-ai/plugin@1.2.27-vim.2 version
# → npm error 404 No match found for version 1.2.27-vim.2
# The lockfile shows what's actually resolved (upstream version):
cat ~/.cache/opencode/bun.lock | grep '@opencode-ai/plugin'
# → "@opencode-ai/plugin": ["@opencode-ai/plugin@1.2.27", ...]
# Compare: upstream opencode works with the same plugin and config
opencode # → plugin loads and functions correctly