Last updated: August 2026 · Covers Cursor 0.47+
Cursor Rules are project-level instructions that tell Cursor AI exactly how to write code, structure files, handle errors, and behave across every task in your project. Without them, Cursor falls back to generic model defaults — with them, every suggestion automatically follows your team's stack, conventions, and workflow preferences.
Cursor currently has two rule formats, and this matters more than it sounds: the legacy .cursorrules single file, and the current .cursor/rules/*.mdc system. This guide leads with the current format, explains exactly why the legacy format silently breaks in Agent mode, and gives you a migration path if you're still on the old one.
.cursor/rules/*.mdc — the current formatIntroduced to replace the single-file system, .mdc (Markdown with Cursor metadata) files live in a .cursor/rules/ directory and support YAML frontmatter that controls when and how each rule activates — something the legacy format cannot do at all.
.cursorrules — the legacy formatA single flat file at your project root. It has no scoping, no activation logic, and loads unconditionally into every request — which was fine when it was the only option, but is now a real limitation.
The critical gotcha: .cursorrules is silently ignored in Cursor's Agent mode. Agent mode uses a different context-loading path than Chat and Composer, and the legacy file is not part of it. If your team has adopted Agent mode for refactoring, feature implementation, or autonomous multi-step tasks — which is now the default way most developers use Cursor — a .cursorrules-only project is providing zero guidance during those sessions, with no warning that this is happening.
You do not need to delete an existing .cursorrules file immediately — it still loads in Chat and Composer for backward compatibility. But for any project where Agent mode is used regularly, migrating to .mdc is not optional if you want rules to actually apply. For the full diagnostic and fix, see Cursor Rules Not Working.
For any new project in 2026, start with .mdc directly — there is no reason to begin with a format that will need migrating.
.mdc Format: Structure and Activation Modesmy-project/
├── .cursor/
│ └── rules/
│ ├── 01-core.mdc
│ ├── 02-typescript.mdc
│ └── 03-testing.mdc
├── package.json
└── src/
Files are loaded in lexicographical order — numeric prefixes let you control which rules Cursor "sees" first.
Each .mdc file has a YAML frontmatter block with three fields:
---
description: Conventions for the API layer
globs: "src/api/**/*.ts"
alwaysApply: false
---
# API conventions
- All handlers validate input with Zod before processing.
- Return NextResponse.json() with an explicit status code.
description — a summary Cursor uses to decide relevance when the rule isn't force-loadedglobs — file path patterns that trigger auto-loading when matching files are in contextalwaysApply — boolean; true loads the rule into every single request regardless of contextThese three fields combine into four distinct behaviors:
| Mode | Configuration | When it loads |
|---|---|---|
| Always | alwaysApply: true |
Every request, no exceptions |
| Auto-attach | alwaysApply: false + globs set |
Only when the agent is editing a matching file |
| Agent-decided | alwaysApply: false + description, no globs |
The agent reads the description and decides if it's relevant |
| Manual | No globs, no alwaysApply |
Only when explicitly referenced with @ruleName in chat |
Use Always sparingly — for the 3–5 rules that are genuinely universal to the project (stack, language version, absolute constraints). Use Auto-attach for anything file-type or directory specific (React component conventions, API route conventions, test conventions). Use Agent-decided for rules that apply situationally in a way a glob can't capture (a security review checklist that should trigger when auth code is touched). Use Manual for reference material you want available but don't want consuming context by default.
async/await instead of .then() chains." not "Handle async properly."---
description: Core project identity — always loaded
alwaysApply: true
---
# Project Rules
## Language and environment
- TypeScript strict mode throughout the project.
- Node.js 20+. Use ES modules (`import`), not CommonJS (`require()`).
## File structure
- New components go in `src/components/`.
- Each component gets its own folder: `src/components/Button/Button.tsx` + `Button.test.tsx`.
## Code style
- Functional components only. No class components.
- Named exports for all components and utilities.
- No `any` types. Use `unknown` and narrow it.
## Task behaviour
- Before implementing, write a 3-step plan in a comment block.
- Run `npm test` after every implementation.
- If requirements are ambiguous, ask one clarifying question before starting.
.mdc TemplatesEach template below is split into multiple .mdc files by concern — this is the current recommended pattern, replacing the old single-file approach.
01-core.mdc (Always)
---
description: Project identity and stack
alwaysApply: true
---
# Next.js / TypeScript / Prisma
Next.js 14 App Router. TypeScript strict mode. PostgreSQL via Prisma.
Styling: Tailwind CSS only. Testing: Vitest + React Testing Library.
All routes in `app/`. Never use `pages/`.
02-components.mdc (Auto-attach)
---
description: React component conventions
globs: "src/components/**/*.tsx"
alwaysApply: false
---
- Functional components only. Named exports.
- No `any` type — use `unknown` and narrow it.
- Server components by default; add `'use client'` only when required.
03-data-access.mdc (Auto-attach)
---
description: Prisma and API conventions
globs: ["src/services/**/*.ts", "app/api/**/*.ts"]
alwaysApply: false
---
- All Prisma queries go through service functions in `src/services/`.
- Service functions return `{ data: T } | { error: string }`.
- Never call `prisma` directly inside a component, page, or route handler.
- API success: `{ success: true, data: T }`. API error: `{ success: false, error: string }`.
01-core.mdc (Always)
---
description: Project stack
alwaysApply: true
---
React 18, TypeScript strict, Vite. State: Zustand (client) + React Query (server).
Styling: Tailwind CSS only. No inline styles, no CSS Modules.
02-state.mdc (Auto-attach)
---
description: State management conventions
globs: ["src/stores/**/*.ts", "src/hooks/**/*.ts"]
alwaysApply: false
---
- Zustand stores in `src/stores/`, one store per domain.
- Server state via React Query only — never duplicate in Zustand.
- No `useEffect` for data fetching — use React Query.
- Zustand actions defined inside the store, not as standalone functions.
01-core.mdc (Always)
---
description: Project stack
alwaysApply: true
---
Python 3.12+, type hints everywhere. FastAPI + SQLAlchemy 2.0 async.
Package manager: Poetry. Testing: pytest + pytest-asyncio.
02-api.mdc (Auto-attach)
---
description: API and service layer conventions
globs: ["app/routers/**/*.py", "app/services/**/*.py"]
alwaysApply: false
---
- `async def` for all route handlers and service functions.
- Pydantic models for all request/response bodies — never return raw dicts.
- Business logic in `app/services/`, keep route handlers thin.
- DB queries in `app/repositories/` — no direct ORM queries in services.
- Plural nouns for resource paths: `/users`, not `/user`. Version prefix `/api/v1/`.
01-core.mdc (Always)
---
description: Project stack
alwaysApply: true
---
Go 1.22+. Gin web framework. `pgx` for PostgreSQL, no ORM.
Testing: standard `testing` package + `testify`.
02-backend.mdc (Auto-attach)
---
description: Handler, service, repository conventions
globs: "internal/**/*.go"
alwaysApply: false
---
- Errors always returned, never panicked on (except main.go init).
- `context.Context` as first parameter in all service and repository functions.
- Return `(T, error)` from service and repository functions.
- Handlers translate errors to HTTP status — services never set status codes.
- Every exported function has a godoc comment.
01-core.mdc (Always)
---
description: Project stack
alwaysApply: true
---
Node.js 20+, TypeScript 5+, Express 4. PostgreSQL via `pg`, raw SQL — no ORM.
Testing: Jest + Supertest.
02-database.mdc (Auto-attach)
---
description: Database access rules
globs: "src/db/**/*.ts"
alwaysApply: false
---
- All SQL in `src/db/queries/` — never inline in services.
- Always use parameterized queries: `db.query('SELECT * FROM users WHERE id = $1', [id])`.
- Never concatenate user input into SQL strings.
- Wrap multi-step operations in transactions.
.cursorrules to .mdcYou do not need to do this in one sitting. The recommended path:
.cursor/rules/ and add one .mdc file — start with your most critical, universal rules as 01-core.mdc with alwaysApply: true..cursorrules into scoped .mdc files as you touch that part of the codebase, verifying behavior each time..cursorrules in place during the transition — it still loads in Chat and Composer, so nothing breaks while you migrate..cursorrules, that's expected — it confirms why the migration matters..cursorrules once everything is moved — having both creates undefined precedence behavior; see Cursor Rules Not Working for specifics.Useful starting points rather than copy-paste sources — treat community rules as raw material to adapt, not finished configuration:
.mdc files rather than pasting in wholesale..mdc format with frontmatter, which saves the migration step.Filter anything you copy for specificity: a rule like "Props interfaces are named ComponentNameProps" is worth keeping; "write clean, typed components" is not — if the model would do it anyway, the line just costs tokens.
| Mechanism | What it is | Persists | Loads in Agent mode | Best for |
|---|---|---|---|---|
.cursor/rules/*.mdc |
Project-level, scoped instructions | Yes | Yes | Architecture, stack conventions, naming, workflow rules |
.cursorrules (legacy) |
Project-level, unscoped instructions | Yes | No | Backward compatibility only — do not use for new projects |
| Global rules (Settings → Rules for AI) | Personal developer defaults | Yes | Yes | Personal preferences, agent behaviour, communication style |
@file or @folder mentions |
Files referenced in a specific request | No — per-request only | Yes | Task-specific context: a spec doc, a schema |
| In-request instructions | Instructions given directly in the chat | No — one request only | Yes | One-off overrides |
Decision rule:
.mdc rule, scoped appropriately@file referenceFor the distinction between rules (how code should look) and system-prompt-level agent behavior (how the agent should act when uncertain), see System Prompts for AI Coding Agents.
| Anti-pattern | Example | Problem | Better alternative |
|---|---|---|---|
Starting a new project on .cursorrules |
Creating .cursorrules for a project that will use Agent mode |
Silently provides zero guidance in Agent mode | Start with .mdc directly |
| Vague instruction | "Write clean code." | Cursor cannot operationalize "clean" | "Functions must not exceed 40 lines. Max 3 levels of nesting." |
| Restating the obvious | "Use good variable names." | Wastes token budget | Remove it |
Overusing alwaysApply: true |
10+ rules all marked always-apply | Degrades attention on all of them; see token budget below | Reserve Always for 3–5 genuinely universal rules |
Both .cursorrules and .mdc present |
Migrating without removing the old file | Undefined precedence between the two | Complete the migration, then delete .cursorrules |
| Negative-only rules | "Don't use Redux. Don't use class components." | Cursor needs to know what to do, not just what to avoid | "Use Zustand. Use functional components." |
Every .mdc file that loads for a given request is included in that request's context. The current practical guidance:
.mdc file.alwaysApply: true content should stay under roughly 2,000–3,000 tokens total — beyond this, the model's attention on rules that load later in the combined content measurably degrades, causing it to skip constraints.To stay within budget without losing coverage:
alwaysApply: true reserved for genuinely universal, short rules — push everything else to Auto-attach or Agent-decidedsrc/services/userService.ts"Is .cursorrules completely dead?
No — it still loads in Chat and Composer for backward compatibility. But it is silently ignored in Agent mode, which is how most developers use Cursor for substantive work in 2026. Treat it as legacy: fine to leave in place temporarily during migration, not something to start a new project with.
Should I commit .cursor/rules/ to git?
Yes, in almost all cases. It encodes project conventions that every contributor (human and AI) should follow. Treat it like .eslintrc — part of your project's quality infrastructure.
What's the maximum size for a rule file?
No hard cap, but keep individual .mdc files under 500 lines and combined always-apply content under roughly 2,000–3,000 tokens for reliable adherence. Split large rule sets into focused, scoped files rather than one large one.
Do workspace rules override global Rules for AI?
Yes. Workspace .mdc rules take priority over global settings when they conflict. Global rules are your personal defaults; workspace rules are project-specific and win.
Can I write rules in a language other than English?
Yes. Cursor understands rules in any language the underlying model supports. English tends to produce the most consistent results for technical content.
How do I override a rule for a single task?
Give the override directly in your request: "For this task only, use a class component instead of a functional one." In-request instructions take precedence over persistent rules for that single interaction. See How to Prompt AI Coding Agents for more on structuring effective one-off task instructions.
My rules aren't working — where do I start debugging?
See the dedicated Cursor Rules Not Working troubleshooting guide, or the faster Why Cursor Ignores .cursorrules checklist for a quick diagnostic pass.
.github/copilot-instructions.md setup