How to Write .cursorrules: Cursor Prompt Engineering Guide (2026)
If Cursor's AI keeps generating code you have to fix every time, the problem is not the model: it is your rules file. A good .cursorrules can cut your edit-to-accept ratio from 3:1 to near 1:1. After eight months of iterating on Cursor rules across React, Python, and Go projects, this guide walks through what works, what breaks, and the templates I actually use.
TL;DR
I spent months fixing AI-generated code that ignored my project conventions before I realized the problem was not the model: it was my rules file. A good .cursorrules can cut your edit-to-accept ratio from 3:1 to near 1:1. After eight months of iterating on Cursor rules across React, Python, and Go projects, this guide walks through what works, what breaks, and the templates I actually use.
This tutorial is part of our Cursor knowledge base. If you are new to Cursor, start with our Cursor FAQ and complete setup guide.
What .cursorrules Actually Does
.cursorrules is a markdown file in your project root. Cursor reads it on every AI interaction and prepends its contents to the model's system prompt. Think of it as a persistent instruction layer that sits between your query and the model.
The file works across all Cursor AI modes: Inline (Ctrl+K), Chat, Composer, and Agent. Agent mode is where good rules make the biggest difference because the model has freedom to create files, run terminal commands, and chain multiple operations. Without rules constraining that freedom, Agent mode quickly spirals into over-engineering.
A .cursorrules file can contain project conventions, code style preferences, architectural constraints, tech stack details, and behavioral instructions for the AI. The model treats it as authoritative context: it will follow your rules unless you explicitly contradict them in a prompt.
Why the Default Behavior Falls Short
Cursor ships with sensible defaults, but they are generic. The model does not know your team's naming conventions, your preferred error handling pattern, or whether you use TypeScript strict mode. When it guesses, it guesses wrong often enough to slow you down.
Here is what happens without good rules on a typical React project:
- The AI imports
useStatefrom a barrel export that does not exist in your codebase - It generates 40-line components when your team convention is to split at 80 lines
- It uses
anyinstead of proper TypeScript types because it does not know your zod schemas exist - It writes inline styles because it does not know you are using Tailwind v4
- It creates new utility functions that already exist in
@/lib/
Each of these costs you a round of edits. With good rules, most of them disappear.
Rule Categories That Actually Matter
After testing dozens of rule configurations, I have found that rules fall into four buckets of impact. Focus your effort on the first two.
Tier 1: High-Impact Rules (always include these)
Tech stack and version: Tell Cursor exactly what you are using, including versions. We use Next.js 15 with App Router. All new pages go in app/. Use React Server Components by default. Add 'use client' only when necessary.
This single rule eliminated 80% of my "wrong architecture" generations. Without it, Cursor on an App Router project would generate pages/ directory code about half the time.
Code style and formatting: Use single quotes. No semicolons. Two-space indentation. Prefer arrow functions over function declarations. Use const by default, let only when reassignment is needed.
The model will follow these religiously once stated. If your team uses Prettier or Biome, mention that too and the AI will align its output.
Import conventions: Import from @/components/ for shared UI, @/lib/ for utilities, @/hooks/ for custom hooks. Never use relative imports that go up more than two levels. Do not use barrel exports (index.ts) for components.
Import chaos is the number one thing I used to fix in AI-generated code. This rule fixes it.
Error handling pattern: Use try/catch in async functions. Throw typed errors, never strings. In API routes, return NextResponse.json({ error: message }, { status: code }).
Tier 2: Medium-Impact Rules (add these for your specific stack)
TypeScript strictness: Use strict TypeScript. No any. Prefer unknown over any. Define types in @/types/. Use zod for runtime validation at API boundaries.
Testing preferences: Use Vitest. Tests go in __tests__/ next to the file they test. Name test files *.test.ts. Use describe/it blocks. Prefer integration tests that hit real APIs over mocking everything.
Component patterns: Use functional components. Props go in a separate types.ts in the same folder. Use composition over prop drilling. Extract reusable logic into custom hooks in @/hooks/.
File naming: kebab-case for files and directories. Components get PascalCase filenames. Utility files use camelCase.
Tier 3: Nice-to-Have Rules (add for polish)
Commit style: Follow conventional commits: feat:, fix:, chore:, refactor:, docs:. Keep commits atomic: one logical change per commit.
Documentation: Add JSDoc comments for public API functions. Include @param and @returns tags. Do not document obvious internal helpers.
Performance notes: Avoid unnecessary re-renders. Use useMemo and useCallback only when measured as necessary. Prefer server components for data fetching.
Tier 4: Rules to Avoid
Some rules backfire. Here is what I have learned to leave out:
- Overly specific architectural rules: "Always use the repository pattern with dependency injection" will confuse Cursor when it generates a simple landing page component. Keep architectural rules scoped to relevant directories.
- Conflicting instructions: "Prefer functional style" and "Use classes for stateful services" in the same file will cause the model to flip between approaches unpredictably.
- Rules about things the model already knows: You do not need "Use modern JavaScript syntax" or "Write clean code." These are noise.
- Long prose paragraphs: The model skims after about 500 tokens of dense instruction. Use bullet points and short declarative sentences.
Template: The .cursorrules File I Actually Use
Here is the template I drop into new projects. It covers web development with Next.js and TypeScript, which is what I spend most of my time on. Adapt the stack-specific sections for your framework.
# Cursor Rules
## Stack
- Next.js 15 (App Router)
- TypeScript 5.x, strict mode
- Tailwind CSS v4
- Prisma for database
- Zod for validation
- Vitest for testing
## Code Style
- Single quotes, no semicolons, 2-space indent
- const by default, let only for reassignment
- Arrow functions preferred
- No any; use unknown if type is genuinely uncertain
## Architecture
- app/ for routes, components/ for shared UI, lib/ for utilities
- React Server Components by default
- Add 'use client' only when using hooks or event handlers
- Data fetching in server components; use server actions for mutations
## Imports
- @/components/*, @/lib/*, @/hooks/*, @/types/*
- No relative imports beyond ../../
- Do not use barrel exports for components
## Components
- One component per file
- Props interface in the same file
- Composable over prop drilling; extract to custom hooks in @/hooks/
- kebab-case filenames, PascalCase component names
## Error Handling
- try/catch for all async operations
- Throw typed Error subclasses
- API routes: return NextResponse.json({ error: string }, { status: number })
- Log errors to console.error, do not expose stack traces to the client
## Testing
- Vitest, __tests__/ directory next to the tested file
- *.test.ts naming
- Integration tests preferred over unit tests
- Test real behavior, not implementation details
## Git
- Conventional commits: feat:, fix:, chore:, refactor:, docs:, test:
- Atomic commits: one change per commit
- Good commit messages explain why, not whatThis file is about 1,200 characters. That fits comfortably within the model's attention window without pushing out other context. If your file grows past 2,500 characters, trim the Tier 3 rules first.
How Rules Interact with Cursor Modes
Different Cursor modes obey rules differently.
Inline (Ctrl+K): Rules apply but have the least impact. The inline mode gets a shorter context window and often prioritizes the surrounding code over the rules file. If you find inline edits ignoring your style rules, switch to Chat for that operation.
Chat (Ctrl+L): Rules are consistently followed. Chat has the full context window and the model reads the rules file thoroughly before each response. This is the mode where rules make the most visible difference in code quality.
Composer (Ctrl+I): Rules apply to both the plan and the generated code. If your rules say "prefer server components," Composer will structure its plan around that. The generated diff will respect your style rules. This is where rules save the most time because a Composer session can generate dozens of files, and you do not want to fix formatting in all of them.
Agent Mode: Rules are critical here. Agent mode can create files, run shell commands, install packages, and make multi-step changes. Without rules, it will happily install libraries you do not use, create files in the wrong directories, and format code however it likes. With good rules, Agent mode becomes a reliable junior developer instead of a loose cannon.
One quirk I have noticed: Agent mode sometimes ignores rules in very long sessions (past 50+ turns). I suspect context window pressure pushes the rules out. When this happens, restart the session instead of arguing with the model.
Advanced: Conditional Rules with @-mentions
Cursor supports @file and @directory references in .cursorrules. You can scope rules to specific parts of your codebase:
@file src/app/api/**/*.ts:
- Validate all request bodies with zod before processing
- Return consistent error shapes: { error: string, details?: unknown }
- Include request IDs for debugging
@file src/components/**/*.tsx:
- Use Tailwind classes only; no inline styles
- Export named, not default
- Include Storybook stories in *.stories.tsx sibling filesThe @file directive tells Cursor that these rules only activate when the AI is working on files matching that glob pattern. This prevents your API validation rules from cluttering the context when you are editing a button component.
The @directory variant works the same way but applies to everything in that directory tree.
I use conditional rules sparingly because they add complexity. Start with a flat rules file. Add @file scoping only when you have domain-specific conventions that genuinely do not apply elsewhere.
Testing Your Rules: The Make-Or-Break Iteration
You will not get rules right on the first try. Here is my iteration process:
- Write the initial rules file. Keep it short: 800-1,500 characters.
- Run a test prompt. Ask Cursor Composer to add a feature to your project. Watch what it generates.
- Note every edit you make to the generated code. Count the number of fixes you apply before accepting.
- For each fix, ask: would a rule have prevented this? If yes, add the rule. If the fix was "the AI added a feature I did not ask for," do not add a rule: that is a prompting issue, not a rules issue.
- Repeat steps 2-4 three times. By the third round, your rules file should feel stable.
Here is a real example from one of my projects. Round 1: the AI generated 12 files. I made 8 fixes: 3 import style fixes, 2 type annotation fixes, 1 architecture fix (pages/ instead of app/), 1 naming fix, and 1 missing error handling. I added rules for imports, types, architecture, and errors. Round 2: 4 fixes. Added rules for naming and a subdirectory convention. Round 3: 1 fix (the AI used fetch directly instead of our API client, which I forgot to document in rules). After three rounds, the rules file had stabilized.
Common Mistakes
The kitchen sink problem. New users often copy a 5,000-character rules file from a blog post, drop it in, and wonder why Cursor ignores half of it. The model attention budget is finite. Keep your rules file under 2,500 characters. If you have more conventions, put them in a CONTRIBUTING.md and reference that from .cursorrules.
Rules that duplicate ESLint/Prettier. Cursor's AI does not run your linter before outputting code. Rules like "no unused variables" or "props in alphabetical order" are better enforced by lint-staged than by the AI. Let the linter handle syntax-level rules; use .cursorrules for semantic-level guidance that a linter cannot check (architecture, naming, patterns).
Inconsistent style within the rules file itself. If your rules say "kebab-case filenames" but you name the file .cursorrules (with a dot prefix), the model notices the inconsistency. Small details matter in system prompts.
Not updating rules when the stack changes. I moved a project from Next.js 14 to 15 and forgot to update the rules file. For a week, Cursor kept generating pages/ directory code in my app/ directory project. Update your rules file whenever you change frameworks, major versions, or architectural patterns.
.cursorrules vs Cursor Settings
Cursor has a Settings panel with AI preferences (model selection, context length, rules for specific languages). Do not confuse these with .cursorrules.
Cursor Settings are user-level: they apply to all projects you open in Cursor. Use them for preferences like your preferred model (claude-sonnet-4 vs gpt-5) and global code style defaults.
.cursorrules are project-level: they apply only to the project containing the file. Use them for project-specific conventions: tech stack, architecture, team conventions, directory structure.
Both are read by the AI, but .cursorrules takes precedence when there is a conflict because it is more specific.
The settings panel also has a "Rules for AI" section per language. These are a middle ground: they apply globally but are scoped by file extension. I use them sparingly because having rules in two places makes debugging confusing. I prefer to keep everything in .cursorrules and only use the settings panel for model selection.
What About .cursorrules vs CLAUDE.md?
If you use Claude Code alongside Cursor, you might have both a .cursorrules and a CLAUDE.md file. These serve the same purpose (system instructions) but for different tools. Claude Code reads CLAUDE.md; Cursor reads .cursorrules.
If you maintain both, keep them in sync on the architectural rules (stack, directory structure) but diverge on tool-specific instructions. For example, CLAUDE.md might include Use Claude Code's /init to bootstrap new files while .cursorrules says Use Cursor Composer for multi-file refactors.
A practical approach: maintain one canonical rules file (I use CLAUDE.md because I use Claude Code more) and add a note at the top of .cursorrules: See CLAUDE.md for detailed conventions. This file contains Cursor-specific overrides.
When Rules Are Not the Answer
If you find yourself adding rules for things the AI should not be doing at all, you might have a workflow problem, not a rules problem.
Signs the issue is not rules:
- The AI generates complete features you did not ask for: your prompts are too vague
- The AI uses deprecated APIs: your rules list stack but not versions
- The AI writes correct code that fails tests: your test descriptions are unclear
- The AI ignores your rules consistently: your rules file might exceed the context budget
Start with good prompts, then add rules to tighten the guardrails. Rules are a refinement layer, not a replacement for clear instructions.
Final Rule Set (Quickstart)
If you want to copy-paste a minimal, battle-tested rules file, here it is:
# Cursor Rules
- Stack: [your framework + version]
- Use [your style convention] (single quotes, 2-space, no semicolons)
- const > let, arrow functions preferred
- Imports: [your alias pattern]
- No any; use unknown when uncertain
- try/catch for async; typed errors only
- Tests: [your test framework], __tests__/ directory, *.test.* naming
- Conventional commits: feat:, fix:, chore:, refactor:, docs:, test:
- Do not over-engineer. Write the simplest solution first.Replace the brackets with your actual values. The last line about simplicity is the one rule I have never regretted adding.
Related tutorials:
相关推荐
Claude Code Pricing Guide: Plans, Credits, and Cost Optimization (2026)
I spend $80-150/month on Claude Code and use it 6-7 days a week. This guide breaks down exactly how Claude Code pricing works: per-token API billing, Anthropic credits, Max mode costs, the June 2026 billing change, and real monthly budgets from three developer profiles. I also share the six cost optimization techniques that cut my bill from $340 to $80 without reducing how much I ship.
Cursor Hub: Complete AI Code Editor Knowledge Base (2026)
I have been using Cursor as my daily driver since January 2026. This hub is your central map to every Cursor tutorial, case study, and comparison on WayToClawEarn.
赚钱视角
这个趋势怎么赚钱?
WayToClawEarn 的差异在可验证的赚钱案例,而不只是资讯。从这些复盘开始:
浏览全部案例 →