How to Debug Conversion Failures in the Compound Engineering Plugin
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. 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 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 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. 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) 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:
| Step | Symptom | Location |
|---|---|---|
| Target registration | Unknown target: … |
src/commands/convert.ts (lines 64‑68) |
| Target implementation | Target … is registered but not implemented yet. |
src/commands/convert.ts (lines 70‑72) |
| Converter returns null | Target … did not return a bundle. |
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:
-
Run the CLI with explicit output and extra targets
Execute the conversion with verbose flags to capture the full execution context:
bun run src/cli.ts convert path/to/plugin --to opencode --output ./debug-out --also codexThe CLI prints the converted directory and any warnings about unsupported tools or unmapped hook events.
-
Check console warnings
The converters use
console.warnfor non‑fatal issues. InconvertClaudeToOpenCode, 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. -
Inspect the generated bundle
Before the writer executes, the command holds the bundle in the
bundlevariable (seesrc/commands/convert.tslines 90‑96). Temporarily add debug logging after line 92: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. -
Run the unit tests for the failing target
The repository includes comprehensive tests. For OpenCode conversion failures, execute:
bun test tests/converter.test.tsThis 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.
-
Enable source‑level debugging
Use Bun’s inspector to step through the conversion:
bun run --inspect src/cli.ts convert path/to/plugin --to opencodeAttach VS Code or Chrome DevTools to step into:
- The target’s
convertfunction (e.g.,convertClaudeToOpenCode) applyPermissionslogic (lines 294‑360) for permission‑related failuresnormalizeModel(lines 260‑275) for unexpected model IDs
- The target’s
-
Validate the writer’s path resolution
The writer modules compute output paths using
resolveTargetOutputRootinsrc/commands/convert.ts(lines 143‑149). Ensure that the resolved directory exists and that the process has write permissions. -
Re‑run with a minimal fixture
Isolate plugin‑specific issues by converting the sample fixture:
bun run src/cli.ts convert tests/fixtures/sample-plugin --to opencodeIf this succeeds, the failure stems from the source plugin’s structure rather than the conversion engine.
-
Check for null bundle returns
If you encounter
Target … did not return a bundle, the converter returnednull. This occurs when all commands are disabled (see early returns inconvertCommandssuch asif (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 to expose intermediate state:
// 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 |
CLI entry point that selects the target, runs the converter, and writes the bundle |
src/targets/index.ts |
Registry of all conversion targets and their implementation flags |
src/converters/claude-to-opencode.ts |
Main OpenCode converter; contains model normalization, temperature inference, and permission handling |
src/converters/claude-to-codex.ts |
Target‑specific conversion logic for Codex |
src/targets/opencode.ts |
Writer that persists generated files for OpenCode |
src/targets/codex.ts |
Writer that persists generated files for Codex |
src/utils/resolve-home.ts |
Resolves ~ in user‑provided paths (used for --codex-home, --pi-home) |
src/utils/files.ts |
Helpers for file‑system operations (ensureDir, writeJson, etc.) |
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, identifiable by error messages likeUnknown targetordid not return a bundle. - To debug conversion failures, run the CLI with explicit flags, check
console.warnoutput for non‑fatal issues, inspect the bundle structure before writing, and run target‑specific unit tests. - Enable source‑level debugging with
bun run --inspectto step through converters likeconvertClaudeToOpenCodeand verify logic inapplyPermissionsornormalizeModel. - Use the sample fixture at
tests/fixtures/sample-pluginto 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 (lines 64‑68) when the target name provided via --to does not exist in the targets registry exported from 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 (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 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 or related modules.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →