Cursor (cursor)
Output
.cursor/rules/<name>.mdc
.cursor/agents/<name>.md # one native subagent per agent spec
.cursor/skills/<name>/SKILL.md # one folder per skill, bundled assets included
.cursor/commands/<name>.md # one per command spec
.cursor/hooks.json # when hook specs exist (managed, overwritten each sync)
.cursor/mcp.json # when MCP entries exist
Rules: emit with
alwaysApply: true(override in spec frontmatter). An always-apply rule omitsglobs. A non-always rule withoutglobsfalls back to the Claude-spelledpathslist (comma-joined). When both are absent,globsis omitted too rather than defaulted to**/*, so Cursor treats the rule as description-driven ("Apply Intelligently") or manual-only ("Apply Manually") instead of auto-attaching it to every file. Scalar globs keep minimal quoting so a hand-authored.mdcround-trips clean. (#443, #536)Agents: native Cursor subagents at
.cursor/agents/<name>.md(Cursor 2.4+): frontmattername+descriptionplus optionalmodel,readonly, andis_backgroundwhen the spec declares them; the body is the system prompt. Cursor subagents have notoolsfield, so atoolslist drops with a coverage note;readonly: trueis the coarse equivalent. The old flattened.mdcand agent-as-command emissions are gone; the ledger sweeps stale copies.Commands: each command spec emits as a Cursor command under
.cursor/commands/: Markdown whose body is the prompt. The old/docs/agent/chat/commandspage 308s to that link, a "migrate commands to skills" FAQ; no Cursor page documents.cursor/commandsdirectly any more, so this is the closest surviving reference. Override the directory viaoutputs.cursor.commands-dir.Skills: native folders under
.cursor/skills/<name>/SKILL.md(the Agent Skills layout Cursor 2.4+ discovers), with every bundled sibling file (scripts, references, assets) propagated byte-for-byte. A source-layout scope moves the native tree under that directory and survives import.Frontmatter carries
name+description; optionalpaths,disable-model-invocation,icon,color, andmetadatapass through when the spec declares them (iconandcolorstyle the badge when the skill backs a Custom Mode). The pre-native flattenedskill-<name>.mdccopies are no longer written and get swept by the ledger on the next sync.Review: review specs emit as Bugbot files inside
.cursor/directories:.cursor/BUGBOT.mdat the repo root for unscoped specs,<scope>/.cursor/BUGBOT.mdfor scoped ones, with same-scope specs concatenated. Bugbot always includes the root file and picks up per-directory copies while traversing up from changed files. Override the basename viaoutputs.cursor.review-file. (#433)Environment: environment specs emit as
.cursor/environment.json(background-agent bootstrap). The spec keys pass through verbatim minus agnostic routing fields; multiple specs merge by top-level key. Override the path viaoutputs.cursor.environment-file. (#434)Ignore: ignore specs emit as
.cursorignore(gitignore syntax). Multiple specs concatenate. Override viaoutputs.cursor.ignore-file. (#435)Hooks: emit as Cursor Hooks in a managed
.cursor/hooks.json(version+ per-event arrays). Command hooks retain their{command, matcher?}shape. Atype: prompthook instead emitspromptand optionalmodel. Both forms preservetimeout,loop_limit(includingnull),failClosed, andmatcher. Override the file viaoutputs.cursor.hooks-file. (#438)Cursor uses camelCase event names (
beforeShellExecution,afterFileEdit, ...), passed through verbatim;validateflags unrecognized ones. Thirteen of those events consume amatcher, per the vendor's own "Available matchers by hook" table:preToolUse,postToolUse,postToolUseFailure(tool name),subagentStart,subagentStop(subagent type),beforeShellExecution,afterShellExecution(the full command string),beforeReadFile,afterFileEdit(tool name), andbeforeSubmitPrompt,stop,afterAgentResponse,afterAgentThought(one fixed value each).lintno longer flags a matcher on the last five (#734). It also stays quiet onbeforeMCPExecutionandafterMCPExecution, which that table does not list; a warning there would be the same false positive in the other direction.Cursor also reads Claude Code's own hook file. Third-party hooks puts
.claude/settings.jsonat rank 6 of a seven-rank merge with.cursor/hooks.jsonat rank 3, and "All matching hooks from every source run." So a repo syncingclaudeandcursortogether runs every hook twice. Two gates keep it off until you ask for it, both on that page: "Enable Third-party skills in Cursor Settings → Rules, Skills, Subagents", and "The feature must be enabled for your account" (#756).MCP: written into
.cursor/mcp.jsonunder the standardmcpServersmap (the shared builder also used by Claude Code). A stdio server acceptsenvFile, a path to an env file loading additional variables. A remote (url) server accepts a static-OAuthauthobject,{CLIENT_ID, CLIENT_SECRET, scopes}withCLIENT_IDrequired, for a provider without OAuth Dynamic Client Registration (cursor.com/docs/mcp, #661).Neither field is documented for the other targets sharing this builder, so both stay scoped to Cursor rather than appearing everywhere the shared schema is used. Every entry also accepts MCP
roots, a list of{uri, name}objects.disabled: truehas no effect here; seedisabledsupport by target.
The MCP file is managed as a whole document. Each sync replaces .cursor/mcp.json from MCP specs.
Config keys
| Key | Default |
|---|---|
outputs.cursor.rules-dir | .cursor/rules |
outputs.cursor.agents-dir | .cursor/agents |
outputs.cursor.skills-dir | .cursor/skills |
outputs.cursor.commands-dir | .cursor/commands |
outputs.cursor.mcp-file | .cursor/mcp.json |
outputs.cursor.review-file | BUGBOT.md |
outputs.cursor.environment-file | .cursor/environment.json |
outputs.cursor.ignore-file | .cursorignore |
outputs.cursor.hooks-file | .cursor/hooks.json |
Import
agnostic-ai import cursor reads .cursor/rules/** recursively, so nested rule directories are imported too:
| Source | Becomes |
|---|---|
.cursor/rules/<name>.mdc | <rules>/<name>.md with frontmatter (description, globs, alwaysApply, plus any custom keys) preserved verbatim |
.cursor/rules/<sub>/<name>.mdc | <rules>/<sub>/<name>.md, nested subdirectories preserved |
(no name: in frontmatter) | name: injected from the filename |
.cursor/agents/<name>.md | <agents>/<name>.md (byte-identical copy, provenance header stripped) |
.cursor/skills/<name>/ | <skills>/<name>/, full folder tree (SKILL.md + bundled assets) copied byte-for-byte |
.cursor/commands/<name>.md | <commands>/<name>.md (byte-identical copy, provenance header stripped) |
It round-trips cleanly: a later sync regenerates equivalent .cursor/rules/*.mdc, skill folders, and command files.
Verify
- Install Cursor from cursor.com.
- Check the tree:
ls .cursor/rules/ .cursor/skills/ .cursor/commands/ .cursor/mcp.json,grep "Generated by agnostic-ai" .cursor/rules/*.mdcfor the provenance header (it sits after the frontmatter block),python -m json.tool .cursor/mcp.json > /dev/null. - Open the project. The Rules panel loads every
.cursor/rules/*.mdc(confirmalwaysApplymatches each rule's frontmatter, no "failed to parse" warnings), the Skills list shows each.cursor/skills/<name>/, the agent picker lists each.cursor/agents/<name>.md, and the/command picker lists each.cursor/commands/<name>.md. - If MCPs are configured, Settings → MCP shows every
mcpServers.<name>green. - If hooks are configured,
python -m json.tool .cursor/hooks.json > /dev/nullparses; trigger the matched event (e.g. a shell command forbeforeShellExecution) and confirm thecommandruns.