You’re three messages into a Cursor chat. The agent just wrote a class component when your codebase has been hooks-only for two years. You re-explain. It writes another one. You paste your style guide. Works for one file, then gone. This is the problem the Cursor AI rules file solves – and the one most tutorials skip while showing you a generic React template.
Below I’ll show you what’s actually happening when rules fire (and don’t), because the official docs explain the syntax but not the failure modes you’ll hit by Friday.
The scenario where rules earn their keep
New contributor joins. The team has unwritten conventions – error wrapping, logger usage, which directory owns business logic. The AI knows none of it. Every prompt becomes a re-briefing. Each new chat starts blank; the model has no memory of your stack, your naming conventions, or your preferences between sessions. You end up repeating yourself constantly.
Rules fix this by attaching context before you type anything. Per Cursor’s official rules documentation, when a rule applies, its contents are prepended to the start of the model context – before your prompt reaches the model. Think of it as a system prompt the agent carries everywhere, provided you set it up correctly.
What “the rules file” actually means in early 2026
The terminology changed. There used to be one file: .cursorrules at the repo root. Now there are layers.
| Type | Location | Status | Use for |
|---|---|---|---|
| Project Rules | .cursor/rules/*.mdc |
Current, recommended | Codebase-specific conventions, version-controlled |
| User Rules | Cursor Settings → Rules | Current | Personal preferences across all projects |
.cursorrules |
Repo root | Deprecated (still works – check current docs) | Legacy projects only |
As of early 2026, Cursor’s official docs flag .cursorrules as deprecated and recommend migrating to Project Rules for more control, flexibility, and visibility. If you’re starting today, use .cursor/rules/. Inherited a .cursorrules? Leave it – Cursor reads both.
Setting up your first rule
Create .cursor/rules/project-context.mdc in your repo root. Every .mdc file is Markdown with a YAML frontmatter block on top. The frontmatter controls activation. Getting it wrong is the #1 reason people swear rules “don’t work.”
---
description: Core project conventions for the payments service
globs:
alwaysApply: true
---
# Stack
- TypeScript only. Do not add new .js files.
- Errors are returned as Result<T, E>. Do not throw across module boundaries.
- Test runner is Vitest. Do not generate Jest syntax.
# Architecture
- Business logic lives in `services/`, not in route handlers.
- DB access goes through `lib/db/` - never import the Prisma client directly in a component.
# Banned patterns
- No `any`. Use `unknown` and narrow.
- No default exports.
- No `console.log` in committed code - use the logger in `lib/log.ts`.
Notice the “Banned patterns” section. That’s the most useful part of this file – not “Architecture.” Community guides and the Markaicode Cursor rules guide both make the same observation: negative instructions (“do not use X”) outperform positive style guidance (“prefer clean code”). Telling the agent what NOT to do prevents the correction loops that eat your day. “Prefer functional patterns” is vague. “Do not throw across module boundaries” is not.
The four activation modes – and the one that fails silently
The catch: frontmatter has three fields, but they combine into four distinct behaviors. This distinction matters more than the syntax.
- Always –
alwaysApply: true. Rule loads on every prompt, every chat. Use sparingly. - Auto Attached –
globsset,alwaysApply: false. Loads when matching files are in context. Best for directory-specific rules. - Agent Requested –
descriptionset, no globs,alwaysApply: false. The agent reads the description and decides whether to pull the rule in. - Manual – invoked by name with
@RuleNamein chat.
Mode 3 is where people get burned. Turns out “Apply Intelligently” rules miss conversations when the description is too generic (per the Vibecodingacademy complete guide and the DataCamp tutorial). “Helpful guidelines for the API” gets ignored. “Stripe webhook signature verification and idempotency handling” fires when relevant. Write descriptions like you’re telling a new hire when to consult the doc – not like a folder label.
The token tax nobody warns you about
Every always-on rule is prepended to your context window on every single request. Not just the requests where it’s relevant. Every one. The community calls this the token tax, and it’s invisible until your response times slow down or the agent starts truncating its own outputs.
Is there a clean formula for how many always-apply rules is too many? Honestly, no. The right threshold depends on rule length, model context size (which changes with Cursor updates), and how many files you’re routinely pulling into context. What the Vibecodingacademy guide and community consensus agree on: if you notice Cursor feeling sluggish or hitting context limits, look at your always-apply rules first. One long always-apply rule covering everything is a liability.
Practical fix: If you catch yourself adding a fifth always-apply rule, stop. Convert one to Auto Attached with a glob like
app/api/**/*.ts. The rule still fires when needed – just not when you’re editing CSS.
Split rules by surface area. One core.mdc with alwaysApply: true for the genuinely universal stuff – keep it short. Then api.mdc, db.mdc, ui.mdc with globs scoped to the right directories. Per the official docs, subdirectories can include their own .cursor/rules folder, and nested rules attach automatically when files in that directory are referenced in context.
When rules silently fail
Rules don’t error out when they break. They just stop influencing output.
Recency bias mid-conversation. A rule can fire correctly at message 1 and get ignored by message 8. The model weighs recent tokens more heavily than the rule sitting at the top of context – the DataCamp Cursor Rules tutorial documents this explicitly. The fix isn’t to remind the agent mid-session. Start a fresh chat.
Conflicting globs. Two rules with overlapping globs silently conflict. Cursor picks whichever is loaded last – no warning, no error. If your typescript.mdc says “prefer interfaces” and your react.mdc says “prefer types,” and both match .tsx files, you’ll get inconsistent output with no obvious cause. Narrow the globs or merge the files.
Disappearing edits. Changes to .mdc files sometimes vanish without saving. If edits aren’t sticking: close Cursor completely, select “Override” on the unsaved-changes prompt, reopen. Annoying, undocumented, real.
Rules don’t cover autocomplete. Per the official FAQ (as of early 2026 – check current docs if this matters to you), rules apply only to Agent and Inline Edit. Tab completion ignores them entirely. Set a rule banning console.log and Tab still suggests one – that’s not a bug, that’s the documented boundary.
A maintenance heuristic
Rules rot. Stack changes, conventions evolve, rules written six months ago start fighting current practice. My trigger: when you find yourself re-explaining the same thing to Cursor repeatedly, it belongs in a rule. Write it down then – not later.
The reverse matters too: when a rule starts producing wrong code, it’s probably out of date. Read it like a stranger would. Does it describe how the codebase actually works today? If not, delete it. A wrong rule is worse than no rule.
FAQ
Should I migrate my existing .cursorrules file right now?
No rush – it still works. Move sections to .cursor/rules/*.mdc when you’d benefit from scoping (like when one section only applies to your backend).
Why does the agent ignore my rule partway through a conversation?
Mid-conversation drift. The rule loaded fine at message 1, but got buried by message 8 as newer tokens dominated the context window. Open a new chat with the same prompt – you’ll usually see the rule applied. If it still fails, check that the .mdc frontmatter is valid YAML: a missing closing --- breaks the entire rule silently, with no error shown anywhere. That’s a fun one to debug at 11pm.
Can I generate a rules file automatically?
Yes. Run /Generate Cursor Rules inside a productive chat and Cursor distills the conversation into a draft .mdc file. But don’t treat the output as finished – generated rules tend to be verbose, verbose rules cost tokens, and some generated instructions contradict each other. It’s a starting point, not a deployment artifact.
Next: open your project, count how many times this week you re-explained the same convention to Cursor. Each one is a one-line entry in a .cursor/rules/core.mdc file. Write them down before you forget.