v0.36.2

Rules

Rules are project-specific instructions the agent follows. They use Cursor's rule format, so a project that already has Cursor rules needs no second copy of them.

Rules are resolved from the project root — the nearest ancestor with a .git (or, failing that, the topmost one with a .cast/). A session started in a subdirectory therefore sees the same rules as one started at the root: cd apps/web && cast gets the repository's rules, not none. The home directory is never a root, so ~/.cast stays global configuration.

cast reads, in this order:

Both .md and Cursor's .mdc are read, and subfolders inside a rules directory are for organisation — a rule keeps the scope of the rules directory it lives under, however it is filed.

Rule Types

There are four apply modes, matching Cursor's rule anatomy:

Always Apply

---
always-apply: true
---

Follow these conventions in every response.

Injected into the system prompt every turn. The globs field is ignored.

Auto Attach

---
always-apply: false
globs: ["**/*.ts", "**/*.tsx"]
---

Use strict TypeScript with no `any` types.

Automatically injected when matching files enter the agent's context (via read/write/edit). Once activated, the rule stays for the rest of the session ("sticky").

Agent Requested (Lazy)

---
always-apply: false
description: Use when writing database migrations
---

Always create reversible migrations with both up and down.

The agent sees the rule's name and description in its system prompt. It reads the full content via the read tool when the task seems relevant.

Manual

---
always-apply: false
---

Special instructions for edge cases.

Only activated by @rule-name mention in a message or /rule:<name> command.

Rule Placement

LocationScopeTrust
~/.cast/rules/Global (all projects)Always loaded
.cast/rules/Project rootTrust-gated
.cursor/rules/Project root (a Cursor project's own rules)Trust-gated
apps/web/.cast/rules/Nested subtreeTrust-gated

Nested Rules

Rules can live in .cast/rules/ directories at any depth in the project tree (up to 8 levels). A nested rule at apps/web/.cast/rules/style.md has scope apps/web — its always/auto injection only fires once a context file under apps/web/ is seen.

This matches Cursor's nested rules feature: rules are dormant until the agent touches files in their subtree.

File Format

---
name: api-style
always-apply: false
globs: ["src/api/**/*.ts"]
description: API endpoint conventions
---

## API Endpoints

- Always return typed responses
- Use zod for input validation
- Handle errors with the shared error middleware

Frontmatter Fields

FieldDescription
nameHuman label (defaults to the filename without its extension)
always-applytrue for always mode; false + globs/description for other modes
globsGlob patterns for auto attach mode — a YAML array, or one comma-separated string (globs: *.ts, *.tsx)
descriptionDescription for agent-requested (lazy) mode

Glob syntax

Patterns are matched against the file's path relative to the project root, the same way Cursor and minimatch read them:

PatternMatchesDoes not match
*.tsmain.tssrc/main.ts
**/*.tsmain.ts, src/deep/main.tsmain.js
src/*.tssrc/main.tssrc/deep/main.ts
src/**/*.tssrc/main.ts, src/deep/main.tslib/main.ts
docs/**everything under docs/other/x.md
*.{ts,tsx}main.ts, main.tsxmain.js

* and ? never cross a /; only ** does. To match a file type anywhere in the project, write **/*.ts rather than *.ts.

A rule in a nested .cast/rules directory writes its globs relative to its own subtree: apps/web/.cast/rules/style.md with globs: src/**/*.ts matches apps/web/src/a.ts.

The apply mode is determined automatically from the frontmatter:

@-Mentions

Reference a rule in your message by typing @rule-name:

@api-style review this endpoint

This activates the rule for that turn, regardless of its apply mode. Matching is by the bare name (case-insensitive). Code fences are skipped — @name inside a code block doesn't trigger.

Commands

CommandDescription
/rulesList all loaded rules with their apply mode, globs, scope, and source
/rule:<name>Invoke a rule by name (loads full content into context)

The /rules output shows each rule's state:

Rules
  api-style [auto:globs] globs=["src/api/**/*.ts"] (project) — API endpoint conventions
  security [always] (global) — Security review checklist
  migration [lazy] (project) — Database migration conventions
  edge-cases [manual] (project) — Special edge case handling

Auto rules show [auto:sticky] once they've been activated for the session, or [auto:globs] if they haven't matched yet.

A rule file cast could not read (wrong permissions, a broken symlink) is listed separately with the reason. One bad file never stops the others from loading, but it is no longer dropped in silence either.

Priority

On a name collision (same id), the first-loaded rule wins:

  1. Project (.cast/rules/, then .cursor/rules/) — highest priority
  2. Global (~/.cast/rules/)

Within one scope, project beats global and the first-loaded file wins.