# OpenCode
ID: `opencode` — `agent_config::by_id("opencode")`
(`sst/opencode` — the open-source AI coding agent.)
## Hooks
### User scope (`Scope::Global`)
| File | `~/.config/opencode/plugins/<tag>.ts` |
| Mechanism | One TypeScript plugin file per consumer |
| Backup | `<file>.bak` (only if the file already existed before install) |
### Project scope (`Scope::Local(<root>)`)
| File | `<root>/.opencode/plugins/<tag>.ts` |
| Mechanism | One TypeScript plugin file per consumer |
| Backup | `<file>.bak` (only if the file already existed before install) |
> OpenCode also supports plugins listed in the `plugin` array of
> `opencode.json`, auto-installed via Bun. Not used here; we drop a single
> file in the plugins directory.
### Format
The default plugin (when `HookSpec::script` is `None`):
```ts
// Generated by agent-config. Edit at your own risk.
// Re-running install will overwrite this file.
import type { Plugin } from "@opencode-ai/plugin";
export const Hook: Plugin = async ({ $ }) => ({
"tool.execute.before": async ({ tool }, { args }) => {
if (tool !== "bash") return;
const payload = JSON.stringify({ tool, args });
await $`echo ${payload} | myapp hook opencode`;
},
});
```
Pass `ScriptTemplate::TypeScript(body)` on the `HookSpec` to ship a custom
plugin instead. The library writes the body verbatim.
### Event mapping
The `Event` enum is currently ignored by this integration — OpenCode's hook
points are namespaced strings (`tool.execute.before`, `session.start`,
`message.before`, etc.) and the plugin body declares which it implements.
Use a custom script to attach to anything other than `tool.execute.before`.
OpenCode supports 25+ hook points: `tool.execute.before/after`, session/file/
message/shell/command/LSP/permission/server/todo/TUI families.
### Matcher mapping
The `Matcher` enum is currently unused by this integration — the default
plugin guards on `tool === "bash"` inside the TS body. Use a custom script
to filter differently.
## Prompt instructions
OpenCode reads system instructions from `AGENTS.md`. Use the Codex
integration to write that file.
## MCP servers
### User scope (`Scope::Global`)
| File | `~/.config/opencode/opencode.json` |
| Key | `mcp` |
| Format | JSONC accepted, written as JSON |
### Project scope (`Scope::Local(<root>)`)
| File | `<root>/opencode.json` |
| Format | JSONC accepted, written as JSON |
| Key | `mcp` (object keyed by server name) |
### Configuration
```json
{
"mcp": {
"my-server": {
"type": "local",
"command": ["node", "/path/to/server.js"]
}
}
}
```
OpenCode automatically handles OAuth for remote servers and supports both local
(command array) and remote (url) transports.
## Skills
| User | `~/.config/opencode/skills/<name>/` |
| Project | `.opencode/skills/<name>/` |
OpenCode also scans Claude-compatible and `.agents/skills` locations, but
`agent-config` writes the native OpenCode path for this integration.
## References
- <https://opencode.ai/docs/plugins/>
- <https://opencode.ai/docs/config/>
- <https://opencode.ai/docs/mcp-servers/>
- <https://opencode.ai/docs/skills>
- <https://github.com/sst/opencode>