Migrating from .cursorrules to .mdc files
Why .mdc is the current format
Cursor moved from a single .cursorrules file to per-file .mdc rules inside .cursor/rules/. The new format gives you:
- File-level scoping: Rules can target specific globs, reducing token waste
- Structured frontmatter: YAML metadata tells Cursor when to load each rule
- Better organization: Split one giant file into focused, maintainable rules
- Team-friendly: Easier to review and merge changes when rules are separate files
What changes
The migration command converts your .cursorrules file into one or more .mdc files in .cursor/rules/.
Before (.cursorrules)
# TypeScript rules
Use const by default.
Avoid any type.
# React rules
Use functional components.
Extract custom hooks.
After (.cursor/rules/)
typescript.mdc:
---
description: TypeScript conventions
globs: ["**/*.ts", "**/*.tsx"]
---
Use const by default.
Avoid any type.
react.mdc:
---
description: React component patterns
globs: ["src/**/*.tsx"]
---
Use functional components.
Extract custom hooks.
Running the migration
The migration command reads your .cursorrules file, intelligently splits it into logical sections, auto-detects technology-specific globs, and writes separate .mdc files with proper frontmatter.
npx cursor-doctor migrate
The command will:
- Read
.cursorrulesfrom your project root - Create
.cursor/rules/if it doesn't exist - Smart-split rules using three strategies: markdown headings,
---delimiters, and topic-change heuristics - Auto-detect globs from content (mentions of TypeScript, React, testing, Python, etc. get appropriate file patterns)
- Set
alwaysApply: truefor general rules that aren't technology-specific - Back up
.cursorrulesto.cursorrules.bak - Run a post-migration lint and report any issues
Use --dry-run to preview without writing files, or --force to overwrite existing rules.
Safe operation: The migrate command renames your .cursorrules to .cursorrules.bak instead of deleting it. If .cursor/rules/ already has files, it will warn you and stop unless you pass --force.
What to check after migrating
The migration is automatic, but you should review the output to make sure frontmatter and globs match your intent.
- Check descriptions: Make sure each
descriptionfield accurately describes when the rule should apply - Verify globs: Add or adjust
globspatterns to scope rules to the right files - Test in Cursor: Open a file that should trigger a rule and verify Cursor loads it (check the status bar or use
@rulesin chat) - Run the linter: Use
npx cursor-doctor scanto catch any frontmatter issues
Common gotchas
A few things that trip people up after migration:
Review auto-detected globs
The migrator detects technologies from your rule content (TypeScript, React, Python, testing, etc.) and assigns file globs automatically. Rules without technology-specific content get alwaysApply: true. Double-check that the detected globs match your intent.
Over-splitting
If your .cursorrules file had lots of small headings, you might end up with too many tiny .mdc files. Merge related rules back together. One rule per concern is good, one rule per sentence is too granular.
Old file still active
The migrator renames .cursorrules to .cursorrules.bak, so it won't be loaded by Cursor. If you renamed it back or have both files present, Cursor loads both, and .mdc rules take precedence on conflicts. Delete the .bak file once you've verified the migration.
Manual migration
If you prefer full control, you can migrate manually:
- Create
.cursor/rules/in your project - For each logical section in
.cursorrules, create a new.mdcfile - Add frontmatter with
descriptionandglobs - Copy the rule content below the frontmatter
- Run
npx cursor-doctor scanto validate
Related guides
- How to write Cursor rules that actually work
- Convert rules between Cursor, Windsurf, and Claude Code
- Run cursor-doctor in CI with GitHub Actions
Migrate now
Run the migration command to convert your .cursorrules file to the modern .mdc format.
npx cursor-doctor migrate