If you have been using Cursor for more than a few days, you have already noticed the problem: each new chat starts blank. The AI does not know your stack, your naming conventions, your file structure, or your preferences. You end up re-explaining the same context over and over, "we use TypeScript, we prefer server components, always add error handling", and every session feels like briefing a contractor who just walked in the door.
Cursor rules solve this. They are persistent instructions that load automatically with every conversation, every autocomplete suggestion, and every agent task. Done well, they transform Cursor from a capable AI editor into something that feels purpose-built for your specific project.
This guide covers everything: the current .cursor/rules directory and .mdc format as of 2026, a step-by-step migration guide from the legacy .cursorrules file, the full .mdc frontmatter schema, the difference between rule types, the anatomy of a rule that actually works, 15 ready-to-use templates, the best community rule collections, rules for specific tools like Supabase and Stripe, how AGENTS.md fits in, how to organize rules for large projects, and the most common pitfalls.
Key Takeaways
- Cursor rules use the .cursor/rules directory with .mdc files, replacing the legacy single .cursorrules file for better scope control and token efficiency
- There are four rule activation modes: Always Apply, Auto Attached (globs), Agent Requested (description-based), and Manual (@rule-name), choosing the right one is critical for rules to fire when expected
- Keep always-apply rules under 200 words to avoid the "token tax", every token loads in every single request, consuming your context window budget
- The 15 ready-to-use templates cover the full stack: React components, API routes, Supabase, Stripe payments, Prisma, shadcn/ui, testing, security, and performance
- Commit your .cursor/rules directory to version control so the entire team shares the same AI behavior, coding standards, and output consistency
- Rules are not set-and-forget: evolve them with your project, if you explain the same thing to Cursor three times, it belongs in a rule
Learn this hands-on
Ready to ship a real production app, not just pick a model? Check out the Master Course: Build and Ship a Production-Ready App with Lovable and Cursor.
Why Cursor Rules Matter More Than Most Developers Realize
According to the 2025 Stack Overflow Developer Survey, 84% of developers now use or plan to use AI coding tools in their workflow, up from 76% the year before. But adoption alone does not equal productivity. The developers getting the most out of Cursor are not just using better prompts. They are building better context infrastructure, and cursor rules are the foundation of that.
Without rules, you spend a significant portion of your AI budget on re-establishing context. With well-crafted rules, that context is already present before you type a single word. The AI understands your project's architecture, your team's standards, the tools you are using, and the patterns you want to enforce. Every prompt starts from a position of shared understanding rather than a blank slate.
As Michael Truell, CEO & Co-founder at Cursor, explains: "We think the way developers will build software in the future is by describing intent, and the AI handles the implementation details."
Understanding the Current Format: .cursor/rules vs .cursorrules
There are two places cursor rules can live, and the distinction matters.
The Legacy .cursorrules File
The original approach was a single file named .cursorrules at the project root. Everything lived in one flat file: coding standards, framework conventions, architecture rules, testing preferences. It worked, and it still works today. If you have an existing .cursorrules file, Cursor continues to read it.
The limitation is that a single file has no scope control. Every rule loads for every conversation regardless of relevance. Writing a SQL migration? Your React component guidelines load too. This is wasteful on context tokens, what the Cursor community calls the "token tax", and makes rules harder to maintain as projects grow.
The Modern .cursor/rules Directory
The current recommended approach is the .cursor/rules directory with individual .mdc files. This is the format Cursor standardized on and the one their documentation now leads with.
The structure looks like this:
your-project/
āāā .cursor/
ā āāā rules/
ā āāā general-coding-standards.mdc
ā āāā react-components.mdc
ā āāā api-routes.mdc
ā āāā database-supabase.mdc
ā āāā testing.mdc
ā āāā security.mdc
āāā src/
āāā package.json
Each .mdc file is version-controlled, independently scoped, and loaded only when relevant. This is the format all new projects should use.
Migrating From .cursorrules to .cursor/rules: Step-by-Step Guide
If you searched ".cursorrules deprecated" and landed here, this section is for you. Here is the migration in full, including a before/after example.
Is .cursorrules Deprecated?
Yes. Cursor deprecated the single .cursorrules file in late 2024 (around version 0.43) in favor of Project Rules stored in .cursor/rules/. Cursor still reads an existing .cursorrules file today, so nothing breaks overnight. But the format is legacy: it receives no new features, and everything Cursor has shipped since (glob scoping, per-rule activation modes, agent-requested rules) only works with .mdc files in the new directory.
.cursorrules vs .cursor/rules: What Actually Changes
- One file vs many:
.cursorrulesis a single flat file..cursor/rules/holds one.mdcfile per concern. - Always loaded vs scoped:
.cursorrulesloads in full for every request..mdcfiles support four activation modes, so most rules only load when relevant. - No metadata vs frontmatter:
.cursorruleshas no configuration at all..mdcfiles carry a YAML frontmatter block (description,globs,alwaysApply) that controls activation. - Review and collaboration: separate
.mdcfiles produce clean, per-rule diffs in code review instead of one giant blob.
.md vs .mdc: Which Extension Should You Use?
Inside .cursor/rules/, use .mdc. The extension stands for "markdown with configuration": a standard markdown body plus the YAML frontmatter block that Cursor parses for activation. A plain .md file has no frontmatter and therefore no scope control. If you want frontmatter-free markdown instructions, that is exactly what AGENTS.md is for (covered later in this guide), not a .md file inside the rules directory.
Before and After: A Concrete Migration Example
Before, everything lived in one .cursorrules file at the project root:
# .cursorrules (legacy)
We use Next.js 15 with TypeScript and Tailwind.
Never use the any type.
React components: functional components only, named exports,
props interfaces named ComponentNameProps.
API routes: validate all request bodies with Zod,
check auth first, return { error, code } shapes.
After, the same content becomes three scoped .mdc files:
# .cursor/rules/project-context.mdc
---
alwaysApply: true
---
We use Next.js 15 with TypeScript and Tailwind.
Never use the any type.
# .cursor/rules/react-components.mdc
---
description: React component conventions
globs: src/components/**/*.tsx, app/**/*.tsx
alwaysApply: false
---
Functional components only, named exports,
props interfaces named ComponentNameProps.
# .cursor/rules/api-routes.mdc
---
description: API route conventions
globs: app/api/**/*.ts
alwaysApply: false
---
Validate all request bodies with Zod,
check auth first, return { error, code } shapes.
The project context loads everywhere. The component and API rules only load when you touch matching files. Same instructions, a fraction of the token cost per request.
The Migration in Four Steps
- Create the directory: make
.cursor/rules/at the project root, or open the command palette and search for "New Cursor Rule" to have Cursor scaffold a rule file for you. - Split by concern: move each logical block of your
.cursorrulesinto its own.mdcfile (project context, components, API, testing, and so on). - Set activation per rule: give your project context
alwaysApply: true, addglobsto file-scoped rules, and add adescriptionto task-scoped rules. - Verify, then delete: run a few sessions to confirm the new rules fire, then remove
.cursorrulesso the same instructions are not loaded twice.
The Anatomy of a .mdc Rule File
Every .mdc file has two parts: a YAML frontmatter block that controls when the rule activates, and a markdown body that contains the actual instructions.
---
description: Rules for React component development
globs: ["src/components/**/*.tsx", "src/components/**/*.ts"]
alwaysApply: false
---
# React Component Rules
Always use functional components with TypeScript interfaces.
Never use default exports, use named exports only.
The frontmatter fields control everything:
description: A plain-language summary of when this rule should be used. This is what the agent reads to decide whether to include the rule when it has been set to agent-requested mode.
globs: File path patterns that trigger automatic rule attachment. When you open or edit a file matching these patterns, the rule loads automatically.
alwaysApply: When set to true, the rule loads for every single conversation regardless of context. Use sparingly, this is your global config, not your per-feature config.
The .mdc Frontmatter Schema: alwaysApply, globs, and description Reference
This is the complete reference for the three frontmatter fields, verified against Cursor's official documentation. All three are optional: a .mdc file with an empty frontmatter block (or none of these fields set) is a valid manual rule.
| Field | Type | Default | Effect |
|---|---|---|---|
alwaysApply | boolean | false | true injects the rule into every request |
globs | string (comma-separated glob patterns) | omitted | Auto-attaches the rule when a matching file is in context |
description | string | omitted | Lets the agent decide when to load the rule based on relevance |
alwaysApply: Type, Default, and Example Values
alwaysApply is a boolean and defaults to false. Set it to true for the handful of rules that genuinely apply to every request:
---
alwaysApply: true
---
There are only two valid values, true and false. If the field is missing, Cursor treats it as false. Anything set to true pays the token tax on every single request, so keep those rules terse. Cursor's own docs recommend keeping rules under 500 lines, and always-apply rules should sit far below that.
globs: Type, Format, and Example Values
globs takes file path patterns. In Cursor's official documentation the format is a comma-separated string, not a YAML list:
---
globs: src/**/*.tsx, docs/**/*.md, docs/**/*.mdx
alwaysApply: false
---
Pattern behavior follows standard glob rules:
*.tsmatches.tsfiles in the project root onlysrc/**/*.tsxmatches.tsxfiles anywhere undersrc/, recursively**on its own matches any number of directories
You will also see the YAML array form (globs: ["src/**/*.tsx"]) in community rule collections, and current Cursor builds generally accept it. But the comma-separated string is the documented format, so if a rule refuses to auto-attach, converting the globs to the string form is the first fix to try.
description: Type, Default, and Example Values
description is a free-text string that tells the agent when the rule is relevant. It is what powers agent-requested rules: no globs, just a description the model reads to decide whether to pull the rule in.
---
description: Use when creating or modifying Stripe payment flows, webhooks, or subscription logic
alwaysApply: false
---
Write it like an instruction to a colleague. Concrete triggers ("when modifying webhook handlers") outperform vague ones ("payment stuff"). If the field is omitted and there are no globs and no alwaysApply: true, the rule becomes manual-only.
How the Three Fields Combine Into Rule Types
The four activation modes described in the next section are just combinations of these fields. Cursor's current UI labels them Always Apply, Apply Intelligently (description only), Apply to Specific Files (globs), and Apply Manually (none of the three):
| Frontmatter combination | Rule type |
|---|---|
alwaysApply: true | Always Apply |
description set, no globs | Apply Intelligently (agent requested) |
globs set | Apply to Specific Files (auto attached) |
| None of the three | Apply Manually (via @rule-name) |
The Four Rule Activation Modes
This is where most developers get confused. Cursor rules have four distinct behaviors, and choosing the wrong one is the most common cause of rules not firing when expected.
1. Always Apply
alwaysApply: true
The rule loads in every conversation without exception. Use this for foundational project context: what tech stack you are using, what the project does, team-wide standards that apply everywhere. Keep always-apply rules short, every token they consume is consumed in every single request.
Best for: Project context, universal coding standards, language/framework version pinning.
2. Auto Attached
alwaysApply: false
globs: ["src/api/**/*.ts"]
The rule loads automatically when files matching the glob patterns are in context. When you are working in src/api/, your API rules are present. When you move to src/components/, they are not. This is the most efficient mode for domain-specific rules.
Best for: Component libraries, API routes, database files, test files, anything with clear file boundaries.
3. Agent Requested
description: "Use when creating or modifying Stripe payment flows, webhooks, or subscription logic"
alwaysApply: false
No globs. A description only. The agent reads the description and decides whether the rule is relevant to the current task. If you ask Cursor to "add a Stripe checkout flow," it reads the description, recognizes the relevance, and loads the rule.
Best for: Tool-specific rules (Stripe, SendGrid, Twilio), workflow rules, rules for tasks that cut across multiple file types.
4. Manual
No description, no globs, no alwaysApply. The rule is only included when you explicitly reference it using @rule-name in your prompt.
Best for: Reference rules you only need occasionally, rules for rare tasks, documentation-style rules.
Rule Length: The Token Tax Problem
Every rule token is included in every request that activates that rule. A 500-word always-apply rule might cost you 700 tokens before you have typed a single character. Across hundreds of daily requests, that compounds fast.
The practical guidelines:
- Always-apply rules: Keep under 200 words. This is your elevator pitch about the project.
- Auto-attached rules: 200-500 words is reasonable. These are scoped, so the cost is bounded.
- Agent-requested rules: Can be longer (500-800 words) since they only load when explicitly relevant.
- Manual rules: No strict limit, they are on-demand.
The instinct is to write comprehensive rules. The effective approach is to write precise ones. Ten focused rules outperform one sprawling document.
15 Ready-to-Use Cursor Rule Templates
1. Project Foundation (Always Apply)
---
description: Core project context
alwaysApply: true
---
This is a Next.js 15 SaaS application using TypeScript, Tailwind CSS, Supabase for auth and database, and Stripe for payments.
Always use TypeScript. Never use `any` type, use `unknown` with type guards.
Prefer server components unless client-side interactivity is required.
All database access goes through the /lib/db directory.
Environment variables are validated at startup in /lib/env.ts.
2. React Components (Auto Attached)
---
description: React component development standards
globs: ["src/components/**/*.tsx", "app/**/*.tsx"]
alwaysApply: false
---
Use functional components with TypeScript interfaces.
Use named exports only, no default exports.
Props interface naming: ComponentNameProps.
Use shadcn/ui components from /components/ui before building custom ones.
Install new shadcn components with: npx shadcn@latest add [component-name]
Avoid inline styles, use Tailwind utility classes exclusively.
Keep components under 150 lines. Extract sub-components when they grow.
3. Tailwind CSS Standards (Auto Attached)
---
description: Tailwind CSS styling conventions
globs: ["**/*.tsx", "**/*.jsx"]
alwaysApply: false
---
Use Tailwind utility classes, never inline styles or external CSS files.
Follow mobile-first responsive design: base ā sm ā md ā lg ā xl.
Use the cn() utility from /lib/utils for conditional classes.
Color usage: primary actions use the brand color tokens, not arbitrary hex values.
Spacing follows the 4px grid: use p-4, gap-6, mt-8, not arbitrary values.
4. API Routes (Auto Attached)
---
description: API route development standards
globs: ["app/api/**/*.ts", "pages/api/**/*.ts"]
alwaysApply: false
---
Every API route must validate the request body using Zod before processing.
Authentication check must be the first operation in every protected route.
Return consistent error shapes: { error: string, code: string }.
Use HTTP status codes correctly: 400 for validation, 401 for auth, 403 for authorization, 500 for server errors.
Never log sensitive data (passwords, tokens, full request bodies).
Rate limiting is handled by the middleware in /middleware.ts.
5. Testing Standards (Auto Attached)
---
description: Testing guidelines and conventions
globs: ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"]
alwaysApply: false
---
Use Vitest for unit tests, React Testing Library for component tests.
Test behavior, not implementation. Test what a user sees and does.
Each test file covers exactly one module or component.
Use descriptive test names: "returns 401 when user is not authenticated".
Mock external dependencies (APIs, databases) in all unit tests.
Aim for 80% coverage on critical paths: auth, payments, data mutations.
6. Security Rules (Auto Attached)
---
description: Security standards for all code
globs: ["app/api/**/*.ts", "lib/**/*.ts"]
alwaysApply: false
---
Never hardcode secrets, API keys, or credentials.
Always validate and sanitize user input before processing.
Use parameterized queries, never string-interpolate SQL.
Authentication tokens must be stored in httpOnly cookies, never localStorage.
Always check authorization (ownership/permissions), not just authentication.
Sanitize any data that will be rendered as HTML to prevent XSS.
7. Supabase Database (Auto Attached)
Related Course on Vibe Coding Academy
---
description: Supabase client usage and database patterns
globs: ["lib/db/**/*.ts", "lib/supabase/**/*.ts", "app/api/**/*.ts"]
alwaysApply: false
---
Use the Supabase server client for all server-side operations (never the browser client on the server).
Import the server client from /lib/supabase/server.ts.
Row Level Security is enabled on all tables. Never bypass RLS with the service role key unless explicitly required for admin operations.
Always handle the { data, error } response pattern, never destructure without checking error.
Use Supabase Storage for file uploads, not local disk.
Database migrations live in /supabase/migrations and must be reviewed before applying to production.
8. Stripe Payments (Agent Requested)
Related Course on Vibe Coding Academy

