Skip to content

plugins: local plugins cannot resolve "@opencode/plugin" import (2.0.12) #50434

Closed

Description

@frankfletcher

Summary

Local plugins written with the documented V2 pattern — import { Plugin } from "@opencode/plugin" plus export default Plugin.define(...) — fail to load in OpenCode 2.0.12 with Cannot find package '@opencode/plugin'. Node and Bun resolve the same import from the same directories without issue, so the server's plugin module resolver is at fault.

Environment

  • opencode version: 2.0.12 (channel=latest)
  • OS: Linux (Ubuntu, kernel 7.0.0-31-generic, x86_64, glibc)
  • Terminal: xterm-256color, truecolor
  • Shell: /bin/bash
  • Install/channel: Homebrew tap anomalyco/tap/opencode-v2
  • Active plugins: vexp-guard (local; kept working via the no-import workaround below). Earlier local plugins (rtk.ts) and the V1 package plugin openslimedit@latest also failed to load with the same resolution error after porting to the documented V2 pattern.

Reproduction

  1. Create a project with .opencode/plugins/probe.js:
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "probe",
  setup() {},
})
  1. Run a headless session with server logs: opencode run --print-logs "hi" (or just open the TUI and inspect ~/.local/share/opencode/log/opencode.log).
  2. Observe the load failure:
failed to load plugin target=<project>/.opencode/plugins/probe.js
cause="Cause([Die(ResolveMessage: Cannot find package '@opencode/plugin' imported from <project>/.opencode/plugins/probe.js)])"

Expected Behavior

Local plugins using the documented @opencode/plugin import load and appear in the plugin list with source: local and status: active (visible via opencode api get /api/plugin).

Actual Behavior

