Rule Engine
Rule Engine#
The rule engine lets you customize review behavior per file and per PR using a declarative expression language. Rules are defined in the [[rules]] array in your config file.
Rule Structure#
[[rules]]
name = "skip-generated"
condition = 'file.path matches ".*\\.gen\\..*"'
priority = 10
[[rules.actions]]
type = "skip_file"
Each rule has:
name – a human-readable label (required)
condition – an expression that evaluates to a boolean (required)
priority – rules with higher priority are evaluated first (default: 0)
actions – a list of actions executed when the condition is true
Expression Language#
Grammar#
Expressions follow this precedence (lowest to highest):
|| (logical OR)
&& (logical AND)
! (logical NOT, prefix)
Comparison: ==, !=, >, <, >=, <=
Membership: in [...]
String operations: matches, contains, starts_with, ends_with
Arithmetic: +
Primaries: identifiers, numbers, strings, booleans, parenthesized expressions
Keywords and, or, not are accepted as aliases for &&, ||, !.
Operators#
| && / and | a && b | Short-circuit logical AND |
| || / or | a || b | Short-circuit logical OR |
| ! / not | !a | Logical negation |
| == | a == b | Equality (cross-type for numbers and strings) |
| != | a != b | Inequality |
| > | a > b | Greater than |
| < | a < b | Less than |
| >= | a >= b | Greater than or equal |
| <= | a <= b | Less than or equal |
| + | a + b | Numeric addition |
| in | a in [b, c] | Membership test against a list |
| matches | a matches "regex" | Regex match (full Rust regex syntax) |
| contains | a contains "substr" | Substring test |
| starts_with | a starts_with "prefix" | String prefix test |
| ends_with | a ends_with "suffix" | String suffix test |
Literals#
Strings: double-quoted "hello" or single-quoted 'hello' with backslash escapes
Numbers: integer or decimal (42, 3.14)
Booleans: true, false
Available Variables#
Variables are accessed with dot notation. Not all variables are available in every context – file-level variables are only present when the rule is evaluated per file.
file.* (per-file context)#
| file.path | string | Full file path relative to the repo root |
| file.extension / file.ext | string | File extension without the dot (e.g. "rs", "ts") |
pr.* (per-PR context)#
| pr.author | string | GitHub login of the PR author |
| pr.title | string | PR title text |
| pr.additions | number | Total lines added in the PR |
| pr.deletions | number | Total lines deleted in the PR |
diff.* (per-file context)#
| diff.additions | number | Lines added in this specific file |
| diff.deletions | number | Lines deleted in this specific file |
Action Types#
Each action is a table with a type field and type-specific parameters.
skip_file#
Exclude the current file from review. No additional fields.
[[rules.actions]]
type = "skip_file"
add_focus#
Add a focus area to the review prompt.
[[rules.actions]]
type = "add_focus"
area = "Check for SQL injection vulnerabilities"
set_severity#
Override the review severity level.
[[rules.actions]]
type = "set_severity"
level = "critical"
add_comment#
Inject a comment into the review context.
[[rules.actions]]
type = "add_comment"
text = "This file is part of the auth subsystem. Review with extra care."
add_instruction#
Add a custom instruction to the LLM system prompt.
[[rules.actions]]
type = "add_instruction"
text = "Verify that all database queries use parameterized statements."
set_review_depth#
Control how thorough the review should be.
[[rules.actions]]
type = "set_review_depth"
depth = "thorough"
add_label#
Add a label to the review output (for downstream processing).
[[rules.actions]]
type = "add_label"
label = "security-review"
Examples#
Skip Generated and Vendored Files#
[[rules]]
name = "skip-generated"
condition = 'file.path matches ".*\\.gen\\..*" || file.path starts_with "vendor/"'
priority = 100
[[rules.actions]]
type = "skip_file"
Strict Review for Security-Sensitive Files#
[[rules]]
name = "security-critical"
condition = 'file.path contains "auth" || file.path contains "crypto" || file.extension in ["sql", "sh"]'
priority = 50
[[rules.actions]]
type = "add_focus"
area = "Check for authentication bypass, injection, and credential leaks"
[[rules.actions]]
type = "set_severity"
level = "critical"
Flag Large PRs#
[[rules]]
name = "large-pr-warning"
condition = "pr.additions + pr.deletions > 500"
priority = 10
[[rules.actions]]
type = "add_comment"
text = "This is a large PR. Consider splitting it into smaller, focused changes."
[[rules.actions]]
type = "set_review_depth"
depth = "thorough"
Skip Specific Authors#
[[rules]]
name = "skip-bot"
condition = 'pr.author == "dependabot[bot]" || pr.author == "renovate[bot]"'
priority = 200
[[rules.actions]]
type = "skip_file"
Focus on Config File Changes#
[[rules]]
name = "config-review"
condition = 'file.extension in ["toml", "yaml", "yml", "json", "env"]'
priority = 30
[[rules.actions]]
type = "add_focus"
area = "Verify no secrets are committed and default values are sensible"
[[rules.actions]]
type = "add_label"
label = "config-change"