Overview
Oh My OpenCode is an OpenCode plugin that transforms the single-agent interface into a coordinated multi-agent orchestration system. The plugin follows a strict 4-step initialization process: config → managers → tools → hooks → plugin interface.Plugin Entry Point
The entire plugin is exported as a single async function fromsrc/index.ts:16:
OpenCode treats all exports as plugin instances and calls them. Only export the plugin function itself, never utility functions.
Four-Step Initialization
Step 1: Config Loading
File:src/plugin-config.ts
Multi-level configuration merge with automatic migration:
agents/categories: Deep merge (project overrides user)disabled_*arrays: Set union (both configs combine)- Feature configs: Project takes precedence
src/shared/migration/):
agent-names.ts: Old agent names → new (e.g.,junior→sisyphus-junior)hook-names.ts: Old hook names → newmodel-versions.ts: Old model IDs → current versionsagent-category.ts: Legacy agent configs → category system
Step 2: Manager Creation
File:src/create-managers.ts
Four core managers handle infrastructure:
| Manager | Purpose | Key Methods |
|---|---|---|
| TmuxSessionManager | Terminal pane orchestration | createSession(), spawnPane(), closePane() |
| BackgroundManager | Async agent execution | launch(), poll(), cancel() |
| SkillMcpManager | Skill-embedded MCP servers | loadSkillMcps(), getServerForSkill() |
| ConfigHandler | OpenCode config provider | 6-phase config injection |
src/plugin-handlers/):
- Provider Registration: Inject available AI providers
- Plugin Components: Register UI extensions
- Agent Registration: Create 11+ builtin agents
- Tool Registration: Expose 26 tools
- MCP Registration: Load 3 built-in + skill-embedded MCPs
- Command Registration: Register slash commands
Step 3: Tool Creation
File:src/create-tools.ts
Builds three artifacts:
src/plugin/tool-registry.ts):
- 19 factory-based tools (
createXXXTool()) - 7 direct
ToolDefinitionobjects (LSP + interactive_bash)
Step 4: Hook Creation
File:src/create-hooks.ts
46 lifecycle hooks organized in 3 tiers:
src/plugin/hooks/create-core-hooks.ts):
- Session Hooks (23): Model fallback, context window monitor, Ralph Loop, think mode
- Tool Guard Hooks (10): Comment checker, write guard, JSON recovery, hashline enhancer
- Transform Hooks (4): Context injector, thinking block validator, keyword detector
src/plugin/hooks/create-continuation-hooks.ts):
- Todo continuation enforcer
- Atlas orchestration guard
- Stop continuation guard
- Background notification
src/plugin/hooks/create-skill-hooks.ts):
- Category skill reminder
- Auto slash command
Hook Composition Pattern
Hook Composition Pattern
Every hook follows the factory pattern:Hooks can be disabled via
disabled_hooks config array.Step 5: Plugin Interface Assembly
File:src/plugin-interface.ts
Assembles 8 OpenCode hook handlers:
Hook System Deep Dive
Hook Execution Points
Hooks intercept 8 lifecycle events:| Hook Point | Fires When | Common Uses |
|---|---|---|
config | Plugin load | Agent/tool/MCP registration |
chat.message | User sends message | First message variant, session setup |
chat.params | Before API call | Effort level adjustment |
event | Session lifecycle | Created, deleted, idle, error |
tool.execute.before | Before tool runs | File guards, label truncation, rules injection |
tool.execute.after | After tool runs | Output truncation, metadata store |
messages.transform | Before API send | Context injection, thinking block validation |
system.transform | System prompt build | System directive filtering |
Example: Ralph Loop Hook
Purpose: Keeps agents working until 100% task completion. Location:src/hooks/ralph-loop/
Registration: src/plugin/hooks/create-core-hooks.ts:23
src/hooks/ralph-loop/hook.ts):
Hook Disabling
Disable hooks via config:Three-Tier MCP System
| Tier | Source | Management |
|---|---|---|
| Built-in | src/mcp/ | 3 remote HTTP: websearch (Exa/Tavily), context7, grep_app |
| Claude Code | .mcp.json | ${VAR} env expansion via claude-code-mcp-loader |
| Skill-embedded | SKILL.md YAML | SkillMcpManager (stdio + HTTP) |
src/plugin-handlers/mcps/index.ts):
Plugin State Management
Model Cache State (src/plugin-state.ts):
src/shared/first-message-variant/):
Tracks per-session first message override:
Initialization Flow Diagram
Key Design Patterns
Factory Pattern
All tools, hooks, and agents use factory functions:Barrel Exports
Each module usesindex.ts barrel exports:
Safe Hook Creation
Hooks wrap in try-catch to prevent plugin crashes:Performance Considerations
Plugin Load Timeout
OpenCode plugins have a 10-second load timeout. The initialization must complete fast:- Config parsing: JSONC with comments (~5ms)
- Manager creation: Sync object construction (~2ms)
- Tool creation: Async skill discovery (~50-200ms)
- Hook creation: Factory calls (~10ms)
- Total: < 300ms typical
Lazy Initialization
Expensive operations defer until first use:- Tmux sessions: Created on first
interactive_bashcall - Background agents: Launched on first
task(..., run_in_background=true) - Skill MCPs: Started when skill loads, killed when unloaded
- LSP server: Connects on first LSP tool call
File Organization
Plugin follows strict directory conventions:- kebab-case for all files and directories
- 200 LOC soft limit per file
- No catch-all files (
utils.ts,helpers.tsbanned) - Co-located tests (
*.test.tsnext to implementation)
Next Steps
Agents
Learn about the 11 specialized agents and their roles
Orchestration
Understand agent delegation and the Intent Gate
Categories
Explore the 8 built-in task categories and model mapping
Configuration
Full config reference with examples