Cursor Rules: Setup, Best Practices, and Examples

A young man with short hair smiles widely. The image is in black and white and framed by a light blue hexagon, representing a focus on Shift-Left Security in CI/CD practices. Matt Tanner   |   Aug 21, 2026

Share on LinkedIn
Share on X
Share on Facebook
Share on Reddit
Send us an email
A computer screen shows a search bar with the query What StackHawk rules do you have? and results explaining always-on HawkScan rules, on-demand rules, and best practices for configuring StackHawk’s security tests, including expert guidance on managing cursor rules.

Cursor generates code that ignores your project’s conventions, puts files in the wrong directory, or reintroduces a pattern your team dropped six months ago. Not because the model is bad, but because it starts every session knowing nothing about how your team works. Cursor rules are how you fix that: instructions Cursor supplies to the agent automatically, so you stop having to retype them.

This guide covers the four rule types, how to write .mdc files, how to debug a rule that isn’t firing, where rules end and skills begin, and what rules can and can’t do for security.

What Are Cursor Rules?

Cursor rules are reusable instructions that Cursor includes in the model context for every Agent session to which they apply. Language models don’t retain memory between completions, so anything the agent should consistently know about your project, stack, or standards has to be re-supplied every time. Rules automate that.

A rule is a small Markdown file that tells the agent things like “we use named exports, not default exports” or “every new endpoint needs an authorization check.” Cursor includes it in context whenever it applies, so you don’t have to type it.

Every rule Cursor includes consumes part of the same context window as your code, which is the constraint behind most of the advice below.

The single .cursorrules file in your project root is the legacy format. Cursor still reads it, but Cursor itself describes it as legacy and slated for deprecation, with migration steps that end with “delete the .cursorrules file from your project root.” The current system is Project Rules, which use individual .mdc files in .cursor/rules/.

Project rules must use the .mdc extension, because the rules system reads description, globs, and alwaysApply from frontmatter. For plain Markdown with no configuration, use AGENTS.md instead.

The Four Rule Types and Where Each Belongs

Cursor supports four rule types, each solving different problems.

Project Rules are .mdc files in .cursor/rules/, version-controlled with your code. Most of your Cursor project rules belong here, so teammates get them on the next pull.

User Rules are global to your Cursor environment. Set them under Customize → Rules. They suit personal preferences like “reply concisely” and apply to Agent (Chat) only.

Team Rules are managed from the Cursor dashboard on Team and Enterprise plans. Admins can enforce them, making the rule required for everyone and removing the option to disable it. This is the only rule type that gives an organization a hard floor rather than a suggestion.

AGENTS.md is plain Markdown in your project root, with no frontmatter and no configuration.

Two behaviors are easy to miss:

  • Nested AGENTS.md files are combined with their parents rather than replaced. The more specific instruction wins only where the two conflict.
  • Cursor reads CLAUDE.md the same way it reads AGENTS.md. Put one in your project root and Cursor picks it up. Per Cursor’s help docs, CLAUDE.md is applied to every conversation regardless of any alwaysApply setting, so a long one is an always-on context cost.

When more than one source applies, Cursor merges them in a fixed order: Team Rules, then Project Rules, then User Rules, with earlier sources taking precedence in case of conflict. An enforced Team Rule therefore overrides any User Rule that conflicts with it.

Cursor also identifies rules by full file path, not filename. Two rules named api.mdc in different folders both apply if their conditions match; there is no filename-based override.

A reasonable split: Team Rules for what is non-negotiable across every repo, Project Rules for one codebase’s stack and conventions, User Rules for your own ergonomic preferences.

How Cursor Decides When a Rule Applies

Each Project Rule declares how it activates through three frontmatter fields, and the combination determines behavior, per Cursor’s rules documentation:

