# Tool Name Conversion in the Compound Engineering Plugin: Mapping Claude Tools to OpenCode, Codex, and Pi

> Discover how the Compound Engineering Plugin converts Claude tool names to OpenCode Codex and Pi formats using a three-step pipeline and regex transformations.

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

---

**The Compound Engineering Plugin implements a three-step conversion pipeline that normalizes Claude-Code tool identifiers through a canonical mapping table, then generates target-specific definitions for OpenCode permissions, Codex documentation blocks, and Pi-compatible syntax via regex transformations.**

The EveryInc/compound-engineering-plugin enables cross-platform compatibility for Claude-Code plugins by converting tool declarations into formats recognized by OpenCode, Codex, and Pi. Understanding this tool name conversion process is essential for developers maintaining multi-platform agent configurations and debugging cross-platform tool behavior.

## The Three-Step Tool Name Conversion Pipeline

The plugin processes tool name conversion through a standardized pipeline implemented across three target-specific converters. Each stage ensures that Claude-Code tool references maintain semantic meaning while conforming to platform-specific naming conventions and permission structures.

## Step 1: Normalizing Claude Tool Identifiers

The conversion begins in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) with the `TOOL_MAP` constant (lines 24‑39). This record maps raw Claude tool strings to canonical lower-case names that all target platforms recognize.

```typescript
// src/converters/claude-to-opencode.ts
const TOOL_MAP: Record<string, string> = {
  bash: "bash",
  read: "read",
  write: "write",
  edit: "edit",
  grep: "grep",
  glob: "glob",
  list: "list",
  webfetch: "webfetch",
  skill: "skill",
  patch: "patch",
  task: "task",
  question: "question",
  todowrite: "todowrite",
  todoread: "todoread",
}

```

Each Claude identifier is lower-cased and mapped to the canonical name. If a tool is not present in this map, the conversion pipeline treats it as unsupported for cross-platform use.

## Step 2: Generating Target-Specific Tool Definitions

After normalization, the pipeline branches into platform-specific generators that create the appropriate configuration structures for each target.

### OpenCode Tool Mapping

For OpenCode targets, the `applyPermissions` function (located in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts)) constructs a `tools` record and permission matrix. The normalized names from `TOOL_MAP` populate both the `config.tools` flag and the permission clauses (`allow`/`deny`), ensuring the OpenCode runtime recognizes which Claude tools correspond to which OpenCode capabilities.

### Codex Tool Mapping

Codex conversion relies on static documentation blocks rather than runtime configuration. The `ensureCodexAgentsFile` function in [`src/utils/codex-agents.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/codex-agents.ts) (lines 12‑23) generates a managed [`AGENTS.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/AGENTS.md) block that documents the semantic mapping between Claude tools and Codex behaviors.

```typescript
// src/utils/codex-agents.ts (excerpt)
Tool mapping:
- Read: use shell reads (cat/sed) or rg
- Write: create files via shell redirection or apply_patch
- Edit/MultiEdit: use apply_patch
- Bash: use shell_command
- Grep: use rg (fallback: grep)
- Glob: use rg --files or find
- LS: use ls via shell_command
- WebFetch/WebSearch: use curl or Context7 for library docs
- AskUserQuestion/Question: ask the user in chat
- Task/Subagent/Parallel: run sequentially in main thread; use multi_tool_use.parallel for tool calls
- TodoWrite/TodoRead: use file‑based todos in todos/ with file‑todos skill
- Skill: open the referenced SKILL.md and follow it

```

This block enables Codex agents to interpret Claude tool references correctly without native tool support.

### Pi Tool Mapping

For Pi targets, the `transformContentForPi` function in [`src/converters/claude-to-pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-pi.ts) (lines 95‑108) performs regex-based replacements on the command or agent body. This transforms Claude-specific tokens into Pi-compatible syntax.

```typescript
// src/converters/claude-to-pi.ts (excerpt)
result = result.replace(/\bAskUserQuestion\b/g, "ask_user_question")
result = result.replace(/\bTodoWrite\b/g, "file-based todos (todos/ + /skill:file-todos)")
result = result.replace(/\bTodoRead\b/g, "file-based todos (todos/ + /skill:file-todos)")

```

These replacements ensure that Pi runners encounter valid syntax when executing converted Claude plugins.

## Step 3: Embedding Mappings in Conversion Output

The final stage inserts normalized tool names into platform-specific output structures. Each target converter—[`claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/claude-to-opencode.ts), [`claude-to-codex.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/claude-to-codex.ts), and [`claude-to-pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/claude-to-pi.ts)—uses the normalized name when building the final bundle.

