# How to Debug Conversion Failures in the Compound Engineering Plugin

> Debug conversion failures in the Compound Engineering Plugin by running the CLI with explicit flags and inspecting console warnings to pinpoint issues in target selection conversion logic or file writing.

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

---

**Run the CLI with explicit output flags and inspect console warnings to identify whether the failure occurs during target selection, conversion logic, or file writing.**

The Compound Engineering Plugin from EveryInc provides a robust pipeline for transforming Claude plugins into alternative formats like OpenCode and Codex. When you need to debug conversion failures, understanding the four-stage architecture and common failure points in the source code will help you isolate issues systematically.

## Understanding the Conversion Pipeline

The conversion process follows a strict sequence defined in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts). Each stage passes data to the next, and failures typically manifest at specific handoff points.

### Step 1: Parse the Claude Plugin

The `loadClaudePlugin` function in [`src/parsers/claude.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/parsers/claude.ts) ingests the source plugin and validates its structure. If the input JSON is malformed or missing required fields, the pipeline exits here.

### Step 2: Select the Target

The `targets` registry in [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts) maps target names (e.g., *opencode*, *codex*) to their respective conversion functions and writers. This registry determines which converter logic executes based on the `--to` flag.

### Step 3: Run the Converter

Each target invokes a specific converter, such as `convertClaudeToOpenCode` in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts). This stage handles **model normalization**, **permission mapping**, and **hook conversion**. If the converter returns `null`, the pipeline aborts before writing.

### Step 4: Write the Bundle

The writer (e.g., `writeOpenCodeBundle` in [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts)) persists the generated files to disk. Failures here typically involve file system permissions or path resolution errors in `resolveTargetOutputRoot`.

## Common Conversion Failure Points

Conversion failures cluster around four specific error conditions in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts):

| Step | Symptom | Location |
|------|---------|----------|
| Target registration | `Unknown target: …` | [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 64‑68) |
| Target implementation | `Target … is registered but not implemented yet.` | [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 70‑72) |
| Converter returns null | `Target … did not return a bundle.` | [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 91‑94) |
| Writer throws | File system stack trace | Writer modules in `src/targets/` |

## Recommended Debugging Steps

Follow this systematic approach to debug conversion failures in the Compound Engineering Plugin:

1. **Run the CLI with explicit output and extra targets**

   Execute the conversion with verbose flags to capture the full execution context:

   ```bash
   bun run src/cli.ts convert path/to/plugin --to opencode --output ./debug-out --also codex
   ```

   The CLI prints the converted directory and any warnings about unsupported tools or unmapped hook events.

2. **Check console warnings**

   The converters use `console.warn` for non‑fatal issues. In `convertClaudeToOpenCode`, look for warnings around line 262 regarding missing model aliases, or around line 60 for hook‑mapping gaps. These warnings explain why generated bundles might be incomplete.

3. **Inspect the generated bundle**

   Before the writer executes, the command holds the bundle in the `bundle` variable (see [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) lines 90‑96). Temporarily add debug logging after line 92:

   ```typescript
   console.log('DEBUG bundle keys:', Object.keys(bundle))
   ```

   This reveals the top‑level structure (`config`, `agents`, `plugins`, `skillDirs`) and confirms whether the converter produced valid output.

4. **Run the unit tests for the failing target**

   The repository includes comprehensive tests. For OpenCode conversion failures, execute:

   ```bash
   bun test tests/converter.test.ts
   ```

   This test file validates command mapping, permissions, model normalization, hook conversion, and MCP server handling. A failing assertion pinpoints the exact conversion logic that is broken.

5. **Enable source‑level debugging**

   Use Bun’s inspector to step through the conversion:

   ```bash
   bun run --inspect src/cli.ts convert path/to/plugin --to opencode
   ```

   Attach VS Code or Chrome DevTools to step into:
   - The target’s `convert` function (e.g., `convertClaudeToOpenCode`)
   - `applyPermissions` logic (lines 294‑360) for permission‑related failures
   - `normalizeModel` (lines 260‑275) for unexpected model IDs

6. **Validate the writer’s path resolution**

   The writer modules compute output paths using `resolveTargetOutputRoot` in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 143‑149). Ensure that the resolved directory exists and that the process has write permissions.

7. **Re‑run with a minimal fixture**

   Isolate plugin‑specific issues by converting the sample fixture:

   ```bash
   bun run src/cli.ts convert tests/fixtures/sample-plugin --to opencode
   ```

   If this succeeds, the failure stems from the source plugin’s structure rather than the conversion engine.

8. **Check for null bundle returns**

   If you encounter `Target … did not return a bundle`, the converter returned `null`. This occurs when all commands are disabled (see early returns in `convertCommands` such as `if (command.disableModelInvocation) continue`). Verify that your source plugin contains enabled commands.

## Adding Debug Logging to the Conversion Command

For persistent issues, instrument [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) to expose intermediate state:

```typescript
// Inside src/commands/convert.ts after the primary bundle is produced
if (!bundle) {
  throw new Error(`Target ${targetName} did not return a bundle.`)
}
console.log('DEBUG bundle keys:', Object.keys(bundle))
await target.write(primaryOutputRoot, bundle)

```

This prints the top‑level keys so you can verify that a non‑empty bundle was produced before the writer touches the filesystem.

## Key Files for Debugging Conversion Failures

| File | Role |
|------|------|
| [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) | CLI entry point that selects the target, runs the converter, and writes the bundle |
| [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts) | Registry of all conversion targets and their implementation flags |
| [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) | Main OpenCode converter; contains model normalization, temperature inference, and permission handling |
| [`src/converters/claude-to-codex.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-codex.ts) | Target‑specific conversion logic for Codex |
| [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts) | Writer that persists generated files for OpenCode |
| [`src/targets/codex.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/codex.ts) | Writer that persists generated files for Codex |
| [`src/utils/resolve-home.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/resolve-home.ts) | Resolves `~` in user‑provided paths (used for `--codex-home`, `--pi-home`) |
| [`src/utils/files.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/files.ts) | Helpers for file‑system operations (`ensureDir`, `writeJson`, etc.) |
| [`tests/converter.test.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/tests/converter.test.ts) | Unit test that validates the OpenCode conversion pipeline; a quick sanity check for debugging |

