Docs · Working with Cursor

Rules for One Shot

The two .cursor/rules files the kit ships, what each one carries, and when to add your own.

Project rules live in .cursor/rules as .mdc files, and they are version-controlled, which is the whole point: a rule that only exists in your editor settings does not travel to the next person or the next machine. The kit ships two of them, and between them they carry the handful of conventions that fail silently when an agent does not know about them.

The format

An .mdc file is markdown with three optional front-matter fields:

  • description, a sentence explaining what the rule covers. The agent reads this to decide whether to pull the rule in.
  • globs, file patterns. The rule attaches when the agent works on a matching file.
  • alwaysApply, a boolean. When true, the rule is in context for every request.

Those three fields give four ways a rule can apply: always, intelligently based on the description, on specific files via the globs, or manually when you @-mention it by name in chat.

one-shot.mdc: the rules that are always on

This one is alwaysApply: true and has no globs, so it is in context for everything. It is short on purpose. The full map is CLAUDE.md, which is nine kilobytes and would be wasteful to carry on every request; the rule carries only the things that are wrong in a way you will not notice:

  • Account scoping. Every model holding customer data gets an account_id with a foreign key, every query goes through Current.account.things rather than Thing.all, and every controller authorizes with Pundit. This is the rule that keeps one customer from seeing another's data, and it is the one worth spending always-on context on. See Accounts and Tenancy.
  • Copy the example Project slice rather than inventing a shape for a new resource. See Adding a Resource.
  • Whether a feature is paid or free, because that decides include RequireEntitlement and no agent can infer it. See Gating a Feature.
  • External services go through an adapter and fake seam, never a direct API call from a controller. See The Adapter+Fake Pattern.
  • bin/check is the definition of done.
  • The source-of-truth files to read instead of guessing, and the fact that app identity is centralized in config/initializers/app_identity.rb.

controllers.mdc: the rules scoped to where they matter

This one sets globs: app/controllers/**/*.rb,app/views/**/*.erb,app/javascript/controllers/**/*.js and leaves alwaysApply false, so it attaches only when the agent is working in those files. That scoping is deliberate. The rules it carries are about the Content Security Policy, and they are irrelevant in a model or a job.

What it covers, all of it a failure with no exception, no flash, and nothing in the network tab:

  • Authorize every action, and look records up through Current.account so a foreign id 404s.
  • A form that redirects off-site needs its host added to policy.form_action in config/initializers/content_security_policy.rb, because form-action covers the whole navigation a form starts, including the redirect.
  • That same form also needs data-turbo="false", or Turbo submits it with fetch and tries to follow the cross-origin redirect as an XHR, which connect-src blocks. Both conditions must hold.
  • Interactive behaviour is an external Stimulus controller, never an inline <script>, because script tags carry a nonce and inline JavaScript is dropped.
  • New UI uses the Terminal design system classes rather than one-off styles.

Each of these is pinned by a spec, so a rule that gets ignored still gets caught. The rule exists to save you the round trip.

Adding your own

Type /create-rule in Agent and describe what you want. Cursor writes the file into .cursor/rules with the front matter already correct, which is faster than getting the fields right by hand.

Two things worth knowing when you do. Keep a rule under 500 lines, and split a rule that outgrows that into several composable ones rather than letting one file sprawl. And prefer a glob-scoped rule to an always-on one wherever the guidance is specific to a layer: always-on context is spent on every single request, including the ones where the rule cannot possibly apply.

The natural candidates in a product built on this kit are the conventions that are yours rather than the kit's: your domain vocabulary, the shape of your own service objects, a house style for copy. The kit's own conventions are already covered.

Next

See which of the kit's skills work in Cursor, and how to reach them: The Kit's Skills in Cursor.