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](/docs/core-concepts/accounts-and-tenancy).
- Copy the example `Project` slice rather than inventing a shape for a new resource. See
  [Adding a Resource](/docs/building-features/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](/docs/billing-entitlements/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](/docs/building-features/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](/docs/cursor/skills-in-cursor).
