Add and ship OpenCode support for one Claude Code plugin at a time. Includes core migration to a reviewable `opencode-plugin/` adapter, maintainer-facing docs, and follow-up CI/versioning setup for package publishing or skill-copy drift checks.
92
92%
Does it follow best practices?
Impact
97%
1.25xAverage score across 2 eval scenarios
Passed
No known issues
Use this when any Claude hook needs OpenCode parity analysis.
Claude hooks and OpenCode plugins are not one-to-one. Port by user-visible intent, not by event name or file path.
Claude hooks often run shell, HTTP, MCP, prompt, or agent handlers with event JSON and command exit conventions. OpenCode plugins are JavaScript/TypeScript modules that return handlers for OpenCode events.
| Cadence | Claude events | Notes |
|---|---|---|
| Session | SessionStart, SessionEnd | Runs when sessions begin, resume, or end. Useful for startup context and state. |
| Turn | UserPromptSubmit, Stop, StopFailure | Runs around a user turn. Some can block or continue behavior. |
| Tool | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch | Runs around tool calls. PreToolUse can block. |
| Permission | PermissionRequest, PermissionDenied | Tied to Claude permission flow. Semantics do not copy directly. |
| Compaction | PreCompact, PostCompact | High parity risk because timing and APIs differ. |
| Agent/task | SubagentStart, SubagentStop, TaskCreated, TaskCompleted | Port only when equivalent OpenCode behavior is available and tested. |
High-value OpenCode events for Claude plugin ports:
| OpenCode event | Use |
|---|---|
tool.execute.before | Validate, block, or mutate a tool call before execution. |
tool.execute.after | Observe successful tool calls. |
shell.env | Inject shell environment variables. |
tui.command.execute | Implement native command behavior. |
tui.prompt.append | Append content to prompt from TUI interactions. |
tui.toast.show | Show user feedback. |
session.created, session.updated, session.compacted, session.idle | Maintain session state; exact timing needs testing. |
experimental.session.compacting | Inject or replace compaction context; treat as experimental. |
permission.asked, permission.replied | Observe permission flow; test before enforcing policy. |
file.edited, file.watcher.updated | React to file changes when a Claude hook watched edits. |
message.updated, message.part.updated | React to conversation changes when needed. |
| Claude hook intent | Claude mechanism | OpenCode strategy | Parity risk |
|---|---|---|---|
| Add startup context | SessionStart stdout/JSON | Prefer shared skill content; otherwise session event or tested context hook | Medium |
| Track modes or user commands | UserPromptSubmit parses prompt | Prefer native OpenCode TUI command/event behavior | Medium |
| Block unsafe tool use | PreToolUse exit/JSON decision | tool.execute.before with tested throw/mutate behavior | High |
| React after a tool succeeds | PostToolUse | tool.execute.after or file/message/session events | Medium |
| Inject shell environment | Shell wrapper or hook | shell.env | Low/medium |
| Persist state | Hook script writes Claude config/data | OpenCode plugin state under OpenCode/XDG-safe paths | Low if tested |
| Register commands | Claude commands/hooks | OpenCode TUI command behavior or command files | Medium |
| Persist compaction context | PreCompact/PostCompact | experimental.session.compacting only with version/test caveats | High |
| Prompt expansion | UserPromptExpansion | Native command or skill activation where possible | High |
| MCP tool hook | Claude MCP hook type | Reimplement with OpenCode SDK/plugin code if possible | High |
MCP server configuration is separate from MCP hook behavior. For .mcp.json or plugin.json.mcpServers, use references/mcp-migration.md instead of treating it as hook porting.
hookSpecificOutput; OpenCode plugins do not use that command-exit contract.Before writing hook code, create a record using assets/hook-parity-record.md.
Do not claim a hook is ported until the record has an implementation strategy, tests, and parity caveats.