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
Create reviewable local OpenCode support for one Claude Code plugin. Preserve shared prompt assets, port hooks by user-visible intent, and stop at working local files plus tests.
ci-setup follow-up for versioning, publishing, and drift-check automation.opencode-plugin/ as the neutral generated package root. Use .opencode/ only as an explicitly documented local dogfooding shim.opencode-plugin/package.json; OpenCode plugin packages are not assumed to install MCP servers.Reference only when needed: placement and coverage (placement policy, coverage audit), skills and commands (skill sharing, commands and agents), package layout (OpenCode package layout), MCP (MCP migration), hooks (hook porting), tests (testing and parity), and maintainer wording (maintainer explanations). Templates live in assets/.
Use these assets when producing migration records and review tables: asset inventory table, coverage audit table, discovery checklist, hook parity record, MCP migration record, MCP test checklist, OpenCode MCP config snippet, and test matrix.
Run when available:
python3 scripts/inspect_repo.py <repo> --format markdownUse the output as a starting inventory, then verify manually. If the task names both a pinned upstream commit and an offline fixture path, use the pinned source when available, but prefer the named repo-relative fixture when network or clone access fails. Never make a transient /tmp clone the only fallback. Record the source used in OPENCODE_SUPPORT.md.
Inventory at least:
.claude-plugin/plugin.json and nested manifests such as plugin/.claude-plugin/plugin.json as separate rows..claude-plugin/marketplace.json and other marketplace metadata.skills/, .claude/skills/, commands/, agents/, hooks, scripts, package metadata, MCP files, worker/service entrypoints, and existing OpenCode integration code.${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, user config/env placeholders, stdin/stdout/exit contracts.Use labels full, partial, missing, or not-applicable. Do not implement with an unaddressed missing row. If a .claude-plugin/ directory lacks plugin.json, explicitly say so instead of implying it was inspected.
For each asset choose: shared, wrapped, rewritten, or Claude-only. Keep shared skill sources in place when possible; use .agents/skills/ for new shared skills; use .opencode/commands/ or .opencode/agents/ only for OpenCode-specific wrappers; copy to opencode-plugin/skills/ only for distribution/runtime need and test equality or document intentional divergence. Keep Claude metadata as evidence and do not generate new .claude/ files unless explicitly asked.
Run when skills exist:
python3 scripts/validate_skills.py <repo> --format markdownFix or document frontmatter issues before packaging. Tests must prove every source and package-local SKILL.md has parseable name and description. If fixture/helper scripts are intentionally absent, say so in the migration note.
opencode-plugin/Create the smallest package that supports the discovered behavior:
opencode-plugin/
package.json
src/plugin.ts # or plugin.js for JS-only repos
src/state.ts # only if state is needed
skills/<name>/SKILL.md
tests/opencode-plugin.test.tsopencode-plugin/package.json must be ESM, set main/exports to an existing entrypoint, include opencode and opencode-plugin keywords, and restrict files to runtime assets such as src/, plugin.js, and skills/. Exclude .claude/, .opencode/, tests, local config, and unrelated agent metadata.
Run after package edits:
python3 scripts/validate_opencode_package.py <repo> --format markdownWhen .mcp.json or plugin.json.mcpServers exists, create a per-server record before writing config.
Convert Claude MCP config to opencode.jsonc / opencode.json:
command: "cmd" plus args: [...] becomes command: ["cmd", ...args].env becomes environment.type: "local"; URL servers are type: "remote".${CLAUDE_PLUGIN_ROOT} only after deciding where equivalent files live.Include an actionable config snippet or patch and tests/manual checks (opencode mcp list when available).
For every Claude hook, create a parity record before coding. Include event/matcher/command, fields used, output/failure behavior, intended user-visible behavior, OpenCode mapping, reuse-vs-rewrite decision, test evidence, and caveats.
Common mappings:
PreToolUse → tool.execute.before when blocking/mutation is needed; test semantics.PostToolUse → tool.execute.after.SessionStart → session lifecycle hook plus skill/context strategy; timing differs.UserPromptSubmit → native TUI command or prompt handling where available; avoid Claude stdin JSON contracts.PreCompact/PostCompact → experimental compaction APIs only with tested-version caveats.Use OpenCode/XDG-safe state paths, not Claude config/cache paths.
Minimum evidence:
OPENCODE_SUPPORT.md records source URL/commit or fixture path, inventories surfaces with labels, includes hook parity and MCP decisions, compares existing OpenCode integrations if present, lists verification commands, and states honest caveats.Finish when the maintainer has:
missing rows.opencode-plugin/ adapter package plus optional documented .opencode/ shim.Then offer next steps:
docs to polish README/OPENCODE_SUPPORT wording for maintainers.ci-setup to inspect existing Claude plugin versioning and set up package publishing or skill-copy drift checks. Do not add CI files without user approval.