Back to blog
Engineering19 min read

Cursor Rules and Prompt Templates (2026)

Which Cursor rule mechanisms exist in 2026, what .mdc frontmatter actually does, and seven copy-paste rule files: house style, testing, framework, architecture, review, do-not-edit, language.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: Cursor project rules are .mdc files in .cursor/rules, and three frontmatter fields decide everything: description, globs, alwaysApply. Those three produce four behaviours — always on, glob-attached, agent-chosen, manual. The root .cursorrules file is legacy per Cursor's help docs. Seven copy-paste rule files below.

A rules file is a prompt that fires without you typing it. That is the whole idea, and it is also the reason most rule sets quietly stop working: every failure mode of a bad prompt applies, except you never see the prompt, so you never diagnose it. Vague instructions get ignored. Two rules that disagree produce behaviour that changes between sessions. A 600-line always-applied file eats the context window on every single request, including the ones it has nothing to do with.

This is Cursor's feature, not ours. Below: which mechanisms exist today, verified against Cursor's own documentation on August 28, 2026; what the three frontmatter fields actually do, including one combination the docs do not cover; and seven complete rule files to paste and edit.

Which Cursor rule mechanisms exist in 2026?

Cursor's reference page opens by saying it "supports four types of rules" and lists Project Rules, User Rules, Team Rules and AGENTS.md. The help page adds a fifth file that the reference page does not mention at all. Here is the full set as documented on both pages.

MechanismWhere it livesScopeDocumented on
Project rules.cursor/rules/*.mdcThe repo, version-controlledReference and help
User rulesCustomize → Rules, synced to your accountEvery project, you onlyReference and help
User rule files~/.cursor/rulesThis machine only, does not syncHelp only
Team rulesCursor dashboard, Team and Enterprise plansEvery repo in the orgReference and help
AGENTS.mdProject root and subdirectoriesThe repo, plain markdownReference and help
CLAUDE.mdProject rootThe repo, always appliedHelp only
.cursorrulesRepo rootLegacyHelp only

Two rows deserve a second look. The account-synced user rules and the on-disk user rule files are different mechanisms with nearly the same name: the help page says the on-disk ones "stay on the machine and do not sync". And CLAUDE.md is not a compatibility afterthought, because the help page says those files are "always applied to every conversation", regardless of any alwaysApply setting. If you keep a CLAUDE.md for Claude Code and a .cursor/rules set for Cursor, Cursor is reading both, and only one of them is scoped.

Is .cursorrules dead, or does it still work?

This is the question the search results get wrong most often, so here is exactly what Cursor publishes and exactly what it does not.

The reference documentation at cursor.com/docs/rules contains zero occurrences of the string cursorrules. Not a deprecation note, not a migration paragraph. The file simply does not appear in the page that documents the rules system.

The help page does address it, under a heading asking how to migrate. Its answer: the .cursorrules file in your project root "is legacy and will be deprecated". It then gives four steps: create a new rule via the command palette, copy the content across, set the type to Always Apply, which the page says "matches the old behavior", and delete the old file.

The practical read: .cursorrules is a single always-on blob with no scoping, which is the worst shape a rules file can have. Even if it works perfectly today, the migration to .cursor/rules is the upgrade you wanted anyway, because it is what lets you stop paying for the Python rules while editing CSS.

What do the .mdc frontmatter fields actually do?

Project rules live in .cursor/rules as .mdc files. The extension is load-bearing: Cursor's docs state that a plain .md file in that folder is ignored, because it has no frontmatter to specify the three fields. If you prefer plain markdown with no metadata, the documented answer is AGENTS.md instead.

The three fields are description, globs, and alwaysApply. Cursor's docs give this interaction table:

alwaysApplydescriptionglobsBehaviour
trueAlways included. Globs and description are ignored.
falseprovidedAuto-attached when a matching file is in context.
falseprovidedomittedAgent reads the description and pulls the rule in when relevant.
falseomittedomittedIncluded only when you @-mention the rule in chat.

Those four rows map onto the four labels in Cursor's type dropdown: Always Apply, Apply to Specific Files, Apply Intelligently, and Apply Manually.

Note what the table leaves out. There is no row for alwaysApply: false with both a description and globs set — which is a combination the UI will happily let you produce, and which plenty of published example files use. Cursor does not document what happens then. I have not found a page that specifies it, so I am not going to tell you. If you need that behaviour, split the rule in two and scope each half explicitly; a documented mechanism you understand beats an undocumented one that appears to work.

Globs are comma-separated and use standard patterns. From Cursor's own reference: **/*.ts matches all TypeScript files in any directory, src/** matches everything under src/, docs/**/*.md, docs/**/*.mdx shows the comma form, and tailwind.config.* matches any extension.

