How Agents Are Converted to Cursor Agent Requested Rules in Compound Engineering

When converting a Claude Code plugin to a Cursor bundle, each Claude agent becomes a separate .mdc rule file under .cursor/rules/ with alwaysApply: false and a descriptive field, creating an Agent Requested rule that Cursor only activates when relevant.

The EveryInc/compound-engineering-plugin repository provides a CLI tool that transforms Claude Code plugins into Cursor-compatible bundles. Understanding how agents are converted to Cursor Agent Requested rules is essential for developers migrating their AI-assisted workflows between these environments.

The Conversion Pipeline

The transformation begins in src/converters/claude-to-cursor.ts, where the convertClaudeToCursor function orchestrates the migration. For each agent defined in the Claude plugin, it invokes convertAgentToRule to generate a corresponding Cursor rule object.

This conversion adheres to the Cursor rule specification defined in docs/specs/cursor.md, specifically implementing the Agent Requested rule type characterized by three properties: alwaysApply: false, an empty globs array, and a populated description field.

Understanding the Agent Requested Rule Model

Cursor distinguishes between rule types based on when they should be applied to a conversation. The Agent Requested model delegates activation decisions to the AI itself:

Rule type alwaysApply globs description Meaning
Agent Requested false empty set The AI decides whether to include the rule based on relevance of its description

When alwaysApply is false and no file globs are specified, Cursor's runtime evaluates the rule's description against the current conversation context to determine relevance.

Step-by-Step Agent Transformation

The convertAgentToRule function implements a four-stage pipeline to transform Claude agents into Cursor Agent Requested rules.

Name Normalization and Deduplication

First, the agent's name undergoes normalization via normalizeName(agent.name), which converts the identifier to lowercase and hyphenates it for filesystem compatibility. The uniqueName utility then ensures this identifier remains unique across the entire plugin, preventing collisions when multiple agents might have similar names.

Front-Matter Construction

The rule's YAML front-matter is constructed with exactly two fields:

description: <agent description or fallback>
alwaysApply: false

Notably, the globs field is omitted entirely, which satisfies the Agent Requested model's requirement for an empty glob pattern. This structure is defined in src/converters/claude-to-cursor.ts between lines 35-38.

Body Content Transformation

The agent's body content passes through transformContentForCursor, which handles path rewrites, slash-command flattening, and other syntax adaptations necessary for Cursor compatibility. If the agent defines capabilities, these are prefixed to the body as a ## Capabilities section before final assembly.

Final Rule Assembly

The formatFrontmatter utility combines the YAML front-matter with the transformed body content to produce the rule's final content string. The resulting CursorRule object contains the normalized name and the formatted content, ready for filesystem output.

File Output and Bundle Generation

Once the conversion pipeline generates CursorRule objects, src/targets/cursor.ts handles the physical bundle creation. This module writes each rule to a separate .mdc file within the .cursor/rules/ directory of the output bundle.

The filename corresponds to the normalized, deduplicated rule name assigned during conversion. This file structure allows Cursor's IDE integration to discover and load these rules dynamically, applying them only when the Agent Requested logic determines relevance based on the conversation context.

Code Example

The following example demonstrates converting a Claude plugin containing a security review agent:

import { convertClaudeToCursor } from "./src/converters/claude-to-cursor";

const claudePlugin = {
  agents: [
    {
      name: "Security Reviewer",
      description: "Reviews code for security vulnerabilities and dependency risks",
      body: "Analyze the provided code for:\n- SQL injection vectors\n- Unsafe dependency versions\n- Hardcoded secrets",
      capabilities: ["code_analysis", "security_scanning"]
    },
  ],
  commands: [],
  skills: [],
};

const cursorBundle = convertClaudeToCursor(claudePlugin, {});

// The resulting bundle contains one CursorRule:
// {
//   name: "security-reviewer",
//   content: `---
// description: Reviews code for security vulnerabilities and dependency risks
// alwaysApply: false
// ---
// ## Capabilities

// - code_analysis
// - security_scanning
//
// Analyze the provided code for:
// - SQL injection vectors
// - Unsafe dependency versions
// - Hardcoded secrets
// `
// }

When written to disk via src/targets/cursor.ts, this rule becomes .cursor/rules/security-reviewer.mdc and operates as an Agent Requested rule within Cursor.

Summary

  • Conversion Entry Point: The convertClaudeToCursor function in src/converters/claude-to-cursor.ts orchestrates the transformation of Claude agents into Cursor rules.
  • Agent Requested Model: Converted rules set alwaysApply: false and omit globs, allowing Cursor's AI to decide relevance based on the description field.
  • Name Processing: Agents undergo normalization via normalizeName and deduplication via uniqueName to generate filesystem-safe identifiers.
  • Content Transformation: Agent bodies pass through transformContentForCursor to handle syntax adaptations, with optional capability sections prepended.
  • File Output: The src/targets/cursor.ts module writes each rule as a separate .mdc file under .cursor/rules/ in the output bundle.

Frequently Asked Questions

What determines whether an Agent Requested rule is activated in Cursor?

Cursor's AI evaluates the description field of the rule against the current conversation context. If the description appears relevant to the user's query or the code being edited, the AI includes the rule's content in the context window. This differs from "Always Apply" rules which are included in every interaction, and "Glob Match" rules which activate based on file patterns.

Why are Claude agent names normalized and deduplicated during conversion?

The conversion process uses normalizeName to convert agent names into lowercase, hyphenated identifiers suitable for filesystem paths (e.g., "Security Reviewer" becomes "security-reviewer"). The uniqueName utility then ensures no two rules share the same filename, preventing collisions when multiple agents have similar names or when converting multiple plugins into the same bundle. This guarantees each .mdc file has a unique path under .cursor/rules/.

What happens to Claude agent capabilities during the conversion process?

If a Claude agent defines capabilities, the convertAgentToRule function prepends them to the rule body as a ## Capabilities section before the main content. This preserves the capability metadata in a format readable by Cursor, ensuring the AI understands what tools or functions the agent can access. The capabilities section appears after the YAML front-matter but before the transformed agent body content.

Where are the converted Cursor rules physically stored in the output bundle?

The src/targets/cursor.ts module handles the physical file system operations, writing each converted rule to a separate .mdc file within the .cursor/rules/ directory of the output bundle. Each filename corresponds to the normalized, deduplicated rule name generated during conversion (e.g., security-reviewer.mdc). This directory structure aligns with Cursor's native rule discovery mechanism, allowing the IDE to automatically detect and load these Agent Requested rules.

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 →