- Yes, for npm plugins: OpenCode treats
package.jsonas the install/runtime manifest viareadPluginManifest()inpackages/opencode/src/plugin/install.ts. packageTargets()in the same file readsexports["./server"],exports["./tui"],main(server fallback), optionaloc-themes, andengines.opencode.- For path/file plugins, no separate manifest file is required: module shape is validated by
readV1Plugin()inpackages/opencode/src/plugin/shared.ts(default export object withserver()ortui()), and path plugins must provideid(resolvePluginId()). - Plugin specs are declared as config
pluginentries (Spec) inpackages/opencode/src/config/plugin.ts.
- Yes (indirect, but real):
Hooks["chat.message"]inpackages/plugin/src/index.tslets a plugin mutateoutput.messagebefore persistence. - In
SessionPrompt.createUserMessage(packages/opencode/src/session/prompt.ts), OpenCode calls:plugin.trigger("chat.message", ..., { message: info, parts })- then
sessions.updateMessage(info).
- In
runLoop(same file), request execution resolves model from persistedlastUser.modeland callsgetModel(lastUser.model.providerID, lastUser.model.modelID, sessionID). - Therefore, a plugin can override which model runs by rewriting
output.message.modelinchat.message. - There is no dedicated
registerProviderSelector-style API.
- TUI slash commands: yes.
- API:
TuiPluginApi.command.register()andTuiCommand.slashinpackages/plugin/src/tui.ts. - Runtime wiring:
pluginApi().command.registerinpackages/opencode/src/cli/cmd/tui/plugin/runtime.ts. - Slash exposure:
slashes()inpackages/opencode/src/cli/cmd/tui/component/dialog-command.tsx; consumed by prompt autocomplete inpackages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx.
- API:
- Server slash command registration: no.
- Prompt submission only dispatches
/...when command exists insync.data.command(submit()inpackages/opencode/src/cli/cmd/tui/component/prompt/index.tsx). - Server command list is built in
packages/opencode/src/command/index.tsfrom config/MCP/skills; plugin hooks do not register new server command handlers. - A fork patch would likely touch
packages/opencode/src/command/index.ts(registration surface) andpackages/opencode/src/cli/cmd/tui/component/prompt/index.tsx(dispatch path), plus server route wiring.
- Prompt submission only dispatches
- No single dedicated "before request" callback exists.
- But plugins can emit UX indicators before execution:
- Server plugin hook
chat.messagecan callPluginInput.client.tui.showToast()/appendPrompt()(SDK methods inpackages/sdk/js/src/gen/sdk.gen.ts, classTui). - Backing endpoints exist in
packages/opencode/src/server/routes/instance/tui.ts(/tui/show-toast,/tui/append-prompt). - TUI plugins can render persistent status text via slots (
session_prompt_rightinTuiHostSlotMap,packages/plugin/src/tui.ts) usingapi.slots.register(...).
- Server plugin hook
Hybrid — model routing itself is plugin-capable via chat.message, but exact /model <id> + /route server-command semantics are not first-class plugin hooks and need either UX adaptation to TUI plugin commands or a small OpenCode core patch.