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 before implementing a migration, and again when Claude Code or OpenCode plugin docs change.
The goal is not to force every Claude plugin feature into OpenCode. The goal is to classify every discovered Claude surface so maintainers know what is shared, wrapped, rewritten, manually configured, or Claude-only.
For each documented or discovered Claude plugin feature, record:
| Column | Meaning |
|---|---|
| Claude feature/source | Manifest field, root path, config file, or runtime behavior. |
| Claude behavior | What Claude Code does for users. |
| OpenCode equivalent | Native OpenCode feature, config key, plugin event, or none. |
| Support status | full, partial, missing, or not-applicable. |
| Migration output | File, config snippet, test, or documentation note to produce. |
| Verification | Command, automated test, or manual check. |
| Caveat | Timing, packaging, secret handling, or user-visible difference. |
Use assets/coverage-audit-table.md as the starting checklist.
full: The skill has explicit guidance and a deterministic verification path.partial: The skill has a safe migration stance, but parity depends on project-specific code or manual OpenCode config.missing: The skill does not yet tell the agent what to do. Add guidance before implementing.not-applicable: OpenCode has no equivalent or the Claude feature is distribution-only metadata. Document why.Manifest and metadata:
.claude-plugin/plugin.json.claude-plugin/marketplace.jsonplugin/.claude-plugin/plugin.json.claude-plugin/ directory that lacks plugin.json (record the directory and files explicitly)name, version, description, author, homepage, repository, license, keywordsenabledPluginsComponent fields and root paths:
skills and skills/*/SKILL.mdcommands and commands/*.mdagents and agents/*.mdhooks and hooks/hooks.jsonmcpServers, .mcp.json, and inline MCP configoutputStyles and output-styles/themes and themes/lspServers and .lsp.jsonmonitors and monitors/monitors.jsondependenciessettings.jsonbin/userConfigchannelsRuntime substitutions and storage:
${CLAUDE_PLUGIN_ROOT}${CLAUDE_PLUGIN_DATA}${user_config.KEY}CLAUDE_PLUGIN_OPTION_*bin/ PATH behavior| Claude surface | OpenCode stance | Status | Notes |
|---|---|---|---|
Root .claude-plugin/plugin.json | Input-only Claude manifest; map only safe metadata to opencode-plugin/package.json. | full | Keep distinct from nested plugin manifests in reports. |
Nested plugin/.claude-plugin/plugin.json | Input-only Claude manifest for plugin assets under plugin/. | full | Inventory separately from root .claude-plugin/; do not collapse it into marketplace metadata. |
| Skills | Prefer shared .agents/skills/; package-local copy only when needed for npm distribution. | full | Verify with opencode debug skill. |
| Commands | Prefer shared command text or .opencode/commands/ wrapper with frontmatter when OpenCode-specific. | full | Verify in / palette. |
| Agents | Prefer shared agent prompt or .opencode/agents/ wrapper with frontmatter when OpenCode-specific. | full | Verify in @ picker. |
| Hooks | Rewrite by user-visible intent as OpenCode plugin event handlers. | full | Requires per-hook parity record and tests. |
| MCP servers | Convert to OpenCode config mcp, separate from the npm plugin package. | full | Verify with opencode mcp list; OAuth may need opencode mcp auth <name>. |
| Metadata | Map safe package metadata to opencode-plugin/package.json; keep Claude plugin metadata input-only. | full | Do not generate .claude-plugin/. |
outputStyles | No direct migration target in the current OpenCode docs used by this skill. | not-applicable | Document as Claude-only unless OpenCode docs add parity. |
themes | OpenCode has themes/config, but Claude plugin theme packaging is not 1:1. | partial | Treat as manual OpenCode config unless a tested mapping exists. |
lspServers | OpenCode exposes LSP events, but Claude .lsp.json packaging has no proven 1:1 config mapping here. | partial | Document as manual/rewrite pending docs-backed mapping. |
monitors | No direct OpenCode monitor primitive found in current docs. | partial | Rewrite as plugin/session/file/message behavior only when intent is clear and tested. |
bin/ | OpenCode does not document Claude-style automatic plugin bin/ PATH behavior. | partial | Use explicit package scripts, absolute/relative command paths, or bundled imports. |
settings.json | Claude plugin defaults are input-only unless a known OpenCode config equivalent exists. | partial | Map only documented equivalents; otherwise note as Claude-only. |
userConfig | No plugin-enable prompt equivalent found in current OpenCode docs. | partial | Prefer documented env vars, config placeholders, or README setup; never inline secrets. |
channels | Tied to Claude plugin MCP servers and message injection. | partial | Migrate MCP separately; reimplement channel behavior only with tested OpenCode plugin code. |
dependencies | Map runtime package dependencies to opencode-plugin/package.json. | partial | Do not assume Claude plugin dependency semantics or enable-time prompts. |
${CLAUDE_PLUGIN_ROOT} | Replace only after deciding where equivalent files live. | full | Often opencode-plugin/ or an existing repo path. |
${CLAUDE_PLUGIN_DATA} | Use OpenCode/XDG-safe state or documented env var. | full | Never point OpenCode state at Claude plugin data. |
${user_config.KEY} | Replace with env/config placeholders or documented setup. | partial | Sensitive values need user-managed secret storage. |
CLAUDE_PLUGIN_OPTION_* | No direct OpenCode equivalent assumed. | partial | Use explicit env vars if needed. |
Before writing migration files, produce a short coverage table for discovered surfaces. Do not leave a feature implicit because it is unsupported. Unsupported features need an explicit not-applicable or partial row with a caveat.
If the task provides an offline fixture path, document whether the pinned upstream clone or the fixture path was used. Tests that validate source equality should prefer the fixture path as the deterministic fallback before using any transient clone directory.
If the audit finds a missing row, update this skill's guidance before continuing with implementation.
scripts/validate_skills.py <repo> --format markdown when skills are present.scripts/validate_opencode_package.py <repo> --format markdown after package files exist.opencode mcp list when available.