Summary
graphify install --platform opencode writes a V1-format OpenCode plugin that OpenCode V2 refuses to load, and registers it in .opencode/opencode.json under the V1 plugin key, which V2 also rejects. The result is a failed server plugin load plus a spurious npm-install error.
Environment
- OpenCode
v2.0.12 (Bun-compiled binary, background service)
- graphify
0.9.65 (latest on PyPI at the time of writing)
Observed
OpenCode server log (~/.local/share/opencode/log/opencode.log, role=server):
level=WARN message="failed to load plugin"
target=.../.opencode/plugins/graphify.js ref=err_...
cause="Cause([Fail(PluginModule.LoadError: Plugin must export a default definition
with an id and an effect or setup function. (cause: SchemaError(Missing key at ["default"])))])"
A second, separate failure comes from the config registration being treated as an npm package spec:
level=WARN message="failed to load plugin" target=.opencode/plugins/graphify.js
cause="Cause([Fail(NpmInstallFailedError (cause: Error: Could not read package.json:
ENOTDIR: not a directory, open '.../.opencode/plugins/graphify.js/package.json'))])"
Cause
- OpenCode V2 requires a plugin to default-export a definition with an
id and a setup (or effect) function, and hooks are registered on their domain via ctx.tool.hook("execute.before", ...). V1 plugin functions (named export returning a "tool.execute.before" object) no longer run.
- V2 renamed the shell tool id from
bash to shell.
graphify/install.py::_OPENCODE_PLUGIN_JS is still the V1 shape.
_install_opencode_plugin registers the file under the V1 plugin key using a bare relative path. V2 reads plugins, and a bare path is interpreted as an npm package, producing the NpmInstallFailedError.
- V2 auto-discovers plugins under
.opencode/plugins/, so the config registration is unnecessary.
Suggested fix
- Emit a V2 default-export plugin. A plain object literal is sufficient;
Plugin.define from @opencode/plugin is not resolvable from a loose file under .opencode/plugins/ (no node_modules).
- Drop the
opencode.json registration (auto-discovery handles it), or move it to plugins with a resolvable path.
- Accept both
shell (V2) and bash (V1) tool ids, and use event.input.command instead of output.args.command.
Reference port:
import { existsSync } from "fs";
import { join } from "path";
export default {
id: "graphify",
async setup(ctx) {
let reminded = false;
await ctx.tool.hook("execute.before", (event) => {
if (reminded) return;
if (!existsSync(join(ctx.location.directory, "graphify-out", "graph.json"))) return;
if (event.tool === "shell" || event.tool === "bash") {
event.input.command =
'echo "[graphify] ..." ; ' + event.input.command;
reminded = true;
}
});
},
};
A local patch to install.py and tests/test_install.py is available on request.
Summary
graphify install --platform opencodewrites a V1-format OpenCode plugin that OpenCode V2 refuses to load, and registers it in.opencode/opencode.jsonunder the V1pluginkey, which V2 also rejects. The result is a failed server plugin load plus a spurious npm-install error.Environment
v2.0.12(Bun-compiled binary, background service)0.9.65(latest on PyPI at the time of writing)Observed
OpenCode server log (
~/.local/share/opencode/log/opencode.log,role=server):A second, separate failure comes from the config registration being treated as an npm package spec:
Cause
idand asetup(oreffect) function, and hooks are registered on their domain viactx.tool.hook("execute.before", ...). V1 plugin functions (named export returning a"tool.execute.before"object) no longer run.bashtoshell.graphify/install.py::_OPENCODE_PLUGIN_JSis still the V1 shape._install_opencode_pluginregisters the file under the V1pluginkey using a bare relative path. V2 readsplugins, and a bare path is interpreted as an npm package, producing theNpmInstallFailedError..opencode/plugins/, so the config registration is unnecessary.Suggested fix
Plugin.definefrom@opencode/pluginis not resolvable from a loose file under.opencode/plugins/(nonode_modules).opencode.jsonregistration (auto-discovery handles it), or move it topluginswith a resolvable path.shell(V2) andbash(V1) tool ids, and useevent.input.commandinstead ofoutput.args.command.Reference port:
A local patch to
install.pyandtests/test_install.pyis available on request.