- **OpenCode**: Normalized names populate `config.tools` and permission sections consumed by the OpenCode runtime.
- **Codex**: The [`AGENTS.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/AGENTS.md) block lives alongside other Codex assets, providing runtime guidance for tool interpretation.
- **Pi**: Transformed bodies with Pi-specific placeholders are written into Pi skill files, with compatibility notes appended when MCP references are detected.

## Key Implementation Files

The tool name conversion logic is distributed across the following source files in the EveryInc/compound-engineering-plugin repository:

| Platform | File | Purpose |
|----------|------|---------|
| **OpenCode** | [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) | Contains the `TOOL_MAP` constant and `applyPermissions` function for generating OpenCode tool configurations. |
| **Codex** | [`src/utils/codex-agents.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/codex-agents.ts) | Manages the [`AGENTS.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/AGENTS.md) block that documents Claude-to-Codex tool semantics (lines 12‑23). |
| **Pi** | [`src/converters/claude-to-pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-pi.ts) | Implements `transformContentForPi` for regex-based body transformations (lines 95‑108). |
| **Shared** | [`src/utils/frontmatter.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/frontmatter.ts) | Formats converted front-matter that includes normalized tool entries across all targets. |

## Summary

- The Compound Engineering Plugin uses a **three-step pipeline** to convert Claude-Code tool names for cross-platform compatibility.
- **Normalization** occurs via the `TOOL_MAP` in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts), mapping raw identifiers to canonical lower-case names.
- **OpenCode** targets receive tool definitions through the `applyPermissions` function, which builds runtime-compatible permission matrices.
- **Codex** targets rely on static documentation in [`AGENTS.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/AGENTS.md) (managed by [`src/utils/codex-agents.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/utils/codex-agents.ts)) to interpret Claude tool semantics.
- **Pi** targets undergo regex-based transformation via `transformContentForPi` in [`src/converters/claude-to-pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-pi.ts), replacing Claude-specific tokens with Pi-compatible syntax.

## Frequently Asked Questions

### How does the plugin handle unsupported Claude tools during conversion?

If a Claude tool identifier is not present in the `TOOL_MAP` constant located in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts), the conversion pipeline treats it as unsupported for cross-platform use. The normalization step returns `null` for unknown tools, and subsequent target-specific generators skip or warn on these entries to prevent invalid configurations in OpenCode, Codex, or Pi outputs.

### What is the difference between OpenCode and Codex tool mapping approaches?

OpenCode mapping is **dynamic and configuration-based**: the `applyPermissions` function generates a `tools` record and permission matrix that the OpenCode runtime consumes directly. Codex mapping is **static and documentation-based**: the plugin writes a managed block to [`AGENTS.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/AGENTS.md) that explains semantic equivalents (e.g., mapping Claude's `Read` to Codex's shell reads or `rg`), which Codex agents reference during execution rather than formal configuration files.

### Why does the Pi converter use regex replacements instead of a mapping table?

The Pi converter in [`src/converters/claude-to-pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-pi.ts) uses regex replacements within `transformContentForPi` because Pi requires **syntactic transformation** of tool invocations within command bodies, not just identifier renaming. For example, `AskUserQuestion` must become `ask_user_question` in the actual content, and `TodoWrite` must expand to a file-based todo syntax string. A static mapping table would only handle name translation, whereas regex operations allow inline substitution of complex expressions and platform-specific placeholder syntax.

### Where can I find the complete list of supported Claude tool mappings?

The canonical reference for supported Claude tool mappings is the `TOOL_MAP` constant defined in [`src/converters/claude-to-opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-opencode.ts) at lines 24‑39. This record contains all lower-cased canonical names (e.g., `bash`, `read`, `write`, `edit`, `grep`, `glob`, `list`, `webfetch`, `skill`, `patch`, `task`, `question`, `todowrite`, `todoread`) that the conversion pipeline recognizes and translates for OpenCode, Codex, and Pi targets.