# How to Convert Claude Code Plugins to OpenCode Format Using the CLI

> Easily convert Claude Code plugins to OpenCode format using the compound engineering plugin CLI. This guide shows you how to transform your plugin structure with a simple command.

- Repository: [Every/compound-engineering-plugin](https://github.com/everyinc/compound-engineering-plugin)
- Tags: how-to-guide
- Published: 2026-02-16

---

**You can convert Claude Code plugins to OpenCode format by running `bun run . convert --source ./my-claude-plugin --to opencode` from the compound-engineering-plugin CLI, which parses the plugin structure and writes an OpenCode bundle with agents, skills, and configuration files.**

The `EveryInc/compound-engineering-plugin` repository provides a Bun-based command-line interface that automates the migration from Claude Code to OpenCode format. This tool handles the entire conversion pipeline—from parsing the [`.claude-plugin/plugin.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/.claude-plugin/plugin.json) structure to generating the final [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) configuration and agent Markdown files.

## Prerequisites and Installation

Before converting plugins, ensure you have the following dependencies installed:

- **Bun** runtime (the CLI is built specifically for Bun)
- Access to the `compound-engineering-plugin` repository
- A valid Claude Code plugin directory containing [`.claude-plugin/plugin.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/.claude-plugin/plugin.json)

Install the CLI dependencies:

```bash
bun install

```

## Understanding the Conversion Pipeline

The conversion process follows a synchronous five-stage pipeline defined in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts). Each stage transforms the plugin data into the target format.

### CLI Parsing and Command Definition

The entry point is [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts), which uses **citty** to define the `convert` sub-command. This module validates arguments, resolves output directories, and orchestrates the conversion flow.

Key responsibilities include:
- Parsing `--source`, `--to`, and `--output` flags
- Validating the target format against the registry in [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts)
- Building the options object passed to the converter

### Plugin Loading and Normalization

The `loadClaudePlugin` function in [`src/parsers/claude.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/parsers/claude.ts) reads the Claude Code directory structure. It parses [`plugin.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/plugin.json) and loads agents, commands, skills, hooks, and optional MCP servers into a normalized `ClaudePlugin` object.

This step ensures all plugin components are available in memory before format-specific transformation begins.

### Target Selection and Handler Resolution

[`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts) maintains a registry mapping target names to `TargetHandler` implementations. When you specify `--to opencode`, the CLI retrieves the handler containing the OpenCode-specific converter and writer functions.

Each handler implements a consistent contract for transforming and persisting plugin bundles.

### Conversion Logic

The core transformation happens in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) via `convertClaudeToOpenCode`. This function builds an `OpenCodeBundle` containing:

- **Config**: The root [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) configuration
- **Agents**: Converted to Markdown files with frontmatter (`convertAgent`)
- **Commands**: Mapped to OpenCode's command structure (`convertCommands`)
- **MCP servers**: Transformed via `convertMcp`
- **Hooks**: Generated as a plugin file (`convertHooks`)
- **Skills**: Copied unchanged to the bundle

### Writing the Output Bundle

Finally, `writeOpenCodeBundle` in [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts) persists the bundle to disk. It creates the output directory structure, backs up existing [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) files, writes the configuration, renders agents as `agents/<name>.md`, writes plugin files, and copies skill directories to `.opencode/skills/`.

## CLI Command Structure and Options

The `convert` command accepts several flags to control the conversion behavior:

```bash
bun run . convert [options]

```

### Required Flags

- `--source` (`-s`): Path to the Claude plugin directory (must contain [`.claude-plugin/plugin.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/.claude-plugin/plugin.json))
- `--to`: Target format; use `opencode` for OpenCode format (defaults to `opencode`)

### Optional Flags

- `--output` (`-o`): Directory where the OpenCode bundle will be written (defaults to current working directory)
- `--permissions`: Permission-mapping mode (`none`, `broad`, or `from-commands`). Defaults to `broad`
- `--agentMode`: Controls agent hierarchy (`primary` or `subagent`)
- `--inferTemperature`: When `true`, infers temperature values for each agent based on its description

## Practical Conversion Examples

### Basic Conversion

Convert a Claude plugin to OpenCode format in the current directory:

