Cursor Rules: Complete .cursorrules Guide with Templates (2026)

Cursor Rules: Complete .cursorrules Guide with Templates (2026)

Last updated: April 2026


Cursor Rules are project-level instructions stored in a .cursorrules file 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.

This guide covers the .cursorrules file format, where to place it, how it differs from global rules, ready-to-use templates for the most common stacks, and a debugging workflow for rules that aren't working.


1. What Are Cursor Rules and How Do They Work

Cursor Rules are plain-text instructions injected into the system prompt of every Cursor AI request within a project. Every time you use Composer, ask a question in Chat, or trigger an inline edit — the rules are included automatically. Cursor reads them before generating any response or writing any code.

Think of .cursorrules as a standing brief for an AI contractor. Instead of re-explaining your conventions every session, you write them once, commit the file to your repo, and Cursor applies them consistently.

What rules control:

  • Which files and folders Cursor creates, and where
  • Code style, architecture patterns, and naming conventions
  • Which libraries and frameworks to use (and which to avoid)
  • How Cursor handles errors, tests, and edge cases
  • Whether to ask for clarification or proceed autonomously
  • How Cursor interacts with your existing codebase patterns

What rules do not control:

  • Cursor's underlying model capabilities or context window size
  • Which AI model is used (set in Cursor settings)
  • Anything outside the project scope

2. File Format and Where to Put It

.cursorrules is a plain Markdown or plain text file. No special schema, no required structure — just clear, imperative instructions Cursor can follow.

Primary location

Place .cursorrules in the root of your project, next to package.json, pyproject.toml, go.mod, or your project's equivalent root config file:

my-project/
├── .cursorrules        ← Cursor reads this automatically
├── .gitignore
├── package.json
└── src/

Cursor Rules directory (modular approach)

For larger projects, you can split rules into multiple files inside a .cursor/rules/ directory (supported in Cursor 0.43+):

my-project/
├── .cursor/
│   └── rules/
│       ├── general.mdc     ← General task and code standards
│       ├── testing.mdc     ← Testing-specific rules
│       └── api.mdc         ← API design rules

Each .mdc file supports frontmatter metadata to control when the rule applies:

---
description: React component standards
globs: src/components/**/*.tsx
alwaysApply: false
---

## React component rules
- Functional components only
- Named exports for all components

Global rules

For personal preferences that apply across all your projects, add them in Cursor Settings → Rules for AI (previously called "Custom Instructions"). Workspace rules take priority over global rules when they conflict.


3. Syntax Guidelines

  • Write in imperative sentences: "Always use named exports." not "Named exports should be preferred."
  • Be specific and measurable: "Functions must not exceed 40 lines." not "Keep functions short."
  • Avoid ambiguity: "Use async/await instead of .then() chains." not "Handle async properly."
  • Group related rules under Markdown headings — Cursor uses these as structural context.
  • Use bullet lists for sets of related constraints.
  • Use code blocks for exact patterns, naming conventions, or examples Cursor should follow.

Minimal working example

# 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.

4. Ready-to-Use .cursorrules Templates

Template 1: Next.js 14 App Router + TypeScript + Prisma

# Project Rules — Next.js 14 / TypeScript / Prisma

## Environment
- Next.js 14 with App Router. TypeScript strict mode.
- Database: PostgreSQL via Prisma ORM.
- Styling: Tailwind CSS only.
- Testing: Vitest + React Testing Library.

## File structure
- All routes go in `app/`. Never use `pages/`.
- Server components are the default. Mark client components with `'use client'` only when needed.
- API routes go in `app/api/[resource]/route.ts`.
- Shared UI components go in `src/components/`.
- Business logic goes in `src/services/` — never in components directly.

## Component rules
- Functional components only. No class components.
- Named exports for all components.
- No `any` type. Use `unknown` and narrow it.

## Data access
- 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 response format
- Success: `{ success: true, data: T }`
- Error: `{ success: false, error: string }`

## Task behaviour
- Confirm new file locations before creating them.
- Run `npm run build` after major changes to catch type errors.
- Show me new package installs before running `npm install`.

Template 2: React + TypeScript SPA (Vite + Zustand + React Query)

