This document outlines the differences between Claude Code plugins and OpenCode plugins, and provides strategies for integration and compatibility.
Key Finding: Claude Code plugins and OpenCode plugins are fundamentally different architectures that cannot be directly converted but can be bridged through strategic approaches.
Type: Declarative Configuration Bundles
Structure:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Metadata
├── commands/ # Markdown files with frontmatter
├── agents/ # Markdown files with frontmatter
├── skills/ # Subdirectories with SKILL.md
├── hooks/
│ └── hooks.json # Hook configurations
└── .mcp.json # MCP server configs
Key Characteristics:
- Format: Markdown files with YAML frontmatter + JSON configs
- Distribution: Git repositories via marketplace system
- Installation:
/plugin install plugin-name@marketplace - Execution: Declarative - Claude Code interprets the configs
- Components: Commands, agents, skills, hooks, MCP servers
Example Agent (agents/python_pro.md):
---
description: Master Python 3.12+ development
mode: subagent
temperature: 0.1
tools:
write: true
edit: true
bash: true
---
You are a Python expert...Type: Executable JavaScript/TypeScript Modules
Structure:
.opencode/plugin/
└── my-plugin.ts # Single executable module
Key Characteristics:
- Format: JavaScript/TypeScript code
- Distribution: File copying or npm packages
- Installation: Copy to
.opencode/plugin/or~/.config/opencode/plugin/ - Execution: Imperative - Code runs in Node/Bun runtime
- Components: Event hooks, custom tools, lifecycle methods
Example Plugin:
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ app, client, $ }) => {
return {
// Event hook
event: async ({ event }) => {
console.log("Event:", event.type)
},
// Tool execution hooks
tool: {
execute: {
before: async (input, output) => {
// Intercept tool calls
},
after: async (input, output) => {
// Post-process results
}
}
}
}
}-
Event Hooks
event: Triggered on lifecycle events (e.g.,session.idle)
-
Tool Execution Hooks
tool.execute.before: Pre-execution validation/blockingtool.execute.after: Post-execution processing
-
Lifecycle Hooks (from SDK)
onPreMessage: Before message processingonPostMessage: After message completiononContextPrime: Context injectiononPreToolCall: Before any tool callonPostToolCall: After tool completion
-
Custom Tool Registration
tool: Register new tools with Zod schemas
Plugins receive:
project: Current project informationclient: OpenCode SDK client for AI interactions$: Bun's shell API for command executiondirectory: Current working directoryworktree: Git worktree pathapp: Application context
Commands are Markdown files in .opencode/command/:
---
description: "Run tests with coverage"
---
Run the full test suite with coverage:
`!npm test -- --coverage`Note: OpenCode commands use the same markdown format as Claude Code!
| Aspect | Claude Code Plugins | OpenCode Plugins |
|---|---|---|
| Architecture | Declarative bundles | Executable code |
| Language | Markdown + YAML + JSON | JavaScript/TypeScript |
| Execution | Interpreted by Claude Code | Runs in Node/Bun runtime |
| Agents | Markdown files with frontmatter | Not directly supported* |
| Commands | Markdown with frontmatter | Markdown with frontmatter ✓ |
| Skills | Markdown files | Not directly supported* |
| Hooks | JSON configuration | TypeScript event handlers |
| Distribution | Marketplace + Git | File copy / npm |
| Custom Tools | Not supported* | Full Zod schema support ✓ |
* Can be implemented via plugin code
What Works: Commands can be directly migrated since both systems use markdown with frontmatter.
Implementation:
- Use CodeFlow CLI to convert agents/commands/skills to OpenCode markdown format
- Place converted commands in
.opencode/command/ - Commands work immediately in OpenCode
Limitations:
- Agents and skills don't have direct OpenCode equivalents
- Hooks require code rewrite
- MCP servers need separate configuration
Code Example:
# Convert Claude Code commands to OpenCode format
codeflow convert commands --output .opencode/command/
# Commands are now available in OpenCodeConcept: Generate OpenCode plugin code that wraps Claude Code plugin components.
Implementation:
- Parse Claude Code
plugin.jsonand component files - Generate TypeScript plugin that:
- Registers commands programmatically
- Implements hooks as event handlers
- Creates custom tools for agents/skills
Example Generated Code:
export const ClaudePluginWrapper: Plugin = async ({ client, $ }) => {
return {
// Convert Claude hooks to OpenCode events
tool: {
execute: {
before: async (input, output) => {
// Execute Claude Code hook.json logic
}
}
},
// Register agents as custom tools
tool: {
name: "python_pro",
description: "Master Python 3.12+ development",
args: z.object({
task: z.string()
}),
execute: async ({ task }) => {
// Send task to client with agent prompt
return await client.chat({
prompt: agentPrompt,
temperature: 0.1
})
}
}
}
}Advantages:
- One-time conversion process
- Maintains plugin structure
- Enables full OpenCode capabilities
Challenges:
- Complex code generation
- Not all Claude features map to OpenCode
- Requires runtime dependency management
Concept: Maintain both Claude Code and OpenCode versions of the same plugin.
Implementation:
- Author plugin in OpenCode format (TypeScript)
- Extract declarative components (commands, agents) as markdown
- Package both formats:
my-plugin/ ├── .claude-plugin/ # Claude Code format │ └── plugin.json ├── commands/ # Shared markdown ├── agents/ # Shared markdown └── opencode/ └── plugin.ts # OpenCode executable
Advantages:
- Best of both worlds
- Single source repository
- Commands/agents shared as markdown
Challenges:
- Double maintenance burden
- Hooks must be maintained separately
- No automatic sync
Concept: Create an OpenCode plugin that enables Claude Code plugin loading.
Implementation:
Phase 1: Claude Plugin Loader
// .opencode/plugin/claude-plugin-loader.ts
export const ClaudePluginLoader: Plugin = async ({ directory, client }) => {
const pluginPath = path.join(directory, '.claude-plugin/plugin.json')
const pluginConfig = await loadClaudePlugin(pluginPath)
return {
event: async ({ event }) => {
// Execute Claude Code hooks based on events
await executeClaudeHooks(pluginConfig.hooks, event)
},
// Register agents as tools
...generateAgentTools(pluginConfig)
}
}Phase 2: Extend CodeFlow CLI
Add new command to CodeFlow CLI:
codeflow generate opencode-plugin --input ./my-claude-plugin --output ./my-opencode-pluginThis would:
- Parse Claude Code plugin structure
- Generate OpenCode plugin wrapper TypeScript
- Copy/convert compatible components (commands)
- Create tool registrations for agents
- Convert hooks to event handlers
Advantages:
- Automated conversion
- Leverages existing CodeFlow CLI infrastructure
- Extensible for future features
- Community can contribute converters
- Analyze Claude Code plugin architecture
- Analyze OpenCode plugin architecture
- Document differences and compatibility matrix
- Identify integration strategies
Goal: Enable Claude Code commands to work in OpenCode immediately
Tasks:
- Update CodeFlow CLI to support command-only conversion mode
- Add
.opencode/command/as output target - Create migration guide for commands
- Test with real-world command examples
Timeline: 1-2 days
Goal: Auto-generate OpenCode plugins from Claude Code plugins
Tasks:
- Create new
PluginConverterclass in CodeFlow CLI - Implement Claude Code plugin.json parser
- Generate TypeScript plugin wrapper code
- Handle agent-to-tool conversion
- Handle hook-to-event conversion
- Create template system for generated code
Files to Create:
src/converters/plugin-converter.tssrc/generators/opencode-plugin-generator.tssrc/types/plugin-types.tstemplates/opencode-plugin.template.ts
Timeline: 5-7 days
Tasks:
- Test with example Claude Code plugins
- Create comprehensive migration guide
- Add integration tests
- Document limitations and workarounds
- Create example plugins demonstrating both formats
Timeline: 2-3 days
Tasks:
- Publish updated CodeFlow CLI
- Release migration guide
- Create video tutorial
- Engage with Claude Code and OpenCode communities
| Claude Code Feature | OpenCode Equivalent | Conversion Difficulty | Notes |
|---|---|---|---|
| Commands | Commands | ✅ Easy | Same format! |
| Agents (as markdown) | Custom tools | Requires tool wrapper | |
| Skills (as markdown) | Custom tools | Similar to agents | |
| Hooks (JSON config) | Event handlers (TS) | 🔴 Hard | Requires code generation |
| MCP Servers | MCP integration | OpenCode supports MCP | |
| Plugin metadata | Package.json | ✅ Easy | Standard mapping |
| Marketplace | NPM / Git | Different distribution |
Structure:
security-plugin/
├── .claude-plugin/
│ └── plugin.json
├── commands/
│ └── security-scan.md
├── agents/
│ └── security-expert.md
└── hooks/
└── hooks.json
plugin.json:
{
"name": "security-plugin",
"description": "Security scanning and guidance",
"version": "1.0.0",
"author": { "name": "Security Team" }
}commands/security-scan.md:
---
description: "Run security vulnerability scan"
---
Perform a comprehensive security scan of the codebase:
1. Check for known vulnerabilities
2. Scan dependencies
3. Review code for common security issuesagents/security-expert.md:
---
description: Security analysis and remediation expert
mode: subagent
temperature: 0.2
tools:
read: true
grep: true
---
You are a security expert specialized in identifying and fixing vulnerabilities...hooks/hooks.json:
{
"PostToolUse": {
"command": "./scripts/log-tool-use.sh",
"description": "Log all tool usage for security audit"
}
}Structure:
security-plugin-opencode/
├── .opencode/
│ ├── command/
│ │ └── security-scan.md
│ └── plugin/
│ └── security-plugin.ts
└── package.json
Generated .opencode/plugin/security-plugin.ts:
import type { Plugin } from "@opencode-ai/plugin"
import { z } from "zod"
export const SecurityPlugin: Plugin = async ({ client, $, directory }) => {
// Security Expert Agent as Custom Tool
const securityExpertTool = {
name: "security_expert",
description: "Security analysis and remediation expert",
args: z.object({
task: z.string().describe("Security task to perform"),
context: z.string().optional().describe("Additional context")
}),
execute: async ({ task, context }) => {
const prompt = `You are a security expert specialized in identifying and fixing vulnerabilities...
Task: ${task}
${context ? `Context: ${context}` : ''}
`
const response = await client.chat({
messages: [{ role: "user", content: prompt }],
temperature: 0.2,
tools: {
read: true,
grep: true
}
})
return response
}
}
return {
// Register security expert as tool
tool: securityExpertTool,
// Convert PostToolUse hook to event handler
tool: {
execute: {
after: async (input, output) => {
// Log tool usage for security audit
await $`./scripts/log-tool-use.sh ${input.tool} ${JSON.stringify(output)}`
}
}
}
}
}Commands copied directly:
.opencode/command/security-scan.md (same content as Claude version)
Direct Conversion: ❌ Not possible due to architectural differences
Hybrid Approach: ✅ Feasible with strategic conversion
Best Path Forward:
- ✅ Immediate: Use commands directly (already compatible)
⚠️ Short-term: Manual conversion for simple plugins- ✅ Long-term: Extend CodeFlow CLI with plugin generator
- Commands are compatible - Both systems use markdown with frontmatter
- Agents/Skills need wrappers - Convert to custom tools in OpenCode
- Hooks require code generation - JSON configs → TypeScript event handlers
- CodeFlow CLI is the right place - Extends existing conversion infrastructure
- Not all features map 1:1 - Some manual adaptation required
- Update CodeFlow CLI with plugin conversion support
- Create example conversions for common use cases
- Document edge cases and limitations
- Engage communities for feedback and contributions
Document Version: 1.0 Last Updated: 2025-11-17 Author: Claude (via CodeFlow CLI Research)