Chapter 27
27 / 38

Writing Cursor Rules

⏱️ 15 min

What Are Cursor Rules?

Cursor Rules tell AI how your project works. By defining rule files, you give AI context about:

  • Your coding standards
  • Common patterns and conventions
  • Mistakes to avoid
  • Specific technical requirements

Required Rule Structure

Every rule file should follow this structure:

---
description: Clear, one-line description of what the rule enforces
globs: path/to/files/*.ext, other/path/**/*
alwaysApply: boolean
---

-   **Main Points in Bold**
    -   Sub-points with details
    -   Examples and explanations

File References

# Use [filename](mdc:path/to/file) to reference files

[prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references
[schema.prisma](mdc:prisma/schema.prisma) for code references

Code Examples

Use language-specific code blocks in rules:

// ✅ DO: Show good examples
const goodExample = true;

// ❌ DON'T: Show anti-patterns
const badExample = false;

Rule Content Guidelines

  • Start with high-level overview
  • Include specific, actionable requirements
  • Show examples of correct implementation
  • Reference existing code when possible
  • Keep rules DRY by referencing other rules

Rule Maintenance

  • Update rules when new patterns emerge
  • Add examples from actual codebase
  • Remove outdated patterns
  • Cross-reference related rules

Best Practices

  • Use bullet points for clarity
  • Keep descriptions concise
  • Include both DO and DON'T examples
  • Reference actual code over theoretical examples
  • Use consistent formatting across rules

Rule File Locations

  • Project-level: .cursor/rules/ - project-specific rules
  • User-level: ~/.cursor/rules/ - cross-project universal rules

Example: TypeScript Rule

---
description: TypeScript coding standards for this project
globs: '**/*.ts, **/*.tsx'
alwaysApply: true
---

-   **Type Safety**

    -   Always use explicit return types for functions
    -   Avoid `any` type, prefer `unknown` for uncertain types
    -   Use strict null checks

-   **Naming Conventions**

    -   Interfaces: PascalCase with `I` prefix (e.g., `IUser`)
    -   Types: PascalCase (e.g., `UserRole`)
    -   Constants: UPPER_SNAKE_CASE

-   **Code Organization**
    -   One component per file
    -   Group imports: external, internal, types
    -   Export from index files

Example: Git Commit Rule

---
description: Git commit message standards
globs: ''
alwaysApply: false
---

-   **Commit Format**: `type(scope): description`

-   **Types**:

    -   ✨ feat: New features
    -   🐛 fix: Bug fixes
    -   📝 docs: Documentation
    -   ♻️ refactor: Code restructuring
    -   ✅ test: Tests

-   **Best Practices**:
    -   Keep commits atomic and focused
    -   Write in imperative mood
    -   Explain why, not just what

Next Steps

Check out Git Commit Conventions & Emoji to level up your commit quality.

[VIBE_CODING_LAB_BANNER]

📚 Related resources

Common questions

Open a question to review the practical answer.

Where do Cursor Rules files live and what is the difference between project and user level?

Project-level rules live in `.cursor/rules/` and travel with the repo so the whole team shares one ruleset; user-level rules live in `~/.cursor/rules/` and apply across projects, good for personal style (naming, comment tone). When both define the same rule the project-level wins, so a new teammate clones and instantly inherits the team conventions.

What do the three frontmatter fields in a Cursor Rule control?

(1) `description` — one line explaining what the rule enforces, used by the AI router; (2) `globs` — file patterns like `**/*.ts, **/*.tsx` that decide which files trigger it; (3) `alwaysApply` — boolean, true loads it every turn regardless of file type, false only loads when globs match. A repo-wide rule like Git commits uses `alwaysApply: false` with empty globs so it stays on-demand.

Do DO/DON'T code examples in Cursor Rules actually help?

Yes — concrete `// ✅ DO` and `// ❌ DON'T` snippets land more reliably than prose. The model reading `const goodExample = true` paired with `const badExample = false` lines up the anti-pattern explicitly; a sentence like "avoid `any`" still gets quietly violated sometimes. Ship both shapes in the same rule for the highest hit rate.

What is the `[filename](mdc:path/to/file)` syntax used for?

Cursor-specific file reference syntax that lets rules cross-link to other rules or source files. `[prisma.mdc](mdc:.cursor/rules/prisma.mdc)` pulls that rule whenever the AI touches schema work, and `[schema.prisma](mdc:prisma/schema.prisma)` points straight at the source. Key for keeping rules DRY — define shared logic once, reference it from many rules.

Will too many Cursor Rules slow down AI responses?

Yes but it depends. Rules with `alwaysApply: true` load into context every turn — 5 to 10 is fine, beyond that you eat real tokens; rules scoped via `globs` only load when matched and you can keep dozens with no penalty. Optimisation: short shared conventions in `alwaysApply: true` files, framework/language specifics sliced by globs.