How to Migrate .cursorrules Files to Cursor's .mdc Format
A single .cursorrules file works fine until a project grows past one stack. Once a repo mixes a Next.js frontend with a FastAPI backend, one flat rules file forces Cursor to hold both sets of conventions in every prompt, whether the file you're editing needs them or not. Cursor's newer format fixes this: .cursor/rules/*.mdc is a directory of scoped rule files, each one a Markdown file with frontmatter that tells Cursor exactly when to apply it. Migrating is a mechanical job, not a rewrite, but skipping it means paying an accuracy tax on every prompt in a mixed-stack repo.
What Changed Between .cursorrules and .mdc Rules?
.cursorrules is a single plain-text file at the project root, included in full on every prompt regardless of what file you're editing. .cursor/rules/*.mdc is a directory of separate files, each scoped by a frontmatter block with a description, a list of glob patterns, and an alwaysApply flag. Cursor only pulls in the .mdc files whose globs match the file currently open, so a Python rule never bloats the context for a React component edit. The practical effect is smaller, more relevant prompts: a rule about Django model conventions no longer rides along on every edit to a Tailwind component, and a rule about React hooks no longer gets pulled into a FastAPI route file.
How Do You Convert an Existing .cursorrules File to .mdc?
The conversion is a split-and-tag job, not a rewrite of the rules themselves. Read through your .cursorrules file and group the lines by the part of the stack they govern, then give each group its own file and frontmatter block.
- Create a .cursor/rules/ directory at the project root.
- Read your existing .cursorrules file and group the lines by concern (frontend, backend, database, testing).
- Create one .mdc file per group, named for what it covers, such as frontend-conventions.mdc.
- Add a frontmatter block to each file with a description, a globs list matching the relevant file paths, and alwaysApply set to false unless the rule is truly universal.
- Paste the matching rule text below the frontmatter as plain Markdown.
- Delete or archive the old .cursorrules file once every rule has a home.
- Restart Cursor so it picks up the new directory.
The frontmatter is the part people get wrong most often. A glob pattern that's too broad (matching every file) defeats the point of scoping; one that's too narrow means the rule silently never fires on files it should cover. Write the glob to match the file extensions and directory the rule actually concerns — src/**/*.tsx for a React component rule, api/**/*.py for a FastAPI route rule — and test it against a real file before moving on to the next rule.
Why Split One Rules File Into Several .mdc Files?
A flat .cursorrules file can't tell Cursor to only apply a rule to .tsx files. Every rule in it applies to every prompt, so a large flat file both wastes context and lets conventions from an unrelated part of the stack bleed into an edit. Splitting by scope fixes both problems at once, and it also makes the rules easier to maintain: updating the Prisma conventions means editing one small file instead of scrolling through an unrelated 400-line document to find the three relevant lines.
| Aspect | .cursorrules (legacy) | .cursor/rules/*.mdc (current) |
|---|---|---|
| File count | One file for the whole project | One file per concern or stack |
| Scoping | Applies to every prompt | Applies only where globs match |
| Metadata | None | Frontmatter: description, globs, alwaysApply |
| Multi-stack projects | Rules from unrelated parts leak in | Each stack's rules stay isolated |
What Happens If You Keep Both Formats?
Cursor reads both if both exist: the legacy .cursorrules file still applies to every prompt, and any .mdc files layer on top with their own scoping. That's a reasonable transition state while you migrate section by section, but it defeats the purpose if you leave it that way permanently — the flat file keeps injecting unscoped rules into every prompt even after you've built scoped replacements for the same conventions. Treat the flat file as a checklist during migration: as each concern gets its own .mdc file, delete the matching lines from .cursorrules, and once it's empty, remove it.
A common shortcut is migrating only the rules for the stack you touch most and leaving the rest in the flat file indefinitely. That works, but it means the project runs on two systems at once — some conventions scoped, some global — which makes it harder to reason about why Cursor followed one rule and ignored another on a given prompt. Finishing the migration for every rule in the file removes that ambiguity.
Writing twenty scoped .mdc files by hand for a project that touches half a dozen frameworks is where most people stop migrating halfway through and leave the flat file in place. BuyCoded's Cursor Rules Mega-Pack ships 1,057 rules across 20 stacks — Next.js 15, React 19, TypeScript, Tailwind v4, Python 3.12+, FastAPI, Django 5, Go, Rust, and more — already written in both the legacy .cursorrules format and the current .mdc format with working frontmatter, so a mixed-stack project can pull in pre-scoped files per stack instead of authoring each glob pattern from scratch.
How Do You Verify Cursor Is Actually Using the New Rules?
Open a file that matches one of your new .mdc globs and ask Cursor directly what conventions it's following for the project. It will summarize the active rules back to you, which confirms the frontmatter matched and the file loaded. If a rule doesn't show up, the glob pattern is the first thing to check — a mismatched path is the most common reason an .mdc file silently never applies. Two more checks worth running: open a file that should NOT match the rule and confirm Cursor doesn't mention it, and check that alwaysApply is set to false on anything you meant to scope, since a stray true silently turns a targeted rule back into a global one. Do this check right after writing each file rather than at the end — a bad glob is much faster to spot against one freshly written file than against a whole directory you migrated a week ago and no longer remember the intent behind.
Is It Worth Migrating If Your Rules Already Work?
If your project is a single stack and .cursorrules hasn't caused problems, migrating buys you less — the scoping benefit only shows up once a repo mixes conventions. The real cost shows up in multi-stack repos, where every prompt on a Python file is still carrying React conventions it will never use, and vice versa. Migration effort is the honest objection here — hand-splitting a large rules file and getting the globs right for every stack takes real time, which is exactly what a pre-built, pre-scoped pack trades for a one-time cost instead of an afternoon of trial and error per stack.
Get Rules Already Migrated to Both Formats
If you'd rather start from rules that are already split and scoped than convert a flat file by hand, browse the full catalog at BuyCoded's products page — every pack ships as a complete, downloadable source zip with a commercial license, so you can drop in what your stack needs and skip the manual conversion entirely.
Frequently asked questions
What is the difference between .cursorrules and .mdc rule files?
.cursorrules is Cursor's legacy format: one plain-text file at the project root that applies to every prompt. .mdc files live in a .cursor/rules/ directory, one file per concern, each with a frontmatter block (description, globs, alwaysApply) that tells Cursor which files the rule applies to. The .mdc format scopes rules instead of applying all of them everywhere.
Do old .cursorrules files still work in current Cursor versions?
Yes. Cursor still reads a .cursorrules file if one exists at the project root, alongside any .cursor/rules/*.mdc files in the same project. Both formats can run together during a migration, though leaving the flat file in place long-term means its rules keep applying unscoped to every prompt even after you've built scoped .mdc replacements.
Can I use both .cursorrules and .cursor/rules/*.mdc in the same project?
Yes, Cursor supports both at once. This is useful mid-migration: keep the flat file for rules you haven't converted yet, and add .mdc files for the ones you have. Once every rule has a scoped .mdc equivalent, delete the .cursorrules file so unscoped rules stop applying to unrelated files.
What does the alwaysApply field do in an .mdc file?
alwaysApply is a frontmatter setting in an .mdc file. Set to true, the rule applies to every prompt regardless of glob matches, similar to legacy .cursorrules behavior. Set to false, the rule only applies when the file being edited matches one of the globs listed in that same frontmatter block.
How many stacks does the BuyCoded Cursor Rules Mega-Pack cover?
The pack covers 20 stacks, including Next.js 15, React 19, TypeScript, Tailwind v4, shadcn/ui, Vue 3, Svelte 5, Python 3.12+, FastAPI, Django 5, Go, Rust, Node with Express, PHP, Laravel, Prisma 6, Drizzle ORM, Supabase, PostgreSQL 16+, and React Native with Expo, at 1,057 total rules shipped in both Cursor formats.
Does migrating to .mdc rules require restarting Cursor?
Yes. After adding or editing files in .cursor/rules/, restart Cursor so it re-reads the directory. The change takes effect on your next prompt after the restart. You can confirm it worked by opening a matching file and asking Cursor what conventions it's following for the project.