What happened
Plugin.init() in packages/opencode/src/plugin/index.ts is a stub that only logs "plugin system stub - init called" and returns. External plugins from ~/.config/opencode/plugins/ are never loaded.
This was introduced in commit 53f683f when we aligned the plugin system with upstream in PR #392. The alignment restored upstream's Effect-based plugin files but left init() as a stub since the fork doesn't use Effect.
Expected behaviour
Plugin.init() loads internal plugins (CodexAuthPlugin, CopilotAuthPlugin)
Plugin.init() loads external plugins from config directories via PluginLoader.loadExternal()
- Plugins receive a
PluginInput with an SDK client, project info, and Bun shell access
- Plugin load failures are logged but don't crash the system
Root Cause
Commit 53f683f replaced the working init() with a stub:
export async function init() {
log.info("plugin system stub - init called")
}
All the supporting infrastructure still exists and works:
Config.get() scans ~/.config/opencode/plugins/*.{ts,js} and populates config.plugin[] (config.ts:460-474, 1338-1345)
PluginLoader.loadExternal() fully functional (loader.ts:152)
applyPlugin() defined (index.ts:46-52)
INTERNAL_PLUGINS defined (index.ts:15)
PluginInput type from @opencode-ai/plugin (packages/plugin/src/index.ts:26-33)
Implementation
Replace the stub init() in packages/opencode/src/plugin/index.ts:
- Add imports:
Config, Server, Instance, createOpencodeClient
- Create an SDK client with in-process fetch adapter (no HTTP roundtrip — use
Server.App().fetch() directly)
- Build
PluginInput from Instance context
- Load internal plugins via
INTERNAL_PLUGINS array
- Load external plugins via
PluginLoader.loadExternal() with error reporting
- Update
.fork-features/manifest.json with "plugin-loading" feature entry documenting this divergence from upstream
The proposed code uses @ts-ignore for the fetch type incompatibility between Hono and native fetch. Per AGENTS.md, @ts-ignore is forbidden. Use a type-safe approach instead (e.g., a properly typed adapter function or explicit cast with explanatory comment).
Acceptance Criteria
Definition of Done
What happened
Plugin.init()inpackages/opencode/src/plugin/index.tsis a stub that only logs "plugin system stub - init called" and returns. External plugins from~/.config/opencode/plugins/are never loaded.This was introduced in commit 53f683f when we aligned the plugin system with upstream in PR #392. The alignment restored upstream's Effect-based plugin files but left
init()as a stub since the fork doesn't use Effect.Expected behaviour
Plugin.init()loads internal plugins (CodexAuthPlugin, CopilotAuthPlugin)Plugin.init()loads external plugins from config directories viaPluginLoader.loadExternal()PluginInputwith an SDK client, project info, and Bun shell accessRoot Cause
Commit 53f683f replaced the working
init()with a stub:All the supporting infrastructure still exists and works:
Config.get()scans~/.config/opencode/plugins/*.{ts,js}and populatesconfig.plugin[](config.ts:460-474, 1338-1345)PluginLoader.loadExternal()fully functional (loader.ts:152)applyPlugin()defined (index.ts:46-52)INTERNAL_PLUGINSdefined (index.ts:15)PluginInputtype from@opencode-ai/plugin(packages/plugin/src/index.ts:26-33)Implementation
Replace the stub
init()inpackages/opencode/src/plugin/index.ts:Config,Server,Instance,createOpencodeClientServer.App().fetch()directly)PluginInputfrom Instance contextINTERNAL_PLUGINSarrayPluginLoader.loadExternal()with error reporting.fork-features/manifest.jsonwith"plugin-loading"feature entry documenting this divergence from upstreamQuality Gate: @ts-ignore
The proposed code uses
@ts-ignorefor the fetch type incompatibility between Hono and native fetch. Per AGENTS.md,@ts-ignoreis forbidden. Use a type-safe approach instead (e.g., a properly typed adapter function or explicit cast with explanatory comment).Acceptance Criteria
Plugin.init()loads internal plugins (CodexAuthPlugin, CopilotAuthPlugin)Plugin.init()loads external plugins from~/.config/opencode/plugins/*.{ts,js}viaPluginLoader.loadExternal()@ts-ignore,as any, or other quality gate violationsbun run typecheckpasses with 0 errorsbun testpasses (existing + new tests for plugin loading).fork-features/manifest.jsonupdated with"plugin-loading"feature entrybun run .fork-features/verify.tspassesDefinition of Done
init()Plugin.trigger()still works with loaded hooks