# Project Rules — React SPA / TypeScript / Zustand / React Query

## Environment
- React 18, TypeScript strict mode, Vite as bundler.
- State: Zustand for client state. React Query for server state.
- Styling: Tailwind CSS. No inline styles, no CSS Modules.
- Testing: Vitest + React Testing Library.

## Component conventions
- One component per file. File name = component name.
- All components use named exports.
- Props interfaces defined directly above the component.
- No `useEffect` for data fetching — use React Query instead.

## State management
- Zustand stores in `src/stores/`. One store per domain.
- Server state managed by React Query only — don't duplicate in Zustand.
- Zustand actions defined inside the store, not as standalone functions.

## File structure
- `src/components/` — reusable UI components
- `src/features/` — feature-scoped components and logic
- `src/services/` — API service functions (typed, no `any`)
- `src/stores/` — Zustand stores
- `src/hooks/` — custom hooks
- `src/types/` — shared TypeScript types

## Task behaviour
- Order: types → service function → React Query hook → component.
- Never add a library without asking first.
- Run `npm run type-check` after completing a task.

Template 3: FastAPI + Python + SQLAlchemy

# Project Rules — FastAPI / Python / SQLAlchemy

## Environment
- Python 3.12+. Type hints everywhere.
- Framework: FastAPI. ORM: SQLAlchemy 2.0 with async sessions.
- Package manager: Poetry.
- Testing: pytest + pytest-asyncio.

## Project structure
- API routes in `app/routers/` — one file per resource.
- Business logic in `app/services/` — keep route handlers thin.
- Database models in `app/models/`.
- Pydantic schemas in `app/schemas/`.
- DB queries in `app/repositories/` — no direct ORM queries in services.

## Code style
- `async def` for all route handlers and service functions.
- Pydantic models for all request bodies and responses — never return raw dicts.
- All DB operations in try/except with proper rollback on error.

## API conventions
- Plural nouns for all resource paths: `/users`, not `/user`.
- Versioning prefix: all routes start with `/api/v1/`.
- Status codes: 200 GET/PUT/PATCH, 201 POST, 204 DELETE.

## Task behaviour
- Add/update Pydantic schema before adding a new endpoint.
- After adding a model, run `alembic revision --autogenerate`.
- Show `pytest` output after implementation.

Template 4: Node.js + Express + TypeScript + PostgreSQL

# Project Rules — Node.js / Express / TypeScript / PostgreSQL

## Environment
- Node.js 20+, TypeScript 5+, Express 4.
- Database: PostgreSQL via `pg`. No ORM — raw SQL with parameterized queries.
- Testing: Jest + Supertest.

## Project structure
- `src/routes/` — Express Router definitions, no logic
- `src/controllers/` — request handling, input validation
- `src/services/` — business logic
- `src/db/` — database queries, connection pool
- `src/middleware/` — auth, error handling, rate limiting

## Database rules
- 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.

## API rules
- Input validation in the controller, before any service call.
- Error responses: `{ success: false, error: string }`. No stack traces in production.
- All route handlers wrapped in `asyncHandler()`.

## Task behaviour
- New route → update controller, service, and query file.
- Confirm schema changes before writing migration SQL.
- Run `npm test` after completing a task.

Template 5: Go + Gin + PostgreSQL

# Project Rules — Go / Gin / PostgreSQL

## Environment
- Go 1.22+. Web framework: Gin. Database driver: `pgx`.
- No ORM. Raw SQL via `pgx`.
- Testing: standard `testing` package + `testify`.

## Project structure
- `cmd/` — entrypoints (main.go)
- `internal/handlers/` — HTTP handler functions
- `internal/services/` — business logic
- `internal/repository/` — database access layer
- `internal/models/` — struct definitions
- `config/` — environment and config loading

## Code conventions
- Errors always returned, never panicked on (except in main.go init).
- Every exported function has a godoc comment.
- `context.Context` as first parameter in all service and repository functions.

## Error handling
- Return `(T, error)` from service and repository functions.
- Handlers translate errors to HTTP status codes — services never set status codes.
- Log the full error internally; return a generic message to the client.

## Task behaviour
- Order: model → repository → service → handler → route registration.
- Run `go build ./...` and `go vet ./...` after completing a task.
- Show migration SQL before applying it.