@opencode/plugin cannot be resolved by the server's plugin bundler, so every local plugin written with the documented pattern fails to load. Isolation findings:

  • Node resolves the same import from the same file: node -e "import('@opencode/plugin').then(() => console.log('ok'))" works.
  • Bun resolves it too: bun -e "import('@opencode/plugin').then(() => console.log('ok'))" works.
  • Installing @opencode/plugin@2.0.12 (and its @opencode/* dependencies) into node_modules — both as an ancestor of the plugin file and in the global config dir ~/.config/opencode/node_modules — does not help.
  • Unscoped bare imports DO resolve from the plugin directory (import { parse } from "yaml" from the config-dir node_modules loaded fine), so the loader itself is healthy.
  • Scoped and subpath imports fail even when the target files exist: @opencode/ai/schema, yaml/dist/yaml.mjs, and — inside @opencode/plugin's own dist — @opencode/schema/agent, effect/unstable/httpapi, and the peer @opencode/theme.
  • Plugins with no bare imports load fine: a plain export default { id, setup(ctx) } using only node: builtins is accepted by the loader and receives the full context (ctx.tool.hook("execute.before", ...) works).

This looks like a resolver that mishandles package exports/subpath resolution for local plugin files, separate from the LOADER (the loader's shape validation of the default export works).

Additional Context

  • Frequency: reproducible consistently (100%).
  • Also reproduced with the official npm build: npm install -g @opencode/cli@2.0.12 → native binary @opencode/cli-linux-x64 has the same BuildID as the brew binary and fails identically, so this is a runtime defect, not an installer quirk.
  • Recent change: migrated from OpenCode 1.x to 2.0.12. The V1 plugin API breakage is expected, but the documented V2 replacement pattern for local plugins does not work either.
  • Workaround currently in use (works, but bypasses the type-checked Plugin.define): omit the bare import and export a plain object —
export default {
  id: "vexp-guard",
  async setup(ctx) {
    await ctx.tool.hook("execute.before", (event) => {
      // ...
    })
  },
}

Activity

  1. alexrs-cohere commented on Sep 25, 2026

    @alexrs-cohere

    Still reproduces on 2.0.16 (channel=latest), and also for plugins auto-discovered from the global config dir (~/.config/opencode/plugins/), so it isn't limited to project .opencode/plugins/ or config plugins entries.

    Environment

    • opencode version: 2.0.16 (channel=latest)
    • OS: Linux 6.12.90+deb13.1-cloud-amd64 (Debian), x86_64
    • Terminal: tmux, TERM=xterm-256color, COLORTERM=truecolor
    • Shell: zsh
    • Node: v24.18.0 present; it resolves @opencode/plugin fine from the same directory, so the failure is in the server's plugin resolver

    Reproduction

    1. Create ~/.config/opencode/plugins/_probe.ts:
    import { Plugin } from "@opencode/plugin"
    
    export default Plugin.define({
      id: "probe",
      setup() {},
    })
    1. Save the file (or restart). The server log shows:
    level=WARN message="failed to load plugin" target=…/_probe.ts
      cause="Cause([Die(ResolveMessage: Cannot find package '@opencode/plugin' imported from …/_probe.ts)])"
    

    Nothing surfaces in the session; the plugin's hooks and tools are simply absent.

    Workaround that works on 2.0.16: export the definition object directly, with no import —

    export default {
      id: "probe",
      setup() {},
    }

    Plugin.define appears to be a typed identity helper, so the runtime object is equivalent. Both plugins I ported this way load and register their tools/hooks correctly on 2.0.16.

  2. holny commented on Sep 28, 2026

    @holny
    Contributor

    Gentle nudge — this has been open for a week with checks green and no review. The fix is contained: the resolve hook reads scoped @opencode/* imports from the project directory (found by walking back to the .opencode segment of the entrypoint) instead of the plugin file's own directory, and files inside node_modules skip tracking as before. Happy to rebase or adjust.

  3. CarlosCorreaB9 commented on Sep 30, 2026

    @CarlosCorreaB9

    Confirmed on the current stable release — adding occurrence evidence from a different platform (Windows) and a managed-plugin set.

    Occurrence

    • opencode: 2.0.20 (@opencode/plugin dist-tag latest = 2.0.20, i.e. current stable)
    • Platform: Windows, compiled Bun executable
    • Affected location: the global config dir, ~/.config/opencode/plugins/ (auto-discovered, no plugins entry in opencode.json)
    • Affected plugins: 5 of 5 managed loose .ts files in that directory
    • Frequency: 100%, every server boot and every watcher reload

    Observed log lines (verbatim, path redacted to the documented location)

    msg="loading plugin" id=".../plugins/telemetry-runtime.ts" entrypoint="file:///.../plugins/telemetry-runtime.ts"
    level=WARN message="failed to load plugin" target=".../plugins/telemetry-runtime.ts"
      cause="Cause([Die(ResolveMessage: Cannot find package '@opencode/plugin' imported from .../plugins/telemetry-runtime.ts)])"
    

    The same ResolveMessage appears for every loose plugin in the directory, on every boot. Cumulative count observed in the persisted server log: 23–50 occurrences per plugin since 2026-09-19, still reproducing in the most recent boot.

    Isolation checks performed

    • No package.json and no node_modules exist in the global config dir. Consistent with the docs statement that local files "are imported directly" and their dependencies are not installed for you.
    • The import is the documented v2 package: @opencode/plugin resolves on npm at 2.0.20, an exact match for the installed runtime. It is not a typo for the 1.18.x line (@opencode-ai/plugin, latest 1.18.33).
    • Every affected file uses the documented shape: bare import { Plugin } from "@opencode/plugin" plus export default Plugin.define({ id, setup }).
    • The failure is silent outside the log: no session error and no TUI hint. The only visible symptom is that the hooks and tools the plugins register simply do not exist.

    This matches the isolation findings already in this thread, including the report that installing the package into node_modules does not help.

    Related upstream work

    PR #49097 ("fix(plugin): serve bundled SDK to loose plugin files on Bun") describes this as the Bun server side missing the module shim that the Node prelude already installs, and proposes registering the host's own @opencode/plugin specifiers as Bun virtual modules.

    As of this report that PR is still open and unmerged (mergedAt: null, base v2), so no released build contains it. The workaround documented in this thread — dropping the bare import and exporting a plain object with id + setup — avoids the defect but gives up the type-checked Plugin.define surface.

  4. DennisBecker commented on Oct 6, 2026

    @DennisBecker

    I have the same issue when running opencode with a local plugin. Starting opencode v2 it shows 1 plugin failed and /plugins selecting the one plugin shows this error:

    ResolveMessage: Cannot find package '@opencode/plugin' imported from /Users/REDACTED/.config/opencode/my-plugin/src/my-models.ts
        at Plugin.load (/$bunfs/root/chunk-8easrj4b.js:137:26196)
        at Plugin.activate (/$bunfs/root/chunk-fd05ppfs.js:354:30082)
        at Plugin.activate (definition) (/$bunfs/root/chunk-8easrj4b.js:137:26439)
        at PluginSupervisor.activate (/$bunfs/root/chunk-fd05ppfs.js:354:31043)
        at PluginSupervisor.activate (definition) (/$bunfs/root/chunk-fd05ppfs.js:354:29545)
        at ServerProcess.start (/$bunfs/root/chunk-1v3746hj.js:2:6612)
        at ServerProcess.start (definition) (/$bunfs/root/chunk-fd05ppfs.js:448:25082)
    

    Fresh clean install of v2.0.23 - updated to v2.0.24

  5. mgajda commented on Oct 18, 2026

    @mgajda

    Confirmed, and I think the mechanism is specific: it depends on the working directory.

    Bun resolves the bare specifier by walking up from the importing file. The repo tool files live at
    <repo>/.opencode/tool/*.ts, and <repo>/node_modules/@opencode/plugin is a workspace symlink to
    packages/plugin. So inside the opencode repo the import resolves to the repo's own v2 source,
    packages/plugin/src/promise/index.ts, which does not export tool — it was dropped in v2
    (f28c10aa4d). The dynamic import throws:

    SyntaxError: Export named 'tool' not found in module '.../packages/plugin/src/promise/index.ts'.
      at ToolRegistry.all -> ToolRegistry.tools -> SessionTools.resolve -> SessionPrompt.run
    

    Outside the repo the files aren't loaded at all, which is why it looks working-directory dependent.

    Two things worth noting for the fix:

    1. Disabling the tool in config does not avoid it. .opencode/opencode.jsonc sets
      "tools": { "github-triage": false, "github-pr-search": false } and the error still fires — the
      registry imports the module to enumerate before the enabled flag applies.
    2. .opencode/node_modules/@opencode-ai/plugin@1.18.31 does export tool, and it sits closer
      to the importing file, so the same import spelled @opencode-ai/plugin would resolve to it.

    On my machine this is 18 of 790 ERROR lines (2.3%), and it fires once per launch inside the
    repo — 8 times in a single day, every launch, deterministically.

    Context: #35325, #36582.

  6. added a commit that references this issue on Oct 21, 2026
    0228d19
  7. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report. I reproduced this on 2.0.12: a local .opencode/plugins/probe.js that does import { Plugin } from "@opencode/plugin" and export default Plugin.define(...) fails with Cannot find package '@opencode/plugin', and its setup() never runs.

    With the same setup on the latest release, 2.2.0, the plugin loads and setup() runs. I couldn't test the latest dev from source here, so this result is from the published 2.2.0 release. The likely fix is #53422, which makes OpenCode's own @opencode/plugin and effect modules available to plugins. It first shipped in 2.0.25. Upgrading (opencode upgrade, or npm i -g @opencode/cli@latest / your Homebrew tap) should let you go back to the typed Plugin.define pattern. The script below reproduces it.

    The bot will close this issue in 1 day unless you reply that it still happens on 2.0.25 or newer.

  8. opencodejr commented on Oct 29, 2026

    @opencodejr

    I'm closing this because there has been no reply since my last comment. I reproduced the Cannot find package '@opencode/plugin' failure for a local Plugin.define plugin on 2.0.12. On the latest release, 2.2.0, the same plugin loads and its setup() runs. The likely fix is #53422, which first shipped in 2.0.25, so upgrading should let you use the typed Plugin.define pattern again instead of the plain-object workaround.

    If it still happens on 2.0.25 or newer, please comment here or open a new issue with your version and the log line, and we'll look again. Thanks for the detailed report!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions