Writing rules
A rule
Section titled “A rule”Rules live in .rulecast-config.yaml:
repos: - repo: local rules: - id: backend/no-httpexception name: Services raise domain exceptions, not HTTPException files: '^app/services/.*\.py$' detect: regex: pattern: 'raise\s+HTTPException\((?<args>[^)]*)\)' message: "{{file}}:{{line}} raises HTTPException({{args}}) in the service layer. Raise a domain exception; the API layer maps it to a response." context: - "@conventions/backend.md#errors"filesselects what the rule applies to;detectnames one detector and its config.messageis what the agent reads. Named capture groups become template variables.contextpoints at the doc section that explains the rule — delivered alongside the finding.
A rule with context and no detect delivers guidance the first time an agent touches a matching file, with nothing to catch. That is how you carry over a convention no pattern can express.
The full format is in agents/reference/rule-format.md.
Refusing a write
Section titled “Refusing a write”Some rules are not advice. refuse_write: true refuses the edit before it happens, and the agent gets your message and the doc section in place of the tool’s result:
- id: codegen/no-edit-client files: '^src/client/' detect: path: {} refuse_write: true message: "{{file}} is generated from openapi.yaml. Edit the schema and run `pnpm codegen`."A refusal only ever rests on the text the agent is writing, never on a reconstruction rulecast is unsure of, and it happens once per file per session — so a rule can stop a mistake without trapping the agent. Generated code, vendored directories, files that must not change. Everything else is better reported after the write, which is what the other rules do.
That covers the edit tools. A write through Bash cannot be refused before it runs, because nothing knows what a command will write, so rulecast catches it right after: the agent is told the file is protected and how to revert it, it cannot stop until it has, and you are told which file it changed.
Turning a rule off
Section titled “Turning a rule off”-
A whole rule:
enabled: falseon the rule. Under a rule repo’s entry,- id: <rule>withenabled: falseswitches a catalog rule off and keeps the line. -
One finding: a comment on the matched line or the line above it, in the file’s own comment syntax. The reason is required; an ignore without one suppresses nothing.
# rulecast-ignore: python/no-httpexception-in-services legacy endpoint, removed in #412raise HTTPException(404)
rulecast run --all-files --summary counts the ignores, and an ignore or a config change made during an agent session is reported to you when the agent stops: the agent cannot quietly edit its way past a rule.