How to Set Up Cursor Rules Scoped to Specific File Types
Where Cursor rule files live, the four rule types, how to scope them with globs, and example rules you can copy into a real project.

Cursor rules are instructions that get included at the start of the model context, so Agent follows your conventions without you repeating them in every chat. Project rules live in .cursor/rules as .mdc files, and you control when each one applies with three frontmatter fields: description, globs, and alwaysApply.
To add one, type /create-rule in Agent and describe what you want, or open Customize in the sidebar, go to Rules, and click Add Rule. Both save a file into .cursor/rules. The rest of this post covers the file layout, the rule types, glob scoping, example rules, and why a rule sometimes doesn't fire.
Where cursor rules files live#
Cursor supports four kinds of rules:
| Kind | Where it lives | Scope |
|---|---|---|
| Project Rules | .cursor/rules |
Your codebase, version-controlled |
| User Rules | Customize → Rules | Global to your Cursor environment, used by Agent (Chat) |
| Team Rules | Cursor dashboard | Team-wide, on Team and Enterprise plans |
| AGENTS.md | Project root and subdirectories | Plain markdown alternative to .cursor/rules |
For project rules, each rule is an .mdc file and you can name it anything. You can organize them in folders:
.cursor/rules/
react-patterns.mdc # Recognized as a project rule
api-guidelines.md # Ignored (wrong extension)
frontend/ # Organize rules in folders
components.mdc
The extension matters. A plain .md file in .cursor/rules is ignored by the rules system because it has no frontmatter to specify description, globs, and alwaysApply. If you'd rather write plain markdown, use AGENTS.md instead.
Check the rules into git. That's the main reason to prefer project rules over personal ones: everyone on the repo gets the same guidance.
The four rule types and the frontmatter behind them#
In the editor you pick a type from a dropdown, and that dropdown changes description, globs, and alwaysApply for you.
| Rule type | What it does |
|---|---|
| Always Apply | Applies to every chat session |
| Apply Intelligently | Agent decides it's relevant based on the description |
| Apply to Specific Files | Applies when a file matches a pattern |
| Apply Manually | Applies when you @-mention it in chat, for example @my-rule |
Under the hood, the three fields combine like this:
alwaysApply |
description |
globs |
Behavior |
|---|---|---|---|
true |
any | any | Always included. Globs and description are ignored. |
false |
any | provided | Auto-attached when a matching file is in context. |
false |
provided | omitted | Agent reads the description and pulls the rule in when relevant. |
false |
omitted | omitted | Included only when you @-mention the rule. |
If you like seeing logic as code, here's the same table as a small function. Change the inputs and see which mode you end up in.
function ruleMode({ alwaysApply, description, globs }) {
if (alwaysApply) return 'always included';
if (globs) return 'auto-attached when a matching file is in context';
if (description) return 'agent-selected from the description';
return 'manual: only when @-mentioned';
}
const samples = [
{ alwaysApply: true },
{ alwaysApply: false, globs: 'src/components/**/*.tsx' },
{ alwaysApply: false, description: 'RPC service conventions' },
{ alwaysApply: false },
];
for (const s of samples) console.log(JSON.stringify(s), '->', ruleMode(s));
How to write cursor rules for each type#
Here's the smallest useful example of each type, taken from the patterns in the Cursor docs.
Always applied. Use this sparingly, since it goes into every chat:
---
alwaysApply: true
---
- All source files must include the company copyright header
- When you are unsure about implementation details, read the relevant source files before proposing changes
- Never modify generated files in the `dist/` or `build/` directories
Auto-attached by file pattern. This one only shows up when a matching file is in context:
---
globs: src/components/**/*.tsx
alwaysApply: false
---
- Use named exports, not default exports
- Co-locate styles in a module CSS file next to the component
- Keep components under 200 lines. Extract subcomponents into the same directory when a file grows beyond that
- Prefer composition over prop drilling. Pass children or render props instead of threading data through multiple layers
Agent-selected by description. The description is what Agent reads to decide, so write it like a one-line summary of when the rule matters:
---
description: RPC service conventions and patterns for the backend
alwaysApply: false
---
- Define each service in its own file under `src/services/`
- Always validate inputs at the service boundary before passing data to internal functions
- Return structured error objects with a `code` and `message` field, never throw raw strings
- Read `@service-template.ts` for the standard boilerplate before creating a new service
Manual, only via @-mention. Good for checklists you want on demand:
---
alwaysApply: false
---
- Every database migration must have both `up` and `down` functions so it can be fully reversed
- Never alter a column type in-place. Add a new column, backfill, then drop the old one in a separate migration
- Read `@migration-template.sql` for the expected file structure before writing a migration
Save that last one as, say, .cursor/rules/migrations.mdc, then type @migrations in chat to pull it in.
Scoping cursor rules to files with globs#
Separate multiple patterns with commas. These are the patterns the docs list:
| Pattern | Matches |
|---|---|
* |
Any single file name segment |
** |
Any number of directories (recursive) |
*.ts |
All .ts files in the root |
**/*.ts |
All .ts files in any directory |
src/** |
All files anywhere under src/ |
src/**/*.tsx |
All .tsx files anywhere under src/ |
docs/**/*.md, docs/**/*.mdx |
.md and .mdx files under docs/ |
tailwind.config.* |
tailwind.config with any extension |
One thing that trips people up: *.ts only matches the root. If you want TypeScript files everywhere, write **/*.ts.
A file-scoped rule is attached when a matching file is in context, so it won't fire in a chat that never touches those files. That's the point. It keeps frontend advice out of your backend conversations.
Example rules for real projects#
The docs include a few examples worth adapting. They're short on purpose.
Frontend components and API validation, as two separate rules:
When working in components directory:
- Always use Tailwind for styling
- Use Framer Motion for animations
- Follow component naming conventions
In API directory:
- Use zod for all validation
- Define return types with zod schemas
- Export types generated from schemas
Template-driven rules point at a file instead of pasting code:
When creating an Express service, read @express-service-template.ts and follow its structure:
- Follow RESTful principles
- Include error handling middleware
- Set up proper logging
A workflow rule:
When asked to analyze the app:
- Run dev server with npm run dev
- Fetch logs from console
- Suggest performance improvements
The docs show these as rule bodies; put them under frontmatter from the section above to choose how each one is applied. For a Python project, I'd write the same kind of rule with a globs: **/*.py line and your own conventions in the body. The Cursor docs note that community-contributed rules are collected in repositories online, and they're a fine starting point for ideas. Read them before you copy them, because a rule you don't understand is hard to debug later.
Referencing files instead of pasting them#
When a rule says @migration-template.sql, Agent gets the text as written and reads the file with its tools when it needs the content. The file isn't inlined into the prompt. That's true in the editor, the CLI, and Cloud Agents. So if something must always be in context, put it in the rule body. If it's reference material, link it and tell Agent what to look for.
Here's a quick audit script. Run it from your project root and it lists what's in .cursor/rules and flags files the rules system will ignore.
from pathlib import Path
root = Path('.cursor/rules')
if not root.is_dir():
print('No .cursor/rules directory here. Run this from your project root.')
else:
for p in sorted(root.rglob('*')):
if p.is_file():
status = 'ok' if p.suffix == '.mdc' else 'IGNORED (needs .mdc)'
print(f'{p.relative_to(root)}: {status}')
Cursor rules vs AGENTS.md#
AGENTS.md is a plain markdown file with no metadata. Put it in the project root for straightforward cases:
# Project Instructions
## Code Style
- Use TypeScript for all new files
- Prefer functional components in React
- Use snake_case for database columns
## Architecture
- Follow the repository pattern
- Keep business logic in service layers
Cursor also supports AGENTS.md in subdirectories. A nested file applies when you're working with files in that directory or its children, instructions combine with parent directories, and the more specific ones take precedence:
project/
AGENTS.md # Global instructions
frontend/
AGENTS.md # Frontend-specific instructions
components/
AGENTS.md # Component-specific instructions
backend/
AGENTS.md # Backend-specific instructions
My rule of thumb: start with AGENTS.md if all you have is a list of conventions. Move to .cursor/rules when you need globs, a description for Agent to match on, or manual @-mention rules.
Rules sit next to other customization in Customize, where you can also add plugins, skills, and MCPs. The pack I'm working from doesn't detail how skills compare to rules, so check the current Cursor docs for that.
User rules, team rules, and precedence#
User Rules are global preferences set in Customize → Rules. They apply across all projects and are used by Agent (Chat). A typical one:
Please reply in a concise style. Avoid unnecessary repetition or filler language.
Team Rules are managed from the dashboard on Team and Enterprise plans. Admins choose whether a rule is enforced. If it isn't, team members can toggle it off under Team Rules in Customize. Team Rules are free-form text, not folders, and they support glob patterns. With no glob, a Team Rule applies to every conversation.
When sources conflict, the order is Team Rules, then Project Rules, then User Rules. All applicable rules are merged, and earlier sources win on conflicts. The docs also warn that AI guidance shouldn't be your only security control.
Cursor rules not working: common mistakes#
Start with the type. The docs' own advice for a rule that isn't being applied: for Apply Intelligently, make sure a description is defined; for Apply to Specific Files, make sure the pattern matches the files involved.
Then check this list:
- Wrong extension. A
.mdfile in.cursor/rulesis ignored. Rename it to.mdc. alwaysApply: trueoverriding your plan. When it's true, globs and description are ignored.- Glob doesn't match.
*.tsis root only. Use**/*.tsfor any directory. - Nothing in context. A glob rule attaches when a matching file is in context. If the chat never touches a matching file, it won't show up.
- No description. A rule with no globs, no description, and
alwaysApply: falseis manual. You have to @-mention it. - User Rules in Inline Edit. User Rules aren't applied to Inline Edit (Cmd/Ctrl+K). Only Agent (Chat) uses them.
- Expecting Tab to follow rules. Rules don't affect Cursor Tab or other AI features.
- Expecting a file to be inlined. An
@filemention in a rule tells Agent where to look. It doesn't paste the contents. - Rules from a GitHub repo. Rules aren't imported on their own. Package them in a plugin and publish it through a marketplace; the repository needs a
.cursor-plugin/marketplace.json.
To see every rule and its status, open Customize and go to Rules.
Best practices for cursor rules#
The docs say good rules are focused, actionable, and scoped. In practice:
- Keep each rule under 500 lines, and split big ones into composable rules.
- Give concrete examples or point to referenced files.
- Write like clear internal docs. Avoid vague guidance.
- Reference files instead of copying them, so rules don't go stale.
- Skip what Agent already knows: full style guides (use a linter), common commands like npm, git, and pytest, and rare edge cases.
My advice: start simple and add a rule only when you see Agent make the same mistake twice. When it makes a mistake, update the rule. The docs also mention you can tag @cursor on a GitHub issue or PR to have Agent update the rule for you.
For current details, see the Cursor rules docs and the docs.cursor.com entry point.
Quick reference checklist#
- Project rules go in
.cursor/rulesas.mdcfiles. - Pick the type: Always Apply, Apply Intelligently, Apply to Specific Files, or Apply Manually.
- Globs: comma-separated, and
**/*.tsfor any directory. - Intelligent rules need a
description. - Manual rules need no globs or description, and you call them with
@rule-name. - Reference big files with
@file, and paste anything that must always be in context. - Use
AGENTS.mdfor simple, metadata-free instructions. - Check rules into git, and use
/create-ruleto generate new ones. - Precedence: Team Rules, then Project Rules, then User Rules.
Quick answers
Why are my Cursor rules not showing up?
Check the extension first: project rules must be .mdc, and a plain .md file in .cursor/rules is ignored. Then check the type. Intelligent rules need a description, and file-scoped rules need a glob that matches files in context.
Do Cursor user rules apply to Cmd/Ctrl+K?
No. User Rules are only used by Agent (Chat), not Inline Edit. Put the guidance in a project rule or use Agent instead.
How do I generate a Cursor rules file?
Type /create-rule in Agent and describe the rule. It writes a file with proper frontmatter into .cursor/rules. You can also use Customize → Rules → Add Rule.
Should I use AGENTS.md or .cursor/rules?
AGENTS.md is a simple plain markdown option for straightforward instructions, and it works in subdirectories too. Use .cursor/rules when you need frontmatter to control when a rule applies.
Did this solve it?
One tap. No account.
Sorry about that. What was missing?
from 0 readers
Saved you an hour? Send a tip.
USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.
Network
0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
On a computer? Scan the code with your phone wallet, or copy the address.
Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.
Discussion
Start the discussion
Next note