Writing Rules

Define what matters to your team as markdown files with YAML frontmatter.

1. RULE FORMAT

Rules live in .saguaro/rules/ as markdown files with YAML frontmatter. Each rule defines a single convention or constraint that Saguaro enforces during review.

FieldRequiredDescription
idYesUnique identifier, kebab-case
titleYesHuman-readable name
severityYeserror (blocks, exit 1), warning (logged), or info
globsNoFile patterns to match. Default: all files. Prefix ! to exclude.
.saguaro/rules/no-console-log.md
1---
2id: no-console-log
3title: No console.log in production code
4severity: warning
5globs:
6 - "**/*.ts"
7 - "**/*.tsx"
8 - "!**/*.test.ts"
9---
10
11console.log, console.warn, and console.debug should not appear in
12production code. Use a structured logging library instead.
13
14### Violations
15
16\`\`\`
17console.log("Processing order", orderId, customerEmail);
18\`\`\`
19
20### Compliant
21
22\`\`\`
23logger.info("Processing order", { orderId });
24\`\`\`

2. GETTING RULES INTO YOUR REPO

2.1Generate from codebase sag rules generate analyzes your code and proposes rules based on patterns and conventions it detects in your project.

1# Analyze your codebase and propose rules
2sag rules generate

2.2Create with AI assistance sag rules create [target] creates a rule scoped to a specific directory or file pattern, using AI to draft the rule content.

1# Create a rule scoped to a specific directory
2sag rules create src/api

2.3Write by hand — create a .md file in .saguaro/rules/ following the format above. This gives you full control over the rule content and structure.

3. WHAT MAKES A GOOD RULE

3.1Specific — targets a concrete behavior, not a vague guideline. A good rule describes exactly what to do and what not to do.

3.2Scoped — uses globs to target only relevant files. A rule about API error handling should match src/api/**/*.ts, not everything.

3.3Has examples — includes ### Violations and ### Compliant sections with code snippets so the AI reviewer knows exactly what to look for.

3.4Right severity error for things that must block, warning for preferences, info for suggestions.

.saguaro/rules/use-custom-errors.md
1---
2id: use-custom-errors
3title: Use AppError instead of generic Error
4severity: error
5globs:
6 - "src/**/*.ts"
7 - "!src/**/*.test.ts"
8---
9
10Always throw AppError with a specific error code instead of generic
11Error. This ensures consistent error handling and makes errors
12programmatically distinguishable.
13
14### Violations
15
16\`\`\`typescript
17throw new Error("User not found");
18throw new Error(\`Invalid input: \${value}\`);
19\`\`\`
20
21### Compliant
22
23\`\`\`typescript
24throw new AppError("USER_NOT_FOUND", "User not found");
25throw new AppError("INVALID_INPUT", \`Invalid input: \${value}\`);
26\`\`\`

4. WHAT MAKES A BAD RULE

  • Kitchen-sink rules that try to enforce too many things at once — split them into focused, single-purpose rules
  • Rules that duplicate linter checks — use ESLint or Biome for formatting and syntax. Saguaro rules are for higher-level conventions that static analysis cannot catch.
  • Overly broad globs that match files the rule does not apply to — a React component rule should not match *.test.ts files
  • Vague instructions like "write clean code" — the AI reviewer needs concrete, actionable guidance to produce useful results

5. MANAGING RULES

Saguaro provides CLI commands for managing your rules directory.

CommandDescription
sag rules listList all rules
sag rules explain <id>Show full details for a rule
sag rules validateCheck rule structure and frontmatter
sag rules delete <id>Delete a rule by its ID
sag rules locatePrint the rules directory path

6. TIPS

  • Version control your rules alongside code — they are part of your project's conventions
  • Review rules in PRs like you review code — rule changes affect the entire team
  • Start with a few high-value rules, then add more as patterns emerge from real reviews
  • Use sag rules validate in CI to catch malformed rules before they reach production
  • Globs use repo-root-relative paths, so rules work correctly in monorepos. Scope rules to specific directories like src/api/**/*.ts rather than broad wildcards.