Rule typealwaysApplydescriptionglobsBehavior
Always ApplytrueignoredignoredIncluded in every chat session
Apply to Specific Filesfalsenot usedprovidedAuto-attached when a matching file is in context
Apply IntelligentlyfalseprovidedomittedAgent reads the description and pulls the rule in when relevant
Apply ManuallyfalseomittedomittedOnly included when you @-mention the rule
Flowchart showing how rules apply, following Cursor Rules Best Practices: Checks if alwaysApply is true, globs are set, or description is set—leading to four options: Always Apply, Apply to Specific Files, Apply Intelligently, or Apply Manually.

Caption: The same four rows as the table above, in the order you actually debug them.

Those four names are the current ones in Cursor’s UI and docs. If you’ve read older guides referring to “Auto Attached” or “Agent Requested,” that’s the same mechanism under retired names.

Four code snippets in dark boxes compare settings—Always Apply, Apply to Specific Files, Apply Intelligently, and Apply Manually—each showing different configurations for alwaysApply, globs, and descriptions. These examples highlight how implementing Cursor Rules Best Practices can streamline your configuration process and ensure optimal rule application across your codebase.

Caption: Whatever the UI shows you, these three fields are what actually decide when a rule fires.

A useful starting point is one Always Apply rule carrying project context: the tech stack, the folder layout, and the two or three conventions that hold everywhere. Keep it short, since Cursor includes it in every Agent chat alongside any applicable Team Rules, User Rules, AGENTS.md, and CLAUDE.md.

How to Write an .mdc Rule File

An .mdc file is frontmatter plus content. The frontmatter controls activation; the content is the actual instruction. Here’s a glob-scoped rule that auto-attaches whenever a migration file is in context:

---
globs: src/db/migrations/**/*.sql
alwaysApply: false
---

- Every migration needs a matching down migration in the same file
- Never DROP or rename a column in the same release that stops writing to it; split across two deploys
- Add an index in its own migration, never alongside a schema change
- Prefix the filename with a UTC timestamp, not a sequence number

And an Apply Intelligently rule, where the description is the only thing the agent reads when deciding whether the rule is relevant:

---
description: How this codebase handles background jobs, retries, and idempotency. Use when adding, editing, or debugging anything that runs off the request path.
alwaysApply: false
---

- Jobs live in src/jobs/ and take a single serializable payload argument
- Every job must be safe to run twice; key idempotency off the payload, not off job state
- Retries are configured per job, never globally; default is 3 with exponential backoff
- A job that calls a third-party API records the outbound request ID before awaiting the response

The description in the second example is deliberately long. It is the only field the agent evaluates when deciding whether an Apply Intelligently rule is relevant, so naming the situations it covers gives the agent something concrete to match against. “Background job conventions” does not.