5. Cursor Rules vs. Other Cursor Features

Understanding when to use .cursorrules vs. other Cursor mechanisms prevents confusion and wasted effort.

Mechanism What it is Persists Version controlled Best for
.cursorrules (workspace) Project-level standing instructions Yes Yes Architecture, stack conventions, naming, workflow rules
Global rules (Settings → Rules for AI) Personal developer defaults Yes No Personal preferences, agent behaviour, communication style
@file or @folder mentions Files referenced in a specific request No — per-request only Yes (the files) Task-specific context: a spec doc, a schema
In-request instructions Instructions given directly in the chat No — one request only No One-off overrides

Decision rule:

  • Will you need this instruction in more than one session? → .cursorrules
  • Personal preference that doesn't belong in the repo? → Global rules
  • Context specific to one task? → @file reference
  • One-time override? → Say it directly in the request

6. Common .cursorrules Anti-Patterns

Anti-pattern Example Problem Better alternative
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
Contradictory rules "Always write tests." + "Only write tests when asked." Cursor cannot resolve the ambiguity Pick one and remove the other
Scope-incorrect rules Putting personal preferences in a team .cursorrules Affects all contributors' Cursor sessions Put in global rules instead
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."

7. Token Budget and Rule Length

Every character in .cursorrules is included in every Cursor request. Longer rules consume more context window, leaving less room for your code and conversation.

Rule file size Effect Recommendation
< 50 lines Minimal impact Fine for any project
50–150 lines Noticeable but acceptable Review for redundancy
150–300 lines Significant consumption Split into .cursor/rules/
> 300 lines Risk of rule truncation Refactor aggressively

To reduce size without losing coverage:

  • Merge related rules into one concise statement
  • Reference files instead of repeating patterns: "Follow the structure of src/services/userService.ts"
  • Delete rules for things Cursor does correctly by default — test by removing the rule and running a task

8. Troubleshooting: Why Your Rules Aren't Working

Step 1: Confirm Cursor is reading the file

Open Cursor Chat and ask: "What rules are you following from the .cursorrules file?"

Cursor will either quote your rules back (confirming it read the file) or indicate it found nothing. If nothing:

  • Confirm the file is named exactly .cursorrules (no extension)
  • Confirm it is in the project root
  • Restart Cursor or reload the window

Step 2: Check rule specificity

Vague rules are technically read but practically ignored. Run a minimal test:

  1. Pick one rule
  2. Give Cursor a small task where that rule clearly applies
  3. Check if the output follows it

If not, make the rule more specific and retry.

Step 3: Check for conflicts

If you have both workspace and global rules, check for contradictions. Resolve by making the workspace rule more explicit.

Step 4: Check rule position

Rules near the top receive more attention. Move your most critical rules to the top. Use a ## Critical rules or ## Always apply section at the very beginning.

Step 5: Check token budget

If your file exceeds 200 lines, Cursor may not give adequate attention to rules in the bottom sections. Trim to under 150 lines for reliable adherence.

Symptom Likely cause Fix
Rules followed in short tasks but not long ones Context window pressure Move critical rules to the top; reduce file size
Rules work on new files but not edits Rule written for creation, not modification Rewrite: "All components, new and existing, must..."
A specific rule ignored consistently Rule is ambiguous or conflicts with defaults Test in a new empty task; add a concrete example

9. FAQ

Should I commit .cursorrules to git?

Yes, in almost all cases. It encodes project conventions that every contributor (human and AI) should follow. Treat it like .eslintrc — it's part of your project's code quality infrastructure.

Can I have different rules for different folders?

Yes, using the .cursor/rules/ directory with .mdc files and globs frontmatter. This lets you apply different rules to src/components/ vs src/api/ vs __tests__/.

What's the maximum size for .cursorrules?

No hard limit, but practical performance degrades beyond ~300 lines. Keep under 150 lines for optimal rule adherence. If you need more, use the modular .cursor/rules/ approach.

Do workspace rules override global Custom Instructions?

Yes. Workspace .cursorrules take priority over global rules 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 .cursorrules for that single interaction.


Related

Enjoyed this article?

Share it with your network