Do project, user, and team rules override each other?

They combine. This trips people up because "precedence" suggests a winner, and there mostly is not one.

Cursor's reference page gives the order as Team Rules, then Project Rules, then User Rules, and then states the part that matters: "All applicable rules are merged; earlier sources take precedence when guidance conflicts." The help page phrases the same order as Team Rules > Project Rules > User Rules.

So a user rule saying "always add JSDoc" and a project rule saying "no comments unless the code is non-obvious" do not resolve into one instruction. Both land in the model's context, and you get whichever one the model weighted higher on that particular request. That is not a bug in Cursor. It is the ordinary behaviour of a system prompt assembled from several sources, and it is the single most common reason a rule "randomly" stops being followed. If two rules disagree, the fix is to delete one, not to phrase the other more forcefully.

Team rules add one more wrinkle: on Team and Enterprise plans an admin can mark a rule enforced, which means members cannot toggle it off. Team rules also support glob patterns, and the docs note that a team rule without a glob applies to every conversation.

Are nested .cursor/rules directories in subfolders supported?

Honest answer: Cursor's current documentation does not say, and I am not going to fill the gap.

What both pages actually describe is subfolders inside one .cursor/rules directory. The reference page's file-layout example shows a frontend/ folder holding components.mdc, annotated as organising rules in folders. The help page prefers you skip even that, saying nested subfolders work "but a flat structure is simpler and easier to manage". It also notes that Cursor "identifies rules by their full file path, not their name alone", so two rules with the same filename in different folders both apply.

None of that is the same as a .cursor/rules directory living inside packages/api/. If you have read that a rules folder can be nested per package, check the date on what you read: it is not described on either current Cursor page, and this system has been reorganised before.

What is documented for per-directory instructions is AGENTS.md. The reference page states plainly: "Cursor supports AGENTS.md in the project root and subdirectories." Nested files are combined with parent directories, with more specific instructions taking precedence. So if your monorepo needs different guidance per package today, the documented route is a nested AGENTS.md per package, not a nested rules folder.

Why does a rules file behave exactly like a prompt?

Because it is one. Cursor's docs say so directly: "When applied, rule contents are included at the start of the model context." There is no interpreter, no validator, no enforcement layer. Your rule is text, prepended to the conversation, competing for attention with the file you are editing and everything you have said since.

That single fact generates the whole discipline:

Vague instructions get ignored. "Write clean, maintainable code" costs tokens and changes nothing, because the model already thinks it is doing that. Cursor's own best practices say to "Avoid vague guidance" and write rules "like clear internal docs". A rule earns its place when it names something the model would otherwise get wrong: a directory, a helper, a banned import, a specific sequence.

Contradictions produce inconsistency, not errors. Nothing warns you. The two instructions merge, and the output varies by session. Every contradictory pair is a coin flip you are paying for on every request.

Always-on rules are charged on every request. Cursor caps its guidance at "Keep rules under 500 lines", but a 500-line always-applied rule is an enormous standing tax. The reason globs exists is so the React conventions load when you touch a .tsx file and stay out of the context when you are writing a migration.

Rules are guidance, not enforcement. This is the part vendors are careful about and blog posts are not. Cursor's docs describe rules as providing "system-level instructions" and consistent guidance. Nothing on either page promises compliance, and Cursor's team-rules section contains its own caution that AI guidance should not be your only security control. If a rule must hold, it needs a linter, a test, or a CI check behind it. Use rules to steer defaults, not to guarantee outcomes.

And a scope limit worth knowing before you blame your phrasing: Cursor's reference FAQ says "Rules do not impact Cursor Tab or other AI features", and the help page extends that to Inline Edit and Bugbot PR reviews. Rules apply to Agent. If your rule appeared to do nothing during a Cmd-K edit, it was never loaded. For the wider set of reasons a loaded rule still gets ignored, see why Cursor ignores your rules file.

Seven Cursor rule templates you can paste today

Complete files. Replace anything in CAPS_LIKE_THIS with your own stack, delete the lines that do not describe your repo, and keep them short.

1. House style and conventions — always applied

The only file that should be alwaysApply: true. Keep it under roughly thirty lines forever: everything you add here you pay for on every request.

---
alwaysApply: true
---

- Package manager is PACKAGE_MANAGER. Never generate lockfile edits by hand.
- Imports use the `@/` alias for anything under `src/`. Never emit deep relative
  paths like `../../../lib`.
- Errors are returned, not thrown, across module boundaries. Internal helpers
  may throw.
- No new dependencies without asking first. Check `package.json` before
  suggesting a library.
- When you are unsure how something is done here, read a neighbouring file
  before proposing a pattern.

2. Testing — auto-attached by glob

Scoped to test files, so it costs nothing while you are writing production code.

---
globs: TEST_GLOB
alwaysApply: false
---

- Test framework is TEST_FRAMEWORK. Do not introduce another one.
- One behaviour per test. If a test name contains "and", split it.
- Assert on observable output, never on internal call counts, unless the call
  itself is the contract.
- Use the existing factories in `FACTORY_PATH`. Do not hand-build fixture
  objects inline.
- Never add a snapshot test for anything a human has to read to review.
- When a test fails, fix the code or the test deliberately. Never loosen an
  assertion to make a run green.

3. Framework rule — auto-attached by glob

Parameterise the glob and the framework; the shape holds for any of them. This example is written for a React app.

---
globs: src/components/**/*.tsx, src/app/**/*.tsx
alwaysApply: false
---

- Components are named exports. No default exports.
- Server components by default. Add the client directive only when the file
  needs state, effects, or browser APIs, and say why in a one-line comment.
- Data fetching happens in STATE_LAYER. Components receive data as props.
- Styling is STYLING_APPROACH. Do not add inline style objects.
- Keep a component under 200 lines. Past that, extract a subcomponent into the
  same directory rather than adding another prop.
- Any user-facing string goes through I18N_HELPER. A bare string literal in
  JSX is a bug, not a detail.

4. How to make a change here — agent-requested

No glob, just a description the agent reads to decide relevance. This is the rule that saves the most time, because it encodes the sequence a newcomer gets wrong.

---
description: How to add or change a feature in this codebase — the required order of edits, where each layer lives, and what must be updated together
alwaysApply: false
---

Adding a feature touches four places, in this order:

1. Schema first. Migrations live in `MIGRATIONS_DIR`, numbered, additive only.
   Never edit a migration that has already run.
2. Data access next, in `DATA_DIR`. One file per domain. No queries anywhere
   else in the codebase.
3. Server action or endpoint in `API_DIR`, validating input with
   VALIDATION_LIBRARY at the boundary before anything else runs.
4. UI last, in `UI_DIR`, consuming the action through STATE_LAYER.

Rules that apply across all four:

- New fields are optional or defaulted. Existing callers must keep working
  without changes.
- Never rename or remove a column, an exported symbol, or a route parameter
  in the same change that adds something. Split it.
- If a change cannot avoid breaking an existing caller, stop and say so
  before writing code.

5. Review — manual, via @-mention

Neither field set, so it loads only when you type @review. That is the point: a review pass is deliberate, and should not sit in context while you write.

---
alwaysApply: false
---

Review the current diff. Do not rewrite it. Report findings only.

For each finding, give the file, the line, what breaks, and the smallest fix.

Look for, in this order:

1. Correctness. Off-by-one, unhandled null, wrong await, swallowed error,
   a condition that reads backwards.
2. Contract breaks. A changed function signature, a renamed export, a route
   parameter, a stored key, a database column that existing callers depend on.
3. Missing tests for the branch this diff introduces.
4. Anything that duplicates a helper that already exists in HELPERS_DIR.

Do not comment on formatting, import order, or naming preferences. A linter
owns those.

If the diff is clean, say so in one sentence. Do not invent findings.

6. Generated and vendored files — leave them alone

Short, always applied. It earns permanent residency because the failure it prevents is expensive and silent.

---
alwaysApply: true
---

Never edit files in these locations. They are generated or vendored:

- `GENERATED_DIR` — regenerate with `GENERATE_COMMAND` instead.
- `vendor/`, `third_party/` — upstream code. Patch via PATCH_MECHANISM.
- Any file whose first line contains "DO NOT EDIT" or "auto-generated".
- Lockfiles. Change the manifest and run the package manager.

If a fix appears to require editing one of these, the real fix is upstream or
in the generator. Say so instead of editing the file.

7. Language-specific rule — auto-attached by glob

One per language in a polyglot repo. This example is Python; the shape transfers.