Glob patterns behave conventionally: **/*.ts matches TypeScript files anywhere, src/** matches everything under src/, and comma-separated patterns combine scopes. Scope narrowly where you can, since an Always Apply rule is included whether or not it is relevant.

Creating your first rule in four steps

# macOS / Linux / WSL
mkdir -p .cursor/rules
# Windows PowerShell
New-Item -ItemType Directory -Force .cursor/rules
  1. Make the directory. mkdir -p .cursor/rules in your project root (New-Item -ItemType Directory -Force .cursor/rules in PowerShell).
  2. Add one .mdc file, named for the concern it covers. Kebab-case works well: migrations.mdc, api-errors.mdc. Resist the urge to make a single rules.mdc holding everything.
  3. Set the frontmatter for how you want it to fire. Start with globs for rules about specific files, and with a description for rules about situations. Leave alwaysApply: false unless the rule genuinely belongs in every conversation.
  4. Test it before you trust it. Open a new Agent chat and prompt something the rule should shape. If nothing changes, @-mention the rule by name. Behavior changing under the mention means your frontmatter is wrong; behavior staying the same means the rule text is too vague.

Then commit it, so teammates and any remote or CI environment get the same rule.

Two shortcuts: /create-rule in Agent chat generates a rule file with correct frontmatter from a description, and Customize → Rules → + New creates one through the GUI. If + New is missing, check the scope picker; selecting more than one scope hides every creation control on that tab. Subdirectories work as your set grows, so .cursor/rules/frontend/components.mdc is picked up like any top-level rule.

Why Your Cursor Rule Isn’t Working

Most Cursor rules that appear broken are activation problems, not content problems. Work through these in order.

The extension is wrong. Project rules must use .mdc. Cursor ignores plain .md files in the rules directory without warning or error, so check this before anything else.

The glob pattern doesn’t match what you think. A typo never matches, and neither does a pattern anchored at the wrong level. A glob-scoped rule also needs a matching file actually in context: ask about app/routers/users.py without that file open or referenced, and a rule scoped to app/routers/**/*.py won’t attach. Too broad fails the other way, since **/*.py attaches to every Python file in the repo and dilutes the guidance.

The description is too vague. “Error handling rules” gives an Apply Intelligently rule nothing to match against. Name the situations it covers, as in the background-jobs example above.

The rule was included, but later responses stopped following it. Before blaming the rule, check that it still applies to the files and the task now in context. If a long conversation has simply drifted, restate the constraint in your next prompt or start a fresh chat. Rules with concrete code examples hold up better against this than rules written as prose.

Two rules disagree. Conflicting instructions are the hardest case to spot, because the agent follows one of them and the output looks deliberate. If the behavior seems arbitrary, check whether an Always Apply rule conflicts with a more specific rule.

One test isolates all of these: force the rule by typing @ and the rule name. If the behavior changes, the content is fine, and the activation config is wrong. If it doesn’t, the frontmatter is fine, and the rule text is too vague to act on.

Cursor Rules Best Practices

Cursor’s official guidance on writing rules is a pretty solid place to start: keep rules under 500 lines, split large rules into multiple composable ones, provide concrete examples, and reference files rather than pasting their contents so rules don’t go stale as code changes.

I also really like this blog that Atlan’s engineering team published with four practices from several months of production use:

  • Be assertive, not suggestive. “Consider using TypeScript interfaces” permits several valid outputs. “Always define TypeScript interfaces for component props” permits one. Atlan’s framing is to write rules as if onboarding a very fast, very literal intern.
  • Put the important context last. Atlan found the model tends to prioritize information at the end of a rule file, so they flipped their structure to end with the part that matters most.
  • Roughly one concept per rule. Atlan’s benchmark is under 50 to 80 lines per rule, which is well below Cursor’s 500-line ceiling and closer to what actually stays maintainable.
  • Write rules reactively. Their cue for writing a new rule is the moment you think “ugh, it did that again.” Cursor’s docs give the same advice from the other direction: add rules only when you notice the agent repeating a mistake. Either way, don’t try to encode your entire engineering handbook up front.

What to leave out matters as much. Don’t copy style guides into rules, since a linter enforces formatting better than a prompt. Don’t document commands the agent already knows, like npm or git. Don’t encode rare edge cases.

Treat the rule set like code: check the directory into git, review changes in pull requests, prune periodically. The cost of a large set is less about tokens than selection accuracy, since the more near-duplicate descriptions the agent chooses between, the worse its choices get. Review after any refactor or folder rename. A rule pointing at app/api/ after you moved everything to app/routers/ does not error; it stops firing.

Cursor Rules vs Skills

Cursor documents rules and skills as separate customization primitives and draws the line this way: rules are short guidelines and constraints, skills are multi-step workflows and procedures. The table below adapts Cursor’s comparison and adds a row on invocation.

RulesSkills
PurposeShort coding guidelines and constraintsMulti-step workflows and procedures
LengthA few lines to a few hundredOften longer, with step-by-step instructions
How appliedIncluded as context in every or matching conversationInvoked on demand
Invoked byAutomatic inclusion or @-mention/skill-name, @skill-name, or the agent autonomously
Example“Use TypeScript for all new files”“Deploy to staging: run tests, build, deploy, verify”

A skill is a folder containing a SKILL.md, plus optional scripts/, references/, and assets/ subdirectories. They live in .cursor/skills/ or .agents/skills/ per project, and ~/.cursor/skills/ or ~/.agents/skills/ globally. Cursor also loads .claude/skills/ and .codex/skills/, which is why a skill written for one agent often works in another. Skills follow the Agent Skills open standard.

Cursor is moving one rule type into skills, though. The built-in /migrate-to-skills skill, available in Cursor 2.4 and later, helps with this and converts Apply Intelligently rules into standard skills. Those are the ones with alwaysApply: false and no globs that the agent pulls in based on description. Rules with alwaysApply: true or specific glob patterns are left alone, and so are User Rules.

The migration leaves Always Apply and glob-scoped rules alone because their triggering behavior has no equivalent in skills. If you’re reaching for a description-driven rule to hold something long and procedural, write a skill instead.

Distribution blurs the line, because some vendors ship tooling that installs as rules. Our agent skills work this way for Cursor, where an install script writes a set of modular stackhawk-*.mdc files into .cursor/rules/, alongside skills in .cursor/skills/. Most of those rules are Apply Intelligently, the same type /migrate-to-skills converts, which is why the repo ships skills alongside them.

Security Rules: What They Can and Can’t Do

Security is tempting to encode in rules, and easy to overestimate. A security rule is worth writing. It is also just a prompt.

A well-scoped one catches a real class of problems at the moment code gets written:

---
globs: src/api/**/*.ts
alwaysApply: false
---

