agent-config 0.2.0

Install hooks/integrations into AI coding harnesses (Claude Code, Cursor, Gemini CLI, OpenCode, Codex CLI, Cline, Windsurf, ...) without learning each one's filesystem layout.
Documentation
# 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 (input, output) => {
    if (input.tool !== "bash") return;
    const payload = JSON.stringify({ tool: input.tool, args: output.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 `input.tool === "bash"` inside the TS body. Use a custom script
to filter differently.

## Prompt instructions

OpenCode reads system instructions from `AGENTS.md`.

| Scope | Host file |
| --- | --- |
| User | `~/.config/opencode/AGENTS.md` |
| Project | `<root>/AGENTS.md` |

When `HookSpec::rules` is present, this integration injects the rules body as a
tagged `AGENT-CONFIG:<tag>` HTML-comment fenced block in that host file.

## Instructions

Standalone instruction bodies installed via `InstructionSurface` use
`InstructionPlacement::InlineBlock`. The body is injected as a tagged
`AGENT-CONFIG-INSTR:<name>` HTML-comment fenced block in OpenCode's `AGENTS.md`
file.

### User scope (`Scope::Global`)

| | |
| --- | --- |
| Host file | `~/.config/opencode/AGENTS.md` |
| Mechanism | Tagged HTML-comment fence (`<!-- BEGIN AGENT-CONFIG-INSTR:<name> -->`) |
| Ledger | `~/.config/opencode/.agent-config-instructions.json` |
| Placement | `InstructionPlacement::InlineBlock` |

### Project scope (`Scope::Local(<root>)`)

| | |
| --- | --- |
| Host file | `<root>/AGENTS.md` |
| Mechanism | Tagged HTML-comment fence (`<!-- BEGIN AGENT-CONFIG-INSTR:<name> -->`) |
| Ledger | `<root>/.opencode/.agent-config-instructions.json` |
| Placement | `InstructionPlacement::InlineBlock` |

## 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

| Scope | Path |
| --- | --- |
| 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/rules/>
- <https://opencode.ai/docs/config/>
- <https://opencode.ai/docs/mcp-servers/>
- <https://opencode.ai/docs/skills>
- <https://github.com/sst/opencode>