Skip to content

Plugin @latest cache can stay pinned to stale npm version #25293

Closed as not planned

Description

@sm18lr88

What happened?

A plugin configured as oh-my-openagent@latest stayed pinned to an older npm package version in OpenCode's plugin package cache, even though npm latest had advanced.

This caused OpenCode to keep loading old plugin behavior until I manually removed the cached package directory and pinned the plugin to the current version.

Evidence

My OpenCode config had:

{
  "plugin": [
    "oh-my-openagent@latest"
  ]
}

But the OpenCode package cache contained:

// C:\Users\Me\.cache\opencode\packages\oh-my-openagent@latest\package.json
{
  "dependencies": {
    "oh-my-openagent": "3.17.4"
  }
}

At the same time:

npm view oh-my-openagent version
# 3.17.12

So @latest was not re-resolved. The cache directory was valid enough for the plugin to load, but it loaded stale code.

User-visible impact

The stale oh-my-openagent 3.17.4 build had older model routing behavior. It treated Sisyphus + GPT-5.5 as invalid and switched sessions to Hephaestus, even though oh-my-openagent 3.17.12 includes GPT-5.5-native Sisyphus support.

Expected behavior

For plugin specs using a moving tag/range such as package@latest, OpenCode should periodically re-resolve the package, validate whether the cached dependency satisfies the requested spec, or otherwise avoid treating the wrapper cache directory as permanently fresh.

At minimum, a cache hit for oh-my-openagent@latest should not continue to use oh-my-openagent 3.17.4 after npm latest is 3.17.12.

Actual behavior

OpenCode reused:

C:\Users\Me\.cache\opencode\packages\oh-my-openagent@latest

The wrapper package.json inside that cache still depended on oh-my-openagent 3.17.4.

Workaround

This fixed the issue locally:

Remove-Item -LiteralPath 'C:\Users\Me\.cache\opencode\packages\oh-my-openagent@latest' -Recurse -Force

Then I pinned the plugin explicitly:

{
  "plugin": [
    "[email protected]"
  ]
}

I also preinstalled the pinned cache path:

npm install --prefix C:\Users\Me\.cache\opencode\packages\oh-my-openagent@3.17.12 oh-my-openagent@3.17.12

Related issue

This seems related to plugin package cache behavior discussed in #23502, but this report is specifically about a successful/usable cache hit for @latest staying pinned to a stale dependency version rather than an ENOENT or incomplete install.

