Grit Configuration

Grit does not require any configuration to use patterns from the standard library.

If you need to customize Grit's behavior further, add a .grit/grit.yaml file in your repository.

SHELL
/repo
├── .grit
│ └── grit.yaml
├── foobar
| └── baz
├── src
└── etc

A Grit configuration might look like this.

grit.yaml
version: 0.0.1
patterns:
  - name: avoid_only
    tags: ['style', 'debugging']
    level: error
    body: |
      `$testlike.only` => `$testlike` where {
        `$testlike` <: or {
          `describe`
          `it`
          `test`
        }
      }
    description: |
      .only is usually a mistake left over from local debugging. Pushing it to
      main risks false negatives on CI.
    samples:
      - input: |
          describe.only('this is a test', () => {
            // ...
          });
        output: |
          describe('this is a test', () => {
            // ...
          });
  - name: disabled_pattern
    level: none # This pattern is disabled
    body: |
      `something` => `somewhere`

Configuration Reference

Grit can be configured using a .grit/grit.yaml file. The file is in YAML format.

Patterns

The patterns field is a list of patterns which are applicable to your codebase.

Each pattern can specify the following fields:

  • name: (Required, string) The name of the pattern. Conventionally in snake case.
  • title: (Optional, string) A short, human-readable title for the pattern. Defaults to the name if not set.
  • body: (Optional, string) The body of the pattern. This is useful for short, inline patterns. If not provided, the pattern should either be imported from a remote Grit module, or defined in a separate file within the .grit directory.
  • description: (Optional, string) A longer description of the pattern.
  • level: (Optional, one of none, info, warn, error) The enforcement level of the pattern for running diagnostics via grit check. Defaults to info.
  • tags: (Optional, string[]) A list of tags which can be used to filter patterns.

Note: You do not need to list patterns which are defined in Markdown or .grit files, they are automatically merged in.

Imported Patterns

The patterns listed in the patterns field don't need be local to your module. If you want to enable a pattern from another module, you just need to name it in your list, prefixed with the module name and a #.

For example, to enable the no_console_log pattern from the JavaScript standard library, you would add the following to your grit.yaml file.

grit.yaml
patterns:
  - name: github.com/getgrit/stdlib#no_console_log

If you want to enable all patterns from another module, just use a * for the pattern name.

For example, to enable all patterns from the standard library, you would add the following to your grit.yaml file.

grit.yaml
patterns:
  - name: github.com/getgrit/stdlib#*

By default, all patterns from the standard library are automatically imported. If you define custom patterns, make sure their names don't conflict with the standard library.

Grit modules are simply referenced by their git URL. This means that you can import configurations from any git repository, including private repositories.

To download remote patterns, run the grit init command through the Grit CLI. Grit searches up the directory tree from your current working directory to find the nearest grit.yaml config. For each remote gritmodule specified in the config, Grit clones a sparse, shallow copy of the repository's root .grit directory into your local .gritmodules directory. Because the remote module's pattern can itself be a reference to another module's pattern, Grit recursively traverses the dependency graph and downloads all modules referenced by grit.yaml files (but only the patterns specified in your grit.yaml will be enforced).

Since gritmodules' patterns are identified by their root .grit/grit.yaml file, you must ensure that any patterns you wish to export from a repository you are using as a remote gritmodule are exposed in the root grit.yaml.

Note: The result of the pattern module downloading process is flat. Defining two patterns with the same name in different modules will cause an error. Grit considers all pattern names that are referenced within modules in the dependency graph, so you may get a pattern naming conflict even if you don't directly reference the conflicting pattern in your grit.yaml file.

Version

The version field specifies the version of this configuration file. We follow semantic versioning. The current version is 0.0.2.

grit.yaml
version: 0.0.2

GitHub

The GitHub field contains GitHub-specific configuration.

Reviewers

The reviewers field is a list of GitHub users and teams which will be requested to review pull requests opened by Grit. Teams should be prefixed with an @ symbol and use the full team name, including the organization.

grit.yaml
version: 0.0.2
patterns: []
github:
  reviewers:
    - gritbot
    - "@getgrit/core"

Markdown patterns

Patterns can be stored in *.md files within a .grit/patterns folder at the root of your repo, including in subdirectories.

Spec

  • The name of the file is used as the name of the pattern (without the .md extension).
  • The title of the pattern is retrieved from the first heading in the file. This can be overridden by adding a title field in the front matter.
  • The description of the pattern is retrieved from the first non-heading paragraph in the file.
  • The GritQL body is retrieved from the first fenced code block in the file.
  • Additional pattern metadata can be configured as YAML in the frontmatter of the markdown file, delineated between --- lines at the start of the document.
    • level: (Optional, one of none, info, warn, error) The enforcement level of the pattern for running diagnostics via grit check. Defaults to info.
    • tags: (Optional, string[]) A list of tags which can be used to filter patterns.
  • Subheadings are used for each test case, following these conventions:
    • If a subheading has a single code block, it represents a test case that should be matched by the pattern. You don't need to provide a transformed example.
    • If a subheading has two code blocks, the first represents the input and the second represents the expected output.
    • A negative test case should have two identical code blocks.
    • Within the sample patterns, you can use // @filename: example.js to represent multiple input/output files that should be tested as a group - like this example.

Note: Grit's pattern resolution logic relies on each named pattern being associated with a single unique body. You should avoid defining multiple patterns with the same file name in different subdirectories, as this will cause conflicts.

Example

MARKDOWN .grit/patterns/remove_console_log.md
---
tags: [optional, tags, here]
---
# Remove console.log

Remove console.log in production code.

```grit
`console.log($_)` => .
```

## Test case one

This is the first test case. You can include an explanation of the case here.

```typescript
console.error("keep this");
console.log('remove this!');
```

It is fine to include additional descriptive text around the test cases.
This is often used to explain the context of the test case, or to explain a convention.

```typescript
console.error("keep this");

```

You can find many more examples in the Grit standard library.

Ignoring patterns

If grit check is flagging too many files, you can ignore specific patterns or files.

Pattern suppression should be used when you want to ignore a true positive result. For example, if you have a pattern that flags a deprecated function, but you have a good reason to use it, you can suppress the pattern.

If patterns are yielding false positives, you should consider modifying the pattern to add conditions that better capture the intent of the code.

.gritignore files

By default, Grit will ignore any files listed in your .gitignore file and any files in a .grit directory.

You can tell Grit to ignore additional files and directories by creating .gritignore files. A .gritignore file is a plain text file where each line is a glob pattern indicating which paths should be omitted from Grit's analysis. For example, the following omits all JavaScript files:

.gritignore
**/*.js

.gritignore files are cascading, so you can define them at multiple levels of the directory hierarchy. The exact semantics are detailed here.

Inline suppression

Named GritQL patterns can be suppressed for a particular line by adding a comment with the grit-ignore directive alongside or above the line to be disabled.

PATTERN
`console.$method($message)` => `console.info($message)`
INPUTOUTPUT
console.log('Hello, world!');
// grit-ignore
console.log('Can you hear me?');
console.info('Hello, world!');
// grit-ignore
console.log('Can you hear me?');

To suppress only a particular set of rules, include their comma-separated names after the grit-ignore directive:

index.js
console.log('This will be rewritten!')
// grit-ignore no_console_log, replace_console_log
console.log('This won't!')

Then when the patterns no_console_log or replace_console_log are invoked by name, such as by running grit apply no_console_log, the second console.log statement will not be rewritten.

Additional context can be added after the rule names, separated by a colon. We recommend using this to explain why the rule is being ignored.

index.py
print('Hello world!') # grit-ignore print_to_log: We want to keep this

User configuration

In addition to the repository-level configuration described above, Grit also supports user-level configuration under a user .grit/patterns directory. By default, this is located in your home directory at ~/.grit/patterns. You can override its location by setting the GRIT_USER_CONFIG environment variable to point at a .grit directory of your choice.

Repository patterns always take precedence over user patterns. If a pattern is defined in both the repository and user configuration, the repository pattern will be used. User patterns cannot be imported by repository configurations, but can be applied through grit apply invocations on the CLI.