---
globs: **/*.py
alwaysApply: false
---

- Target PYTHON_VERSION. Use modern built-in generics, not the legacy
  typing aliases.
- Every public function has type hints on parameters and return value.
- Formatting and linting are owned by LINTER. Do not reformat by hand and do
  not argue with it in comments.
- Raise a specific exception from EXCEPTIONS_MODULE. Never raise bare
  `Exception`, and never use a bare `except:`.
- Prefer a dataclass or a typed dict over passing loose dictionaries between
  functions.
- No mutable default arguments. Ever.

How do you tell whether a rule is actually being applied?

Do not assume it is. Verify, then trust.

The cheapest check is to make a rule observably distinctive for one session. Add a line telling the agent to start its reply with a specific token, run a task that should trigger the rule, and see whether the token appears. If it does not, the rule never loaded, which is a scoping problem: wrong glob, missing description, wrong rule type. No amount of rewording fixes that. If it does load and the guidance is still ignored, that is a content problem, and shortening the rule usually helps more than emphasising it.

Cursor's own troubleshooting is the same shape: check the rule type first, then the pattern. For Apply Intelligently, make sure a description exists. For Apply to Specific Files, make sure the glob matches the files you actually have open.

The other half is a habit rather than a check. When the agent makes the same mistake twice, that is the signal to write a rule. Cursor is explicit: "Start simple. Add rules only when you notice Agent making the same mistake repeatedly." Writing rules for problems you have not had yet is how a rule set becomes 400 lines of guesses.

Which rules should you delete?

Most of them, eventually. A rule set is not an archive; it is a working prompt, and every line in it competes with every other line.

Delete a rule when the thing it prevents can be caught mechanically instead. Cursor's docs list "Copying entire style guides" first under what to avoid, with the reason: use a linter instead, because the agent already knows common style conventions. The same logic retires any rule a formatter, a type checker, or a test could enforce. A linter wins every time, because it does not consume context and it does not merely suggest.

Delete a rule when the code moved. A rule pointing at a directory that no longer exists is worse than no rule, because it is confidently wrong. Cursor's guidance to reference files rather than copy their contents exists partly for this reason.

Delete a rule when you cannot remember which failure it was written for. Most rule sets fail that test somewhere. The same instinct applies to any reusable prompt template: the ones worth keeping are the ones you can point at a specific bad output and say "this is what that stops". Prompt versioning is the same argument applied to prompts you do type.

And delete the aspirational ones. "Write elegant code", "think carefully" and "be thorough" are wishes, not instructions. They survive because deleting them feels like arguing against quality. They do nothing.

Where does MCP fit alongside rules?

Rules and tools solve different halves of the same problem, and it is worth being clear about which one you need.

A rule is standing text. It changes how the model behaves, cannot fetch anything, and goes stale the moment your codebase moves. An MCP server is a connection: Cursor's MCP documentation lists Tools, Prompts, Resources, Roots, Elicitation and Apps as supported protocol capabilities, with Prompts described as "Templated messages and workflows for users". Servers are configured per project in a .cursor/mcp.json file, or globally in the equivalent file in your home directory.

The division that works in practice: rules carry the conventions of this repo and belong in git alongside it. Anything you want in every editor and every project, such as your prompt library or the enhancement step you run before a long task, belongs behind a tool, because a tool follows you and a rule does not. That is the same reasoning behind using MCP inside Claude Code and, for the file-based half of the story, CLAUDE.md templates.

Where Prompt Architects sits in this, plainly: we do not generate .mdc rule files, and there is no Prompt Architects extension for Cursor. What we do is the prompt layer. Our MCP server exposes improve, refine, shorten and enhance as tools, and Cursor is one of the listed clients: you add the server URL under Settings, MCP, then sign in through OAuth. Rules stay your job. Everything above is Cursor's feature, documented by Cursor, and works whether or not you ever touch our product.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account

Start with three files

If you are beginning from nothing, resist the urge to write seven rules today. Write three.

One always-applied file of ten to twenty lines: package manager, import convention, the two mistakes the agent has already made twice. One glob-scoped file for whatever you touch most. One agent-requested file describing how a change gets made in this codebase, because that is the knowledge a new contributor takes a week to absorb and a model never absorbs at all.

Then wait. Add the fourth rule the second time you correct the same thing by hand, and not before. That is also the answer when the agent rewrites code you did not ask it to touch — a scoped rule naming what is off limits beats a longer general one.

Every mechanic in this post was verified against Cursor's own documentation at cursor.com/docs/rules and cursor.com/help/customization/rules on August 28, 2026. This system has been reorganised more than once, so if something here disagrees with what you see in the app, Cursor's docs are the tiebreaker, not this page.

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account