## Summary

- The conversion pipeline in **EveryInc/compound-engineering-plugin** consists of four stages: parsing, target selection, conversion, and writing.
- Most failures occur at specific handoff points in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts), identifiable by error messages like `Unknown target` or `did not return a bundle`.
- To **debug conversion failures**, run the CLI with explicit flags, check `console.warn` output for non‑fatal issues, inspect the bundle structure before writing, and run target‑specific unit tests.
- Enable source‑level debugging with `bun run --inspect` to step through converters like `convertClaudeToOpenCode` and verify logic in `applyPermissions` or `normalizeModel`.
- Use the sample fixture at `tests/fixtures/sample-plugin` to isolate plugin‑specific issues from engine bugs.

## Frequently Asked Questions

### Why does the conversion fail with "Unknown target"?

This error originates in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 64‑68) when the target name provided via `--to` does not exist in the `targets` registry exported from [`src/targets/index.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/index.ts). Verify that you are using a supported target name such as *opencode* or *codex*, and check that the target is properly registered in the index file.

### What does "Target did not return a bundle" mean?

This message appears in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) (lines 91‑94) when the converter function returns `null` instead of a bundle object. This typically happens when all commands in the source plugin are disabled (e.g., `command.disableModelInvocation` is true) or when the converter encounters an early return condition. Check the source plugin for enabled commands and review the converter logic for early exits.

### How can I see the intermediate bundle before it is written to disk?

Insert a temporary debug log in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) immediately after the bundle is generated (around line 92). Add `console.log(JSON.stringify(bundle, null, 2))` to print the full bundle structure, or use `console.log('DEBUG bundle keys:', Object.keys(bundle))` to verify the top‑level keys (`config`, `agents`, `plugins`, `skillDirs`). Remove the log after debugging to avoid cluttering production output.

### Which test file should I run to verify the OpenCode converter?

Run `bun test tests/converter.test.ts` to execute the unit tests for the OpenCode conversion pipeline. This test file validates command mapping, permissions, model normalization, hook conversion, and MCP server handling. If a specific conversion feature is failing, the test output will point to the exact assertion that failed, helping you locate the bug in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) or related modules.