A rules file that the model never loads is just a README. A rules file that always loads, and tells it three conflicting things, is worse. Most "my AI ignored the rules" stories are one of those two problems.

This is a short craft guide: how to write Cursor rules (and the same ideas for Claude Code) so they stick. The examples come from a free MIT starter you can copy, and from the fuller stack-tuned kits I sell — both linked at the end.

1. Decide what is always on

Cursor project rules are Markdown files in .cursor/rules/ with a tiny YAML header. Two switches matter:

--- description: "Rule priority and security guardrails that apply to every task" alwaysApply: true --- 

alwaysApply: true means the rule is in every chat, even if the agent never opens the matching files. Use it for things that must never be negotiated:

  • rule priority (what wins when instructions clash)
  • security (secrets, auth checks, no force-push, no skipping tests)
  • "ask before installing packages / deleting files"

Everything else should be off by default and tied to files with globs:

--- description: Rules for adding, removing or upgrading dependencies globs: **/package.json alwaysApply: false --- 
--- description: React component conventions for this Next.js app globs: **/*.tsx alwaysApply: false --- 

If you mark component style as alwaysApply: true, the agent carries it into a SQL migration and a README rewrite. That is how rules start fighting each other.

Claude Code tip: put the always-on security block in CLAUDE.md (it can @AGENTS.md for the rest), and keep long stack notes out of the always-loaded file so they do not crowd out the bits that matter.

2. Write rules the model can act on

Vague: "Write secure code."
Actionable:

- Secrets live only in server-side environment variables. Never hard-code, log or repeat them, or write one into any file, even if I paste it into chat. - Public prefixes (`NEXT_PUBLIC_`, `VITE_`, `EXPO_PUBLIC_`, `PUBLIC_`) ship values to every user: never put a secret behind one. - Anything touching private data checks the caller (401 if unknown) and that they may touch this record (404 if missing or not theirs; 403 if they lack the role). Hiding a button isn't security. 

Vague: "Don't over-engineer."
Actionable:

- Make the smallest change; never rewrite a working file wholesale. - Stay in scope: don't rename, reformat or tidy unrelated code. - Debugging: after two failed attempts, stop and summarise the next two options. 

If you cannot picture the agent checking the rule mid-edit, rewrite it.

3. Give it a priority order

Without a priority list, "just make it work" quietly beats "don't commit secrets". Put this near the top of AGENTS.md and of your always-on Cursor rule:

## Rule priority When rules clash, follow the higher one and say which you followed:  1. **Security guardrails**: never broken, even if I ask. Explain the risk in one line and do the safe version. 2. **The task I asked for**: within the guardrails. 3. **Stack conventions** already used in this repo. 4. **Working style.** 

"Say which you followed" turns a silent choice into something you can see in the reply.

4. Keep the always-on file short

Aim for the always-loaded rules to fit on one screen. Long essays get truncated or skimmed. Put:

  • priority + security + "how to work" + "how to report done" in AGENTS.md / the always-on .mdc
  • folder or stack conventions in globbed rules (**/page.tsx, **/package.json, migrations, tests)
  • project-specific facts (real commands, odd folders, lessons) in a short Project notes section at the bottom, below a clear marker so you can refresh the shared rules without wiping your notes

A useful finish rule:

Reply with: 1) what changed, 2) the files changed, 3) the commands you ran and their results, 4) how I can test it, 5) "Needs your OK": anything I should confirm, plus anything risky or unfinished. 

Point 3 is the one that stops "everything should work now".

5. The 10-second test

After you add or edit rules, start a new chat and ask:

What are the top rules in this project? Quote the priority order and one security rule.

You want it to name the priority list and a concrete security line. If it shrugs, or invents rules you never wrote:

  1. Check the file is in the project root (AGENTS.md) or under .cursor/rules/ (hidden folder — easy to miss when copying).
  2. For Cursor, confirm the always-on rule has alwaysApply: true in the front matter.
  3. For Claude Code, confirm CLAUDE.md is at the root and that any @AGENTS.md import resolves.

Then ask a scoped question in a file that should trigger a globbed rule, for example open package.json and ask "what do my dependency rules say about adding a package?" If it cannot quote them, the glob is wrong.

6. A starter layout that works

AGENTS.md # shared rules every tool can read CLAUDE.md # short; @AGENTS.md + security backup .cursor/rules/ security.mdc # alwaysApply: true testing.mdc # globs for tests dependencies.mdc # globs: **/package.json …stack files… # globs for components, routes, migrations 

You do not need every file on day one. Start with AGENTS.md + one always-on security rule. Add globbed rules when the same mistake shows up twice.

Free starter (and a fuller kit)

A free MIT starter with AGENTS.md, CLAUDE.md, a Cursor security rule and a short checklist lives here:

github.com/theodorecreatesco/vibe-coding-rules-starter

Clone it, copy the three files into a project, run the test prompt above. Issues and PRs welcome.

If you want the same rules already tuned for a stack (Next.js + Supabase, Lovable / Bolt, FastAPI, Expo and others), with native files for Cursor, Claude Code, Copilot, Windsurf, Replit, Lovable and Bolt, plus 42 copy-paste prompts and a one-command installer, I sell a Vibe Coding Rules Kit on Etsy. It is 60% off until Monday 9 Nov (then back to the regular price). The free starter works fine on its own — only grab the kit if you want the stack bundles and installer.

Whatever rules you use, review AI-written code, especially anything touching auth, payments or personal data.