Project rules
Project rules are markdown files in .dsc/rules/ that the model loads on demand or by convention. Use them for: codebase conventions, architectural constraints, gotchas a brand-new contributor would need.
The system is modeled after Cursor's rule engine — same frontmatter shape, same three-way loading semantics — so existing rule files port over with no changes.
Three categories
How a rule loads is decided by its YAML frontmatter. There are three categories, in order of how aggressively they get pulled in:
- Always-on — frontmatter
alwaysApply: true. Loaded into the system prompt every session, every turn. Use sparingly; every always-on rule is a tax on your context window. - Glob-triggered — frontmatter
globs: ["src/**/*.ts"]. Auto-attached when a matching file is touched. Pattern syntax is gitignore-style (viapathspec) sosrc/api/**/*.pydoes what you'd expect. - Request-only — neither
alwaysApplynorglobs. The model uses therequest_ruletool to load by name when relevant. The rule'sdescriptionis what shows up in the "available" list — make it good, that's the model's only signal.
File format
Markdown with optional frontmatter:
---
description: "How to add a new model to the rate card"
globs: ["src/lib/pricing.ts"]
---
# Adding a new model
When you add a model to `src/lib/pricing.ts`:
1. Add the rate card object with `source: "deepseek_published_full_retail"`.
2. Run `npm run sync-pricing` to mirror to the Worker.
3. Commit BOTH `src/lib/pricing.ts` and `proxy-worker/src/pricing.ts`.
The CI guard will fail your PR if the two files drift.Frontmatter is parsed with python-frontmatter (standard YAML between two --- fences). All fields are optional. If you omit name:, the file stem becomes the rule ID — so pricing.md exposes a rule named pricing.
Where they live
.dsc/rules/— project rules. Walk-up search: Fred starts at your cwd and climbs toward$HOME, taking the first.dsc/rulesit finds. Stops at home, never picks the user-global dir as a "project."~/.dsc/rules/— user-global rules. Always loaded, layered behind project rules.
Both load. Project wins on name collision — your repo's style.md shadows your user-global style.md, which is the right default for shared codebases.
Listing rules
Inside the REPL, /rules shows two sections:
- Active — rules loaded right now (always-on + any glob-matched + any explicitly requested by the model this session).
- Available — rules with a description that aren't currently active. The model can pull these in via
request_rulewhen they look relevant.
If /rules prints nothing, you don't have any rules yet. Drop a markdown file into .dsc/rules/ and re-run.
Authoring tips
- Title with
# H1— the model uses it as the rule's display name when rendering the active block. - Keep each rule focused — one concept per file. A 12-section monolith is harder for the model (and you) than a directory of small named rules.
- Lead with the rule itself, then a "Why" line, then "How to apply." The model reads top-down; put the prescriptive bit first.
- Resist the urge to write the rule "for an AI." Write it like an onboarding doc for a junior engineer; the model handles either fine but humans only handle the latter — and you'll be the one re-reading these in six months.
- Use
descriptionfor request-only rules even if you also useglobs. The description is what the model sees in the "available" list; an empty description means the rule never gets surfaced for explicit pickup.
Use cases
The kinds of things that pay for themselves the moment you write them down:
pricing.md— "Always runnpm run sync-pricingafter editingpricing.ts; the CI guard will fail you otherwise."money-types.md— "We use Drizzle'sbigintfor money columns, never floats. Microcents is the storage unit; convert at the edges."auth-audit.md— "Auth flows must update theaudit_log. Look at the existing magic-link handler for the pattern."migrations.md— "Migrations live insrc/db/migrations/and are numbered. Don't edit a migration that's already shipped."worker-imports.md— "The Worker can't import fromsrc/. If you need shared code, mirror it viascripts/sync-pricing.ts."
Treat .dsc/rules/*.md as a living onboarding doc. If you find yourself explaining a sharp edge to a teammate three times, write a rule. The next person to hit it (human or model) will thank you.
Disabling rules
Set DSC_RULES=0 to skip the rule system entirely — useful for testing without the always-on injection. The default is on.
Related
See /docs/configuration for the broader .dsc/ directory and how settings, hooks, and rules fit together. See /docs/slash-commands for the full /rules command surface.