Environment

  • OS: Microsoft Windows NT 10.0.26200.0
  • OpenCode: 1.14.31
  • Node: v22.20.0
  • npm: 10.9.3
  • Plugin spec: oh-my-openagent@latest
  • Cached dependency observed: oh-my-openagent 3.17.4
  • npm latest observed: oh-my-openagent 3.17.12

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 1, 2026
  2. github-actions commented on May 1, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is specifically about the cache fast-path not re-checking npm for a newer version (rather than an ENOENT or broken path), it may still be worth keeping open as a distinct sub-case, but please review those issues and comment there if they cover your scenario.

  3. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  4. pokk commented on May 19, 2026

    @pokk

    Additional repro (macOS, OpenCode 1.15.5)

    Same bug, different OS, and a second plugin — confirming this isn't oh-my-openagent-specific.

    Plugin 1: oh-my-openagent@latest

    Cached version 4.1.2
    npm latest 4.2.2
    Cache path ~/.cache/opencode/packages/oh-my-openagent@latest/node_modules/oh-my-openagent/
    Stale for ~24h after v4.2.2 dropped; would have stayed indefinitely without manual cleanup.

    Plugin 2: @ex-machina/opencode-anthropic-auth@latest

    Cached version 1.8.0
    npm latest 1.8.1
    Cache path ~/.cache/opencode/packages/@ex-machina/opencode-anthropic-auth@latest/node_modules/@ex-machina/opencode-anthropic-auth/
    Stale for ~5 days.

    Both directories were created on 2026-05-15 (first opencode launch with these plugins). Neither was ever re-resolved on subsequent session starts.

    Workaround (POSIX flavor of the original report)

    rm -rf ~/.cache/opencode/packages/oh-my-openagent@latest \
           ~/.cache/opencode/packages/@ex-machina/opencode-anthropic-auth@latest

    Next opencode start re-downloads to current npm latest.

    Environment

    • OS: macOS 26 (arm64)
    • OpenCode: 1.15.5 (released 2026-05-18) — bug persists across the entire 1.14.x → 1.15.x range
    • Plugin specs in opencode.json (cmux-managed):
      • oh-my-openagent@latest
      • @ex-machina/opencode-anthropic-auth@latest

    Side note

    Any floating-tag spec (@latest, @beta, @next, etc.) hits this surface because the per-plugin cache directory is keyed by the literal version-spec string. The flat shared-deps tree at ~/.cache/opencode/packages/node_modules/ does refresh on its own schedule, but it isn't the path opencode resolves plugin entrypoints from (that's the per-plugin isolated <spec>/node_modules/<pkg>/ tree).

  5. agopalareddy commented on Jun 3, 2026

    @agopalareddy

    Additional reproduction + root cause confirmation (OpenCode 1.15.13, Linux, Bun)

    Can confirm this is still happening on the latest release. Tracked down the exact code path.

    Concrete impact case: @tarquinen/opencode-dcp

    DCP 3.1.8 had a bug where the messages.transform hook created a shadowed local array copy (messages.filter(...) returns a new array), so structural mutations from the prune() function (messages.length = 0; messages.push(...)) never propagated back to output.messages. Net result: the compress tool fired, summaries were generated, but the LLM never saw the compressed context — it kept receiving the full uncompressed messages. Context grew monotonically, compression was a no-op.

    The fix shipped in 3.1.12. But on my system, @latest was permanently pinned to 3.1.8 (installed back in April).

    Root cause chain

    In packages/opencode/src/plugin/shared.ts:

    export async function resolvePluginTarget(spec: string) {
      if (isPathPluginSpec(spec)) return resolvePathPluginTarget(spec)
      const hit = parse(spec)
      const pkg = hit?.name && hit.raw === hit.name ? `${hit.name}@latest` : spec
      const result = await Npm.add(pkg)  // ← resolves once, creates pinned wrapper, never re-checks
      return result.directory
    }

    Npm.add() operates like npm install — it writes a package.json with the resolved version at install time and never re-evaluates on subsequent starts. The wrapper directory at packages/<plugin>@latest/ is treated as "valid" and its node_modules are satisfied, so the loader returns it without ever hitting npm again.

    Stale caches observed

    # wrapper still pinning old version from April
    $ cat ~/.cache/opencode/packages/@tarquinen/opencode-dcp@latest/package.json
    { "dependencies": { "@tarquinen/opencode-dcp": "3.1.8" } }
    
    # npm has moved on
    $ npm view @tarquinen/opencode-dcp version
    3.1.12

    Suggested approach

    The simplest path matches the suggestion already here — on startup, if a plugin spec contains @latest (or any floating range), compare the installed wrapper version against npm and either auto-update or warn. Even just logging a warning when the installed version is behind npm latest would surface this to users who have no idea they're stuck on stale code.

  6. holgerreppert commented on Jun 8, 2026

    @holgerreppert

    Same here. Would be nice to have my plugin updated.....

  7. dio16 commented on Jun 13, 2026

    @dio16

    I was about to file a duplicate, but this issue already covers the root behavior. Adding a Linux + oh-my-opencode-slim@latest repro because it reproduced the same stale @latest cache path after opencode plugin -g -f.

    Repro

    • Published latest observed:

      pnpm view oh-my-opencode-slim version
      # 2.0.0
    • Cached plugin version observed before workaround:

      OpenCode plugin cache entry for oh-my-opencode-slim@latest reported: 1.1.2
      
    • Force-updating global plugin config:

      opencode plugin -g -f oh-my-opencode-slim@latest

      This updated the OpenCode plugin config, but the cached plugin still reported 1.1.2. The UI kept loading the old version until the cache directory was removed.

    Workaround

    rm -rf <OpenCode plugin cache dir>/packages/oh-my-opencode-slim@latest
    opencode plugin -g -f oh-my-opencode-slim@latest

    After removing the cache directory, @latest resolved to 2.0.0.

    Suggested fix direction

    The cache key appears to be the literal spec string, so oh-my-opencode-slim@latest reuses the same cache entry even when npm latest changes. A robust fix would resolve floating specs before cache lookup and include the resolved version in the cache key, or force-delete/refresh the existing cache directory when -f is used with a floating spec.

    Example direction:

    async function installPlugin(spec: string, options: { force?: boolean }) {
      const resolved = await resolvePackageSpec(spec);
      // Example: oh-my-opencode-slim@latest -> [email protected]
      const cacheKey = `${resolved.name}@${resolved.version}`;
      const cacheDir = getPluginCacheDir(cacheKey);
    
      if (options.force) {
        await fs.rm(cacheDir, { recursive: true, force: true });
      }
    
      await ensurePluginCache(cacheDir, resolved.spec);
    }

    Template fields

    • OpenCode version: 1.17.4
    • Terminal: xterm-256color
    • Operating System: Linux/WSL
    • Screenshot/share link: not attached; reproduced via CLI/cache inspection instead.
  8. github-actions commented on Aug 13, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions