How Claude Code Tools Are Mapped to Droid, Cursor, and Other Platform Formats

The Compound Engineering Plugin converts Claude Code plugins into Droid, Cursor, Codex, and OpenCode formats using explicit tool-name maps and content transformers that rewrite commands, agents, and references for each target platform.

The EveryInc/compound-engineering-plugin repository provides a CLI tool that bridges Claude Code's plugin ecosystem with other AI engineering platforms. When you run bunx @every-env/compound-plugin install --to <target>, the tool applies specific mapping logic defined in TypeScript converter files to translate tool invocations, task calls, and agent references into platform-specific syntax.

Factory Droid Tool Mapping

Factory Droid requires explicit tool name translation because it uses PascalCase tool names and maintains a strict whitelist of valid capabilities.

The CLAUDE_TO_DROID_TOOLS Map

In src/converters/claude-to-droid.ts, the CLAUDE_TO_DROID_TOOLS record defines the direct mapping from Claude's lowercase tool names to Droid's PascalCase equivalents:

const CLAUDE_TO_DROID_TOOLS: Record<string, string> = {
  read: "Read",
  write: "Create",
  edit: "Edit",
  multiedit: "Edit",
  bash: "Execute",
  grep: "Grep",
  glob: "Glob",
  list: "LS",
  ls: "LS",
  webfetch: "FetchUrl",
  websearch: "WebSearch",
  task: "Task",
  todowrite: "TodoWrite",
  todoread: "TodoWrite",
  question: "AskUser",
};

Validating Tools with VALID_DROID_TOOLS

Droid only accepts tools defined in the VALID_DROID_TOOLS Set. The converter filters mapped tools against this whitelist before emitting them in the final bundle:

const VALID_DROID_TOOLS = new Set([
  "Read", "LS", "Grep", "Glob", "Create", "Edit", "ApplyPatch",
  "Execute", "WebSearch", "FetchUrl", "TodoWrite", "Task", "AskUser",
]);

How mapAgentTools Applies the Mapping

The mapAgentTools function scans an agent's name, description, and body for any mentioned Claude tools (case-insensitive), maps them to Droid equivalents, and returns the filtered, sorted list:

function mapAgentTools(agent: ClaudeAgent): string[] | undefined {
  const bodyLower = `${agent.name} ${agent.description ?? ""} ${agent.body}`.toLowerCase();
  const mentionedTools = new Set<string>();
  for (const [claudeTool, droidTool] of Object.entries(CLAUDE_TO_DROID_TOOLS)) {
    if (bodyLower.includes(claudeTool)) {
      mentionedTools.add(droidTool);
    }
  }
  if (mentionedTools.size === 0) return undefined;
  return [...mentionedTools].filter(t => VALID_DROID_TOOLS.has(t)).sort();
}

The resulting array is written into the agent's front-matter as tools: [...] by the convertAgent function.

Cursor Content Transformation

Unlike Droid, Cursor does not use a fixed tool registry. Instead, it requires semantic rewriting of content to match Cursor's rule syntax and command structure.

Rewriting Task Calls and Slash Commands

In src/converters/claude-to-cursor.ts, the transformContentForCursor function uses regex patterns to rewrite Claude-specific syntax:

// Task calls become "Use the <skill> skill to: <args>"
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm;
result = result.replace(taskPattern, (_,
    prefix, agentName, args) => {
  const skillName = normalizeName(agentName);
  return `${prefix}Use the ${skillName} skill to: ${args.trim()}`;
});

// Slash commands flatten namespace (e.g., /workflows:plan → /plan)
const slashCommandPattern = /(?<![:\w])\/([a-z][a-z0-9_:-]*?)(?=[\s,."')\]}`]|$)/gi;

Path and Agent Reference Updates

The transformer also handles path rewriting and agent references:

  • Path rewrite: ~/.claude/ directories become ~/.cursor/
  • Agent references: @agent-X patterns become the <agent> rule

The transformed content is then written to .cursor/rules/<name>.md by the Cursor target writer.

Codex and OpenCode Canonical Mapping

Codex and OpenCode share a canonical tool map but apply different content transformations based on their respective syntax requirements.

The Shared TOOL_MAP

Both converters import or define the same TOOL_MAP in src/converters/claude-to-opencode.ts (and referenced in src/converters/claude-to-codex.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",
};

The parseToolSpec function normalizes Claude tool strings (with optional path patterns) into canonical names using this map.

Codex-Specific Content Transformations

In src/converters/claude-to-codex.ts, the transformContentForCodex function applies platform-specific syntax:

// Task calls become "Use the $skill skill to: ..."
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm;
result = result.replace(taskPattern, (_,
    prefix, agentName, args) => {
  const skillName = normalizeName(agentName);
  return `${prefix}Use the $${skillName} skill to: ${args.trim()}`;
});

// Slash commands become /prompts:<normalized>
const slashCommandPattern = /(?<![:\w])\/([a-z][a-z0-9_:-]*?)(?=[\s,."')\]}`]|$)/gi;
result = result.replace(slashCommandPattern, (_, commandName) => {
  const normalizedName = normalizeName(commandName);
  return `/prompts:${normalizedName}`;
});

Agent references (@agent-X) are transformed into $skill skill syntax.

OpenCode Permission Generation

OpenCode uses the same TOOL_MAP and parseToolSpec logic, but instead of generating skill files, it builds a permission matrix for the opencode.json configuration.

When a Claude command specifies allowedTools, each tool string is parsed to extract the canonical tool name and optional path pattern. The applyPermissions function then generates the appropriate permission entries:

  • Tools without patterns are enabled globally
  • Tools with patterns (e.g., write(/tmp/*)) are restricted to those specific paths

This configuration is written to opencode.json under the "permission" key.

Summary

  • Factory Droid uses an explicit name map (CLAUDE_TO_DROID_TOOLS) in src/converters/claude-to-droid.ts to convert lowercase Claude tools to PascalCase Droid equivalents, filtered against VALID_DROID_TOOLS.
  • Cursor relies on content transformation via transformContentForCursor in src/converters/claude-to-cursor.ts to rewrite task calls, slash commands, paths, and agent references without a fixed tool registry.
  • Codex shares the canonical TOOL_MAP with OpenCode in src/converters/claude-to-opencode.ts, applying transformContentForCodex in src/converters/claude-to-codex.ts to generate $skill syntax and /prompts: commands.
  • OpenCode uses the same TOOL_MAP and parseToolSpec logic to build permission matrices in opencode.json rather than transforming content for skill files.

Frequently Asked Questions

How does the Compound Engineering Plugin handle tool name case sensitivity?

The plugin normalizes tool names to lowercase before looking them up in mapping dictionaries. In src/converters/claude-to-droid.ts, the mapAgentTools function converts the agent body to lowercase before checking against CLAUDE_TO_DROID_TOOLS keys. Similarly, parseToolSpec in src/converters/claude-to-opencode.ts normalizes input strings to lowercase before consulting the TOOL_MAP.

Can I customize the tool mappings for a specific target platform?

Currently, the tool mappings are hardcoded in the converter TypeScript files. To customize mappings for Factory Droid, you would need to modify the CLAUDE_TO_DROID_TOOLS record in src/converters/claude-to-droid.ts. For Codex and OpenCode, the TOOL_MAP in src/converters/claude-to-opencode.ts serves as the shared source of truth. The CLI does not currently support external configuration files for custom mappings.

What happens if a Claude tool is not present in the target platform's mapping?

For Factory Droid, tools not found in CLAUDE_TO_DROID_TOOLS are simply not added to the agent's tool list, and tools not in VALID_DROID_TOOLS are filtered out during the mapAgentTools execution. For Cursor, which lacks a fixed tool registry, unrecognized tools pass through the content transformer without modification. For Codex and OpenCode, tools not in TOOL_MAP return null from parseToolSpec and are typically omitted from permission generation or skill transformation.

How are agent references like @agent-name handled across different platforms?

Each platform converter applies specific regex transformations to handle @agent-name references. In src/converters/claude-to-cursor.ts, the transformer converts @agent-X patterns into the <agent> rule syntax. In src/converters/claude-to-codex.ts, the same pattern becomes $<agent> skill to match Codex's $skill syntax. OpenCode does not typically transform agent references in content, instead using the canonical tool names for permission scoping.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →