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.

Custom checks are supported by both Qlty CLI and Qlty Cloud.

Types of Custom Checks

Qlty supports three plugins for custom checks:

AST-Grep

AST-Grep 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:

1[[plugin]]
2name = "ast-grep"

Semgrep

Semgrep 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:

1[[plugin]]
2name = "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:

1[[plugin]]
2name = "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:

1id: no-console-log
2language: javascript
3message: "Avoid using console.log in production code"
4severity: warning
5pattern: console.log($X)

Create an sgconfig.yml configuration file 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.

Semgrep rules

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

1rules:
2 - id: avoid-eval
3 pattern: eval(...)
4 message: "Avoid using eval() as it can lead to security vulnerabilities"
5 languages: [javascript, typescript]
6 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.

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:

1[plugins.definitions.ripgrep.drivers.lint-fixme]
2script = "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:

1[plugins.definitions.rebranded-names]
2releases = ["ripgrep"]
3file_types = ["markdown"]
4description = "Finds references to rebranded names in Markdown"
5
6[plugins.definitions.rebranded-names.drivers.lint]
7script = "rg \"HBO Max|Dunkin Donuts|Square\" ${target} --json --word-regexp --only-matching"
8success_codes = [0, 1]
9output = "stdout"
10output_format = "ripgrep"
11batch = true
12cache_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.

1# Set the category and level for issues found by `rebranded-names` plugin above
2[[override]]
3plugins = ["rebranded-names"]
4category = "style"
5level = "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