Skip to main content
This feature is available exclusively as part of the Pro plan. Please refer to our pricing page for more information about our plans and features.
CodeRabbit supports review instructions based on Abstract Syntax Tree (AST) patterns, powered by ast-grep β€” a Rust-based tool that uses the tree-sitter parser to generate AST rules for popular languages, written by Herrington Darkholme. This feature has a learning curve and is recommended for users already comfortable with YAML configuration.
AST-based context is only available during the automated code review process, it is not available in the chat.
Further reading:

Setup

Use the ast-grep Playground to design and test rules on source code snippets before adding them to your project.
1

Create rules directory

Create a directory to keep all the ast-grep rules in your project directory
2

Add rule files

Add individual .yaml files for each ast-grep rule within the newly created directory
3

Configure rules

Ensure that each .yaml file contains the necessary ast-grep rule configurations
4

Add message property

Ensure that all rules contain a message property that will be used during the review process
5

Update configuration

Add the rules’ directory to the .coderabbit.yaml file under tools.ast-grep configuration
6

Add packages (optional)

Optionally, add a packages property to specify packages that should be installed before running the ast-grep tool
YAML
reviews:
  tools:
    ast-grep:
      essential_rules: true # option to enable essential security rules
      rule_dirs:
        - "custom-name"
      packages:
        - "myorg/myawesomepackage" # custom package name following the format organization/repository

The rule object

The rule object is the core concept of the ast-grep rule system β€” every other feature is built on top of it. Below is the full list of fields in a rule object. Every field is optional and can be omitted, but at least one field must be present. A node matches a rule if and only if it satisfies all fields in the rule object.
YAML
rule:
  # atomic rule
  pattern: "search.pattern"
  kind: "tree_sitter_node_kind"
  regex: "rust|regex"
  # relational rule
  inside: { pattern: "sub.rule" }
  has: { kind: "sub_rule" }
  follows: { regex: "can|use|any" }
  precedes: { kind: "multi_keys", pattern: "in.sub" }
  # composite rule
  all: [{ pattern: "match.all" }, { kind: "match_all" }]
  any: [{ pattern: "match.any" }, { kind: "match_any" }]
  not: { pattern: "not.this" }
  matches: "utility-rule"

Rule categories

Atomic Rule

The most basic rule that checks if AST nodes match

Relational Rule

Rules that check if a node is surrounded by another node

Composite Rule

Rules that combine sub-rules together using logical operators
These three categories can be composed together to create more complex rules.
The rule object is inspired by CSS selectors but with more composability and expressiveness. Think about how CSS selectors work to better understand rule composition.
Read the ast-grep documentation for detailed guides.

Atomic rule

An atomic rule defines the most basic matching rule: whether a syntax node matches or not. There are three kinds: pattern, kind, and regex.
Official documentation: Atomic Rule

Relational rule

A relational rule defines the relationship between two syntax nodes. There are four kinds: inside, has, follows, and precedes. All four relational rules accept a sub-rule object as their value. The sub-rule matches the surrounding node; the relational rule itself matches the target node.
Official documentation: Relational Rule
YAML
rule:
  pattern: await $PROMISE
  inside:
    kind: for_in_statement
    stopBy: end

Composite rule

A composite rule defines the logical relationship between multiple sub-rules. There are three kinds: all, any, and not. all β€” matches if all sub-rules match:
YAML
rule:
  all:
    - pattern: console.log('Hello World');
    - kind: expression_statement
any β€” matches if any sub-rule matches:
YAML
rule:
  any:
    - pattern: var a = $A
    - pattern: const a = $A
    - pattern: let a = $A
not β€” applies negation; matches if the sub-rule does not match:
YAML
rule:
  pattern: console.log($GREETING)
  not:
    pattern: console.log('Hello World')
Official documentation: Composite Rule

Reusing rules as utilities

ast-grep uses YAML for rule representation, which means rule objects cannot be directly reused across rule files. Utility rules solve this.

