Cursor Rules

Cursor Rules are persistent instructions that live in your codebase and shape AI behavior for every interaction. How to write them, when to auto-attach them, and where to find good starting points.

March 30, 20265 min read3 / 6

Without rules, every AI interaction starts from zero. The AI doesn't know your preferred patterns, your naming conventions, or which libraries your project uses. You explain it in every prompt and it forgets the next session.

Cursor Rules fix this. They're persistent instructions — stored in your project or globally on your machine — that get included automatically in AI interactions.

Two Levels of Rules

Project Rules

Project-level rules live in your repository and apply to everyone on the team.

How to create them:

  • Cursor Settings → Rules → "Add Rule"
  • Or create a .cursorrules file in your project root
  • Or use the newer format: .cursor/rules/ directory with individual .mdc files

What to put here:

  • The tech stack with specific versions
  • Your naming conventions
  • Import patterns you enforce
  • Patterns you want avoided
  • Testing approach

Example project rules file:

Plain text
You are working on a Next.js 15 TypeScript application. Tech stack: - Next.js 15.1 (App Router — not Pages Router) - TypeScript 5.4 (strict mode enabled) - Tailwind CSS for all styling - Zustand for global state - Tanstack Query for server state - Vitest + React Testing Library for tests - Zod for runtime validation Conventions: - Components: PascalCase, one per file, in src/components/ - Hooks: camelCase, prefixed with "use", in src/hooks/ - All imports use the "@/" alias (never relative "../") - Use "import type" for type-only imports - Server components by default; add "use client" only when needed Must avoid: - var (use const/let) - any types (use unknown or proper types) - Class components - Inline styles (use Tailwind) - console.log in committed code (use the logger at src/lib/logger.ts) - default exports except for Next.js pages and layouts

This file gets committed to git. Every team member, every AI interaction, inherits it.

User Rules (Global)

User-level rules apply to all projects on your machine. Good for personal preferences that span all work.

How to access: Cursor Settings → Rules → User Rules

Example user rules:

Plain text
Keep explanations concise. Prefer code over prose. When writing functions, use early returns instead of deeply nested conditions. Always use explicit TypeScript return types on function declarations. When I ask you to explain something, lead with a one-sentence summary, then the detail. Never add comments to code unless the logic isn't self-evident.

These preferences get applied across every project, without repeating them per codebase.

Auto-Attach Rules

Regular rules are always included. Auto-attach rules are conditional — they activate only when specific file patterns are in context.

This keeps context lean. The AI only receives rules relevant to what it's currently working on.

How to create an auto-attach rule:

In Cursor's rules UI, specify the "Apply to" file glob pattern when creating a rule.

Example: testing conventions that only apply to test files:

Plain text
Apply to: **/*.test.ts, **/*.spec.ts, **/*.test.tsx When writing tests: - Use describe() blocks to group related tests - Prefer it() over test() - One assertion per test where possible - Mock at the module level with vi.mock(), not inside individual tests - Use userEvent over fireEvent for interaction tests - Always clean up timers and subscriptions with afterEach

When you reference a .test.ts file in your conversation, this rule activates. When you're working on a component, it doesn't.

Other useful auto-attach patterns:

Plain text
API routes: src/app/api/**/*.ts Server components: src/app/**/page.tsx Database layer: src/lib/db/**/*.ts, src/models/**/*.ts Configuration files: *.config.ts, *.config.js Migration files: migrations/**/*.sql

cursor.directory: Pre-Built Rules for Your Framework

Writing rules from scratch is slow. The community has already done much of this work.

cursor.directory is a community-maintained library of Cursor rules for common frameworks and use cases. Browse by framework — React, Next.js, Vue, Svelte, FastAPI, Django, and many more.

How to use it:

  1. Find a rule set that matches your tech stack
  2. Read it — don't just copy it blindly
  3. Edit it to match your specific conventions
  4. Add your "must avoid" patterns based on your project's history

A good framework rule is a starting point, not a final answer. The community rule for Next.js will get you 80% there; the remaining 20% is specific to your team's decisions.

What Makes a Good Rule

Good rules are:

  • Specific: "Use Zod for all runtime validation at API boundaries"
  • Actionable: "Import types separately with import type"
  • Based on real patterns in your codebase

Bad rules are:

  • Vague: "Write good code"
  • Contradictory: conflicting rules cancel each other (and confuse the AI)
  • Too long: the AI loses track of rules buried in a wall of text

Structure that works:

Plain text
[Brief context: what this project is and who it's for] Stack: - [Technology choices with versions] Conventions: - [Naming patterns] - [File structure rules] - [Import patterns] Must avoid: - [Anti-patterns specific to this project]

Keep it scannable. If you wouldn't read all of it, the AI won't either.

Debugging Rules That Aren't Working

If the AI keeps ignoring your rules:

  1. Check for conflicts — do your project rules and user rules say opposite things? Conflicts cause the AI to pick one arbitrarily.

  2. Is the rule too long? — trim it. Test which rules are actually being followed by asking: "What are the conventions for this project according to the rules you have?"

  3. Check if it's loaded — in the Cursor chat panel, you can see which rules are active in the context panel at the bottom.

  4. Be more explicit — "Import types with import type" is clearer than "use proper TypeScript patterns."

The Compounding Return

Rules are the foundation of consistent AI behavior. An AI coding session without rules is like a new contractor who doesn't know how your team works. Rules are the onboarding documentation — written once, applied every time.

The return compounds: each good rule you write prevents the same mistake from appearing in every future session. A one-line rule — "Never use fetch directly, use the apiClient wrapper in src/lib/api.ts" — might save you from correcting the same thing for the next year.

Enjoyed this? Get more like it.

Deep dives on system design, React, web development, and personal finance — straight to your inbox. Free, always.