```bash
bun run . convert ./my-claude-plugin

```

### Explicit Target and Output Directory

Specify the target format and output location:

```bash
bun run . convert \
  --source ./my-claude-plugin \
  --to opencode \
  --output ./my-open-code-output

```

### Custom Permissions and Agent Mode

Convert with strict permission mapping and subagent configuration:

```bash
bun run . convert \
  --source ./my-claude-plugin \
  --output ./output \
  --permissions from-commands \
  --agentMode subagent \
  --inferTemperature true

```

## Output Structure and File Layout

After conversion, the output directory contains the following structure:

```

my-open-code-output/
├── opencode.json          # Root configuration file

├── agents/
│   ├── my-agent.md        # Agent definitions with frontmatter

│   └── ...
├── plugins/
│   └── converted-hooks.ts # Generated hooks plugin

└── .opencode/
    └── skills/
        └── <skill-folders> # Copied skill directories

```

The [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) file contains the main configuration, while agents are stored as individual Markdown files in the `agents/` directory with YAML frontmatter defining their properties.

## Key Source Files and Architecture

Understanding the source code helps when debugging or extending the converter:

| File | Role |
|------|------|
| [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) | CLI command definition, argument parsing, and orchestration logic |
| [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts) | Registry mapping target names to handler implementations |
| [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts) | Persists `OpenCodeBundle` to disk, handles file layout and backup logic |
| [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) | Core transformation logic from `ClaudePlugin` to `OpenCodeBundle` |
| [`src/parsers/claude.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/parsers/claude.ts) | Parses Claude Code plugin directories into normalized objects |
| [`src/utils/files.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/files.ts) | Filesystem primitives for reading and writing operations |
| [`src/utils/frontmatter.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/frontmatter.ts) | YAML frontmatter generation for agent Markdown files |

These files form a complete pipeline that transforms Claude Code plugins into OpenCode-compatible projects through a single CLI invocation.

## Summary

- The **compound-engineering-plugin** CLI provides a Bun-based tool to convert Claude Code plugins to OpenCode format using the `convert` command.
- The conversion pipeline involves five stages: CLI parsing ([`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts)), plugin loading ([`src/parsers/claude.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/parsers/claude.ts)), target selection ([`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts)), conversion ([`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts)), and writing ([`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts)).
- Use `bun run . convert --source <path> --to opencode --output <dir>` to execute the conversion with optional flags for permissions, agent modes, and temperature inference.
- The output generates an [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) configuration, Markdown agent files in `agents/`, plugin files in `plugins/`, and skill directories in `.opencode/skills/`.

## Frequently Asked Questions

### What is the difference between the `--permissions` modes when converting Claude Code plugins?

The `--permissions` flag controls how tool permissions are mapped from Claude Code to OpenCode format. The `broad` mode (default) grants wide permissions suitable for most agent operations, `none` strips all permissions for maximum security, and `from-commands` derives permissions strictly from the command definitions found in the Claude plugin. Choose `from-commands` when you need precise permission alignment with your original command specifications.

### Can I convert plugins to formats other than OpenCode using this CLI?

Yes, the CLI architecture supports multiple target formats through the registry in [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts). While `opencode` is the default and primary target, the `TargetHandler` contract allows for additional converters to be registered. Currently, the repository focuses on OpenCode conversion, but the `--to` flag accepts any registered target name, making the system extensible for future agent platforms.

### How does the CLI handle existing [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) files in the output directory?

The `writeOpenCodeBundle` function in [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts) automatically backs up existing [`opencode.json`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/opencode.json) files before writing new content. This prevents accidental data loss during repeated conversions or iterative plugin development. The backup mechanism ensures you can recover previous configurations if the conversion produces unexpected results or if you need to reference earlier settings.

### What happens to Claude Code skills during the OpenCode conversion process?

Skills are copied unchanged from the Claude plugin directory to the OpenCode bundle. The `convertClaudeToOpenCode` function in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) preserves skill directories exactly as they exist in the source, placing them in `.opencode/skills/` (or the configured layout) via `writeOpenCodeBundle`. This ensures that tool definitions, templates, and resources remain intact and functional in the target environment without requiring transformation or reformatting.