Local utility rule

Local utility rules are defined in the utils field of the config file. utils is a string-keyed dictionary.
YAML
utils:
  is-literal:
    any:
      - kind: string
      - kind: number
      - kind: boolean
rule:
  matches: is-literal

Global utility rule

Global utility rules are defined in a separate file and are available across all rule configurations in the project. To create global utility rules, create a rules directory and a utils directory at the root of your project:
YAML
my-awesome-project   # project root
  |- rules           # rule directory
  | |- my-rule.yml
  |- utils           # utils directory
  | |- is-literal.yml
Add both directories to .coderabbit.yaml under tools.ast-grep:
YAML
reviews:
  tools:
    ast-grep:
      essential_rules: true
      rule_dirs:
        - "rules"
      util_dirs:
        - "utils"
      packages:
        - "my-awesome-org/my-awesome-package" # public repository containing ast-grep rules
Example utility rule file:
YAML
# is-literal.yml
id: is-literal
language: TypeScript
rule:
  any:
    - kind: "false"
    - kind: undefined
    - kind: "null"
    - kind: "true"
    - kind: regex
    - kind: number
    - kind: string
Official documentation: Utility Rule

Packages

A package is a collection of ast-grep rules that can be shared across multiple projects.

Built-in packages

CodeRabbit provides packages you can use out of the box

Custom packages

Create your own packages and share them with your organization or community

CodeRabbit packages

ast-grep-essentials

Essential security rules packageBecause we value security, this package gets its own property in .coderabbit.yaml for easier installation without overwriting existing configurations.
YAML
reviews:
  tools:
    ast-grep:
      essential_rules: true
      packages:
        - "my-awesome-org/my-awesome-package"

Custom packages

To use a public repository containing ast-grep rules as a package, add it to the packages field in .coderabbit.yaml.
  • Must be a public repository
  • Name must follow the format organization/repository
  • Contains rules that follow the ast-grep rule format
  • Follows the required folder structure shown below
my-awesome-project   # project root
  |- rules           # rule directory
  | |- my-rule.yml
  |- utils           # utils directory
  | |- is-literal.yml
rules and utils are reserved directory names and must be named exactly as shown. Inside each directory, the structure is flexible.
YAML
reviews:
  tools:
    ast-grep:
      packages:
        - "my-awesome-org/my-awesome-package"

Supported languages

Web Technologies

  • JavaScript
  • TypeScript

Systems Languages

  • C
  • Rust
  • Golang

Enterprise Languages

  • Java
  • C#
  • Kotlin
  • Python

Examples

JavaScript β€” disallow imports without file extension

YAML
id: find-import-file
language: js
message: "Importing files without an extension is not allowed"
rule:
  regex: "/[^.]+[^/]$"
  kind: string_fragment
  any:
    - inside:
        stopBy: end
        kind: import_statement
    - inside:
        stopBy: end
        kind: call_expression
        has:
          field: function
          regex: "^import$"

TypeScript β€” no console.log except console.error in catch blocks

YAML
id: no-console-except-error
language: typescript
message: "No console.log allowed except console.error on the catch block"
rule:
  any:
    - pattern: console.error($$$)
      not:
        inside:
          kind: catch_clause
          stopBy: end
    - pattern: console.$METHOD($$$)
constraints:
  METHOD:
    regex: "log|debug|warn"

C β€” prefer plain function calls over struct method-style calls

In C, simulating OOP via struct function pointers introduces memory and indirection overhead. This rule flags the pattern and suggests a plain function call with the struct pointer as the first argument.
YAML
id: method_receiver
language: c
rule:
  pattern: $R.$METHOD($$$ARGS)
transform:
  MAYBE_COMMA:
    replace:
      source: $$$ARGS
      replace: "^.+"
      by: ", "
fix: $METHOD(&$R$MAYBE_COMMA$$$ARGS)

What’s next