Skip to content

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

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

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

Metadata

Metadata

Assignees

No one assigned

    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