---
description: Use when creating or modifying Stripe checkout flows, webhooks, subscriptions, or payment logic
alwaysApply: false
---
Use the Stripe Node.js SDK, never raw fetch calls to the Stripe API.
Webhook endpoints must verify the Stripe signature using stripe.webhooks.constructEvent().
Never store full card data. Store only the Stripe customer ID and subscription ID.
Always test with Stripe test mode keys in development (sk_test_...).
Idempotency keys are required for payment creation requests.
Handle these webhook events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed.
Subscription status is the source of truth for feature access, check it on every protected request.
9. Prisma ORM (Auto Attached)
---
description: Prisma ORM patterns and conventions
globs: ["lib/prisma/**/*.ts", "prisma/**/*.ts", "app/api/**/*.ts"]
alwaysApply: false
---
Use the singleton Prisma client from /lib/prisma/client.ts.
Always use transactions for operations that modify multiple tables.
Use select to limit returned fields, never return full records when partial data is sufficient.
Prisma schema changes require a migration: npx prisma migrate dev.
Never run prisma migrate deploy in development, only in CI/CD.
Use Prisma's built-in pagination: take/skip for offset, cursor for cursor-based.
10. shadcn/ui Components (Agent Requested)
---
description: Use when adding, modifying, or composing shadcn/ui components
alwaysApply: false
---
Install components with npx shadcn@latest add [component-name], never copy-paste manually.
shadcn components live in /components/ui, never modify them directly.
Extend shadcn components by wrapping them in a new component in /components.
Use the Dialog component for modals, Sheet for sidepanels, Popover for inline overlays.
Form validation uses React Hook Form + Zod with the shadcn Form component.
Toast notifications use the Sonner integration, not the legacy Toast component.
11. Error Handling (Always Apply)
---
description: Error handling and logging conventions
alwaysApply: true
---
All async operations must use try/catch. No unhandled promise rejections.
User-facing errors must be human-readable, never raw error messages or stack traces.
Log errors server-side with context: user ID, route, timestamp.
Use the AppError class from /lib/errors.ts for structured error throwing.
The global error boundary in /app/error.tsx handles uncaught client errors.
12. TypeScript Strict Mode (Auto Attached)
---
description: TypeScript conventions and strict mode rules
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---
TypeScript strict mode is enabled. Honor it, no ts-ignore without explanation.
Use unknown over any. Narrow types with type guards before using them.
Define shared types and interfaces in /types, import from there, never redefine.
Prefer type unions over enums for simple string variants.
Use satisfies operator to validate against a type without widening it.
Generic function parameters should be named T, U for single-letter cases, or descriptive names for complex signatures.
13. Vibe Coding Workflow (Agent Requested)
---
description: Use when building new features end-to-end from prompt to deployment
alwaysApply: false
---
When building a new feature: schema first, then API, then UI.
Always generate the Supabase migration before writing any application code that depends on it.
Create a feature branch before starting. Commit at each working milestone.
Write the happy path first. Add error states and edge cases in a second pass.
Before calling a feature done: it renders without console errors, the API returns correct status codes, and auth protection is verified.
14. Code Review Checklist (Manual)
---
description: Pre-commit code review checklist
alwaysApply: false
---
Before committing, verify:
- No hardcoded secrets or API keys
- No console.log statements left in production paths
- TypeScript compiles with zero errors
- All new API routes have input validation
- Database queries use proper error handling
- Any new environment variables are documented in .env.example
- Component props are fully typed
15. Performance Standards (Auto Attached)
---
description: Performance optimization rules
globs: ["app/**/*.tsx", "src/**/*.tsx"]
alwaysApply: false
---
Images must use the Next.js Image component with explicit width/height.
Avoid importing entire libraries when named imports are available.
Use React.memo() for components that receive the same props frequently.
Lazy load below-the-fold components with next/dynamic.
Database queries must include LIMIT clauses, never fetch unbounded lists.
Client components must not trigger waterfalls: fetch data in server components and pass as props.
Best Cursor Rules Examples: A Curated Gallery
The 15 templates above cover a modern TypeScript full-stack setup. If your stack is different, or you want to see how other teams write rules, there is a large ecosystem of community collections worth mining.
Where to Find Community Cursor Rules
- awesome-cursorrules (PatrickJS): the largest and best-known collection, with hundreds of rules organized by framework and language. One caveat: many entries still use the legacy single-file
.cursorrulesformat, so treat them as raw material to split into scoped.mdcfiles rather than something to paste in wholesale. - cursor.directory: a browsable, searchable directory of community rules by stack, useful for quickly comparing how different people write rules for the same framework.
- awesome-cursor-rules-mdc (sanjeed5): community rules already converted to the modern
.mdcformat with frontmatter, which saves you the migration step.
What Separates a Great Rule From a Mediocre One
Before copying anything, filter with these criteria:
- Specific over generic: "Props interfaces are named ComponentNameProps" beats "write clean, typed components". If the AI would have done it anyway, the line is wasted tokens.
- Scoped, not global: great examples use
globsor adescriptionso they only load when relevant. A 600-line always-on rule is a red flag, however good its content. - Project decisions, not language tutorials: the AI already knows what TypeScript is. Rules should encode the choices it cannot guess: your file layout, your naming, your error shape, your forbidden patterns.
- Short enough to maintain: if you would not reread it in a code review, the model's attention will drift over it too.
Example: Python + FastAPI Rule
---
description: FastAPI endpoint and service conventions
globs: app/**/*.py
alwaysApply: false
---
Use FastAPI with Pydantic v2 models for all request and response schemas.
Every endpoint declares an explicit response_model.
Use async def for all route handlers and database calls.
Dependency injection via Depends() for db sessions and auth, never module-level globals.
Raise HTTPException with explicit status codes, never return error dicts.
Business logic lives in app/services/, route handlers stay thin.
Example: Vue 3 + TypeScript Rule
---
description: Vue 3 component conventions
globs: src/**/*.vue
alwaysApply: false
---
Use the Composition API with <script setup lang="ts">, never the Options API.
Define props with defineProps<Props>() using a typed interface.
Use Pinia for shared state, composables in src/composables/ for reusable logic.
Component files are PascalCase and single-responsibility.
Emit events typed with defineEmits, no untyped $emit calls.
Example: Git Commit Conventions Rule (Agent Requested)
---
description: Use when writing commit messages or preparing a commit
alwaysApply: false
---
Follow Conventional Commits: type(scope): summary.
Allowed types: feat, fix, chore, refactor, docs, test.
Summary in imperative mood, lowercase, no trailing period, under 72 characters.
One logical change per commit, never mix refactors with features.
These three, plus the 15 templates above, cover the most common request patterns. For anything more exotic, the collections linked at the top of this section almost certainly have a starting point you can adapt.
Organizing Rules in Large Projects
When a project grows past a handful of rules, organization becomes the challenge.
A folder structure that works well:
.cursor/rules/
āāā core/
ā āāā project-context.mdc # always apply
ā āāā typescript-standards.mdc # always apply
āāā frontend/
ā āāā react-components.mdc
ā āāā tailwind.mdc
ā āāā performance.mdc
āāā backend/
ā āāā api-routes.mdc
ā āāā security.mdc
ā āāā error-handling.mdc
āāā tools/
ā āāā supabase.mdc
ā āāā stripe.mdc
ā āāā prisma.mdc
ā āāā shadcn.mdc
āāā workflow/
āāā testing.mdc
āāā vibe-coding.mdc
āāā code-review.mdc
Cursor reads all .mdc files recursively from .cursor/rules/, so subdirectory organization is for your benefit, not Cursor's. Name files clearly, you will reference them by name when using manual rules.
For teams, commit the .cursor/rules/ directory to your repository. This is one of the most underused practices in collaborative vibe coding: shared rules mean shared AI behavior. Every developer on the team gets the same context, the same standards, the same output consistency.
AGENTS.md vs .cursor/rules: Which One Should You Use?
Cursor also supports AGENTS.md, and it is worth understanding where it fits before you decide how to structure your project instructions.
AGENTS.md is a plain markdown file with no frontmatter and no configuration. You drop it at the project root, write your instructions, and Cursor reads it. Cursor also supports nested AGENTS.md files: place one in any subdirectory and it applies automatically when you work with files in that directory or its children. It is an emerging cross-tool standard, so the same file can serve Cursor and other AI coding agents that have adopted it.
The trade-off is control:
- Choose
AGENTS.mdwhen you want simple, portable instructions with zero configuration, especially if your team uses multiple AI coding tools and you want one source of truth. Nesting gives you rough directory-level scoping for free. - Choose
.cursor/ruleswhen you need real activation control: glob-scoped rules, agent-requested rules with descriptions, manual rules, and per-rule token budgeting. None of that exists inAGENTS.md.
They also coexist fine: many teams keep a lean AGENTS.md for cross-tool project context and use .cursor/rules/ for the Cursor-specific, scoped rule set. For how rules fit into a broader Cursor workflow (models, context management, and prompting habits), see our Cursor AI best practices guide.
Common Pitfalls and How to Debug Them
Rules not firing when expected. The most common cause is glob pattern misconfiguration. Cursor's glob syntax is strict. Test your patterns against actual file paths. src/**/*.tsx matches files in subdirectories; src/*.tsx only matches files directly in src/.
Conflicting rules. If two rules give contradictory instructions, one says "use default exports," another says "never use default exports", Cursor will follow the most recently loaded rule or produce inconsistent results. Audit for contradictions when adding new rules.
Always-apply rules killing context window. If Cursor feels slow or you are hitting context limits, look at your always-apply rules first. A 1,000-word always-apply rule is expensive. Trim aggressively, or convert it to auto-attached with appropriate globs.
Agent not picking up agent-requested rules. The description must clearly describe the use case. "Stripe payment flows" is actionable. "Use for payment stuff" is not. Write descriptions as if explaining to a human when to use the rule.
Migrating from .cursorrules. You do not need to delete your .cursorrules file immediately, Cursor still reads it. Migrate incrementally: move sections to .mdc files one at a time, verifying behavior as you go, then remove the old file once everything is in the new format.
Next Steps
Cursor rules are not a set-and-forget feature. The best rule sets evolve with the project. When you find yourself re-explaining the same thing to Cursor three times, that is a signal it belongs in a rule. When a rule has not fired in weeks, it might be time to remove it.
The 15 templates above give you a working foundation for a modern full-stack project. Start with the always-apply project context rule and one or two auto-attached rules for your primary file types. Add from there as you notice gaps.
If you want to see cursor rules applied in a real end-to-end vibe coding workflow, from initial scaffolding to authentication, payments, and deployment, the Master Course walks through the complete process with real projects. The practical gap between "I know how cursor rules work" and "I have a production-quality rule system for my project" closes fast when you see it applied in context.
Related Course on Vibe Coding Academy
Building with Cursor and want to go further? Explore the full vibe coding curriculum at vibecodingacademy.ai.
