> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qlty.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Checks

Custom checks allow you to create and enforce your own static analysis rules specific to your codebase and organization's needs. Qlty provides support for three powerful static analysis engines, giving you flexibility in how you define and implement custom checks.

<Tip>
  Custom checks are supported by both [Qlty CLI](/cli/quickstart) and [Qlty
  Cloud](/cloud/quickstart).
</Tip>

## Types of Custom Checks

Qlty supports three plugins for custom checks:

### AST-Grep

[AST-Grep](https://ast-grep.github.io/) is a syntax-aware code search and transformation tool that uses Abstract Syntax Trees (ASTs) to understand code structure. This makes it particularly effective for complex pattern matching that accounts for code syntax rather than just text matching.

Key features:

* Structural code search across 20+ programming languages
* AST-based pattern matching for more accurate results
* Fast execution
* Supports languages including JavaScript, TypeScript, Python, Java, Go, C++, and more

Use `qlty plugins enable ast-grep` or add ast-grep to your `qlty.toml`:

```toml lines theme={"system"}
[[plugin]]
name = "ast-grep"
```

### Semgrep

[Semgrep](https://semgrep.dev/) is a lightweight static analysis tool designed for finding bugs, detecting vulnerabilities, and enforcing code standards. It uses a pattern syntax that looks like the code you're searching for.

Key features:

* Supports 20+ programming languages
* Pattern matching that understands code semantics
* Designed for security-focused rules
* Easy-to-write patterns that resemble the target code

Use `qlty plugins enable semgrep` or add semgrep to your `qlty.toml`:

```toml lines theme={"system"}
[[plugin]]
name = "semgrep"
```

### Ripgrep

Ripgrep is a high-performance text search tool that can be used for simple pattern matching in your codebase. While it doesn't understand code structure like AST-Grep or Semgrep, it's extremely fast and useful for straightforward text pattern searches.

Key features:

* Blazing fast text search across files
* Regular expression support
* Useful for simpler pattern matching needs

Use `qlty plugins enable ripgrep` or add ripgrep to your `qlty.toml`:

```toml lines theme={"system"}
[[plugin]]
name = "ripgrep"
```

## Writing Custom Rules

Each tool has its own syntax for defining rules:

### AST-Grep rules

AST-Grep rules use a YAML format that defines patterns to match in the code's syntax tree:

```yaml lines theme={"system"}
id: no-console-log
language: javascript
message: "Avoid using console.log in production code"
severity: warning
pattern: console.log($X)
```

Create an [`sgconfig.yml` configuration file](https://ast-grep.github.io/reference/sgconfig.html) in your project and use the `ruleDirs` key to specify the directory containing your custom rules.

Learn more about writing AST-Grep rules in the [AST-Grep documentation](https://ast-grep.github.io/guide/pattern-syntax.html).

### Semgrep rules

Semgrep rules also use YAML with a pattern syntax that closely resembles the code being searched:

```yaml lines theme={"system"}
rules:
    - id: avoid-eval
      pattern: eval(...)
      message: "Avoid using eval() as it can lead to security vulnerabilities"
      languages: [javascript, typescript]
      severity: ERROR
```

Store your rules in a `.semgrep.yaml` file in your project root or `.qlty/configs/` directory.

Learn more about writing Semgrep rules in the [Semgrep documentation](https://semgrep.dev/docs/writing-rules/overview).

### Ripgrep patterns

Unlike AST-Grep and Semgrep, ripgrep uses regular expressions for pattern matching.

Ripgrep matchers are defined in the `qlty.toml` file by customizing the `ripgrep` plugin definition, or creating a new plugin.

Here is an example of customizing the `ripgrep` plugin, which by default looks for `TODO` comments, to look for other patterns in your code:

```toml lines theme={"system"}
[plugins.definitions.ripgrep.drivers.lint-fixme]
script = "rg \"APPLES|ORANGES|STRAWBERRIES\" ${target} --json --word-regexp --only-matching"
```

Here is an example of defining a brand new plugin based on ripgrep which finds references to an outdated name:

```toml lines theme={"system"}
[plugins.definitions.rebranded-names]
releases = ["ripgrep"]
file_types = ["markdown"]
description = "Finds references to rebranded names in Markdown"

[plugins.definitions.rebranded-names.drivers.lint]
script = "rg \"HBO Max|Dunkin Donuts|Square\" ${target} --json --word-regexp --only-matching"
success_codes = [0, 1]
output = "stdout"
output_format = "ripgrep"
batch = true
cache_results = true
```

## Triaging issues from custom checks

You can define triage rules in `qlty.toml` which customize the category and level of issues found by your custom checks. This allows you to prioritize certain issues over others, or to categorize them based on your team's workflow.

```toml lines theme={"system"}
# Set the category and level for issues found by `rebranded-names` plugin above
[[triage]]
match.plugins = ["rebranded-names"]
set.category = "style"
set.level = "low"
```

## Benefits of Custom Checks

* **Enforce organization-specific standards**: Create rules tailored to your team's coding guidelines
* **Prevent common errors**: Catch recurring issues before they make it into production
* **Ensure consistency**: Maintain coding style and best practices across your codebase
* **Improve security**: Enforce security best practices specific to your application

## See Also

* [Analysis Configuration](/analysis-configuration)
* [Linting](/linting)
* [Plugins](cli/concepts/plugins)