- Never build SQL from string concatenation; use parameterized queries
- Every new endpoint must include an explicit authorization check before data access
- Validate and type all request inputs at the route boundary

The limits show up quickly, though. A rule can’t confirm the generated code actually enforces authorization at runtime. It can’t tell you whether the endpoint it just wrote is reachable without authentication. And it can’t catch the vulnerability introduced three files away from where the rule applied. Cursor’s own documentation even mentions that “AI guidance should not be your only security control.”

A rule shapes what gets generated. Only running the application tells you what the generated code actually does. That is the gap that dynamic application security testing (DAST) and runtime testing fill: they exercise the running app rather than read the source code.

Our HawkScan skill runs that step inside the coding session rather than after it. The agent writes the feature, scans the running app, reads the findings, applies fixes, and rescans to confirm the vulnerability is gone. The rescan is the part a rule file cannot do.

Installing our agent skills into Cursor

Before you start, you’ll need:

  • A StackHawk account
  • The hawk CLI, authenticated with hawk init --browser locally, or HAWK_API_KEY supplied as a secret in CI
  • An application running somewhere the scanner can reach
  • A look at .cursor/hooks.json if your project already configures hooks, since the installer writes that file

1. Install into your project

git clone https://github.com/stackhawk/agent-skills.git
bash agent-skills/scripts/install.sh --platform cursor --target .

Running this command should output something similar to this:

Terminal output shows Cursor rules, skills (DAST scanning, API reporting, CI/CD pipeline, data seed, scan optimization), and hooks (configuration, scan reminder) installed in respective directories—demonstrating adherence to Cursor Rules Best Practices throughout the setup.

That writes three things:

PathWhat lands there
.cursor/rules/Modular stackhawk-*.mdc rules
.cursor/skills/The scanning, reporting, and CI skills
.cursor/hooks/stop.shThe stop hook

As of the writing of this post, August 2026, that’s 25 rules and five skills, though the repo moves. --target . installs into the repo; our docs use --target ~ for a global install. Project-scoped is usually right, for the same reason any rule describing the codebase belongs in it.

2. Confirm the rules loaded

Ask the agent “what StackHawk rules do you have?” and it should describe what it can now do.

A computer screen shows a dark-themed chat interface discussing StackHawk rules, HawkScan, Cursor Rules Best Practices, and project files. The left sidebar displays navigation options and file lists; code snippets and links are visible in the main window.

 If it doesn’t, you have an activation problem, and the same debugging steps from earlier apply.

3. Configure and scan

From there it’s conversational:

  • “Set up HawkScan for my Express API” generates a stackhawk.yml from your stack
  • “Scan my app running on localhost:8080” runs the scan and parses what comes back

The rules are what teach the agent to do this without you explaining the tool first.

What the stop hook does

This part is worth understanding even if you never install any of it. When the agent loop ends, the hook:

  • Checks whether code files changed without a scan having run
  • Instructs the agent to run one if so
  • Stays quiet on documentation-only changes, or when a scan already ran

That pairing generalizes beyond security: a rule states the standard, and a hook picks the moment to enforce it.

For the longer walkthrough, our guide to writing secure code with Cursor covers the workflow end to end, and our AI security docs cover configuration and the other supported agents.

Where to Find Example Rules

You rarely need to start from a blank file:

  • awesome-cursorrules: a large collection organized by framework and language. Despite the name, it uses the current .mdc format, and its contributing guide requires description, globs, and alwaysApply frontmatter. Covers Next.js and FastAPI stacks through to a DevSecOps rule on secret handling.
  • cursor.directory: now a plugin marketplace rather than a pure rules directory, with a one-click “Add to Cursor” install. Most rule bodies are still frontmatter-free prompt text, so expect to add activation config yourself.
  • dotcursorrules.com: a directory of submitted rules, still heavy on legacy .cursorrules single-file content that needs converting.

Treat these as starting points, not drop-ins: they encode someone else’s conventions, and the whole point of rules is encoding yours.

Final Thoughts

Four decisions cover most of what you need from Cursor rules. Start with two or three rules aimed at mistakes the agent actually repeats in your repo. Scope each one as narrowly as its subject allows, and keep the Always Apply set short. Check activation before rewriting a rule’s content. Move long procedural instructions into skills.

And be clear about what rules are: guidance, not enforcement. Where output has to meet a standard rather than merely aim at one, put a test behind it. That is the part we handle for application security.

Cursor Rules FAQ

What are Cursor rules?

Cursor rules are standing instructions supplied to Agent whenever they apply, so you don’t retype them every session. They come in four forms: Project Rules as .mdc files in .cursor/rules/, User Rules set in Customize, Team Rules managed from the dashboard, and plain AGENTS.md files. Only Project Rules use frontmatter.

Where should I put Cursor rules?

Project-specific rules go in .cursor/rules/ as .mdc files, checked into git. Personal preferences go in User Rules under Customize. Simple projects can skip the structure and use AGENTS.md in the project root.

How do I add rules to Cursor?

Create an .mdc file in .cursor/rules/ by hand, type /create-rule in Agent chat, or use Customize → Rules → + New. To pull rules from a repository, cloning into .cursor/rules/imported/ is more reliable than the documented import UI:
git clone .cursor/rules/imported/

Why isn’t my rule being applied?

Check activation before content. Confirm the file uses .mdc, since plain .md in .cursor/rules/ is ignored. Confirm the type matches how you expect it to fire: Apply Intelligently rules need a specific description, file-scoped rules need globs matching a file actually in context. Then force it with @rule-name; if behavior changes, the config is the problem.

Do rules affect Cursor Tab or Inline Edit?

No. Rules apply to Agent (Chat) only, not Cursor Tab, not Inline Edit (Cmd/Ctrl+K), and not Bugbot PR reviews. Bugbot has its own surface: put repository-specific review guidance in .cursor/BUGBOT.md.

Should I use a rule or a skill?

Use a rule for short standing guidance, a skill for a detailed procedure the agent runs on demand. If it’s long and step-by-step, it’s a skill, and /migrate-to-skills converts description-driven rules of that shape.

Are Cursor rules worth it?

They pay off when they prevent a correction you are already making repeatedly, and cost you when written speculatively: always-on rules spend context every session, and conditional ones add selection and maintenance overhead even when they don’t load. Start with two or three aimed at mistakes the agent actually makes in your repo.

More Hawksome Posts

What We Learned Watching Engineers Use AI Agents for Real Work

What We Learned Watching Engineers Use AI Agents for Real Work

We spent months watching engineers use AI coding agents on real engineering work. Not demos. Not benchmarks. Actual teams, actual code, actual deadlines. This is not a post about a product. It is a post about patterns. Here is what showed up, and here is what surprised us. The...