CursorIntermediate

How to Set Up Project Rules in the .cursor/rules Folder

Create scoped, versioned project rules so Cursor follows your stack conventions on every request without you repeating yourself.

9 minIntermediate

Rules are persistent instructions Cursor injects into the AI's context so it follows your conventions without you pasting them into every prompt. The modern format lives in a .cursor/rules folder inside your repo, with one file per rule. This guide creates a couple of useful rules and shows how to scope them so they only apply where they should.

What you need

  • Cursor installed and a project open
  • A repo where you can commit a new folder (rules are versioned with your code)
  • A clear idea of one or two conventions your team always wants followed

Step 1: Create the rules folder

At the root of your project create a folder named .cursor/rules. Each rule is a separate file ending in .mdc (a Markdown variant with a small metadata header). You can also generate one from the command palette with the New Cursor Rule command.

zsh — project root
$mkdir -p .cursor/rules
$touch .cursor/rules/typescript.mdc
$ls .cursor/rules
typescript.mdc
$

Step 2: Write a rule with a metadata header

Each .mdc file starts with a small frontmatter block that tells Cursor when the rule applies, followed by the instructions in plain Markdown. Setting a glob makes the rule attach automatically whenever a matching file is in context.

.cursor/rules/typescript.mdc
---
description: TypeScript conventions for this repo
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---

- Prefer `type` aliases over `interface` unless declaration merging is needed.
- Never use `any`; use `unknown` and narrow it.
- All exported functions need an explicit return type.
- Use named exports, not default exports.

Step 3: Choose how each rule attaches

Rules attach in one of a few ways. Always Apply puts the rule in context on every request. Auto Attached uses the globs you set. Agent Requested lets the model pull the rule in when it judges the description relevant. Manual means the rule only loads when you reference it by name.

ModeSet byWhen it loads
AlwaysalwaysApply: trueEvery request
Auto Attachedglobs: [...]When a matching file is in context
Agent Requesteddescription onlyWhen the model decides it is relevant
ManualneitherOnly when you @mention the rule
Cursor — rules in the file tree
Explorer
.cursor
rules
typescript.mdc
api-style.mdc
src
.cursor/rules/typescript.mdc
1---
2description: TypeScript conventions
3globs: ["**/*.ts", "**/*.tsx"]
4alwaysApply: false
5---
6- Prefer type aliases over interface.
7- Never use any.
Each rule is a versioned file under .cursor/rules.

Step 4: Verify the rule is active

Open a TypeScript file, start a chat, and ask the model what rules it is following. It should mention your TypeScript conventions. You can also see attached rules listed at the top of the chat context for the current request.

Keep rules short and specific
A rule that says ten concrete things gets followed; a 400-line rule gets diluted. Split big rule files by concern (one for API style, one for tests, one for naming) and let globs decide which load.

Example: after adding the rule above, asking Cursor to add a function produces a named export with an explicit return type and no any in sight, with no extra instructions from you.

Watch related tutorials

Tags
#rules#context#config#conventions