Guide
Config

Config

GPTLint config is inspired by ESLint’s new flat config format, so if you’ve ever used eslint, then gptlint should feel very familiar.

Just like ESLint, GPTLint supports a variety of ways to customize and extend it’s behavior and default linting rules. Configs can come from the following places, with more specific configs overriding more general settings:

  • default settings
  • project-specific config file (gptlint.config.{js,mjs,cjs})
  • CLI flags (all of the main config settings have corresponding CLI flags)
  • inline config overrides in source files (/* gptlint-disable */)

In the near future, we’ll be moving the current set of default JS/TS rules into an NPM package @gptlint/typescript-config, and in general this is the expected way to provide reusable sets of pre-configured rules going fowards. As a general principle, we’re trying to follow ESLint’s config design as closely as possible.

Print Config

You can always run gptlint --print-config to print out exactly what rules, files, and settings are being resolved by GPTLint.

The --print-config option is extremely useful for making sure your project is set up correctly and for validating your understanding of how the linter works under the hood.

Default Config

The default config is available like so:

import { recommendedConfig } from 'gptlint'

recommendedConfig is an array of LinterConfig objects which enable the default rule set. If you do not specify a custom config file, then the recommended config will be applied by default. If you do specify a custom config file, then you must manually opt-in to the default rules like in the examples below. This design makes it easy to add support for third-party NPM packages and reusable bundles of custom configs instead of treating the built-in rules specially.

Config File

The GPTLint configuration file may be named any of the following:

  • gptlint.config.js
  • gptlint.config.mjs
  • gptlint.config.cjs

It should be placed in the root directory of your project and export an array of configuration objects. Here’s an example:

gptlint.config.js
import { recommendedConfig } from 'gptlint'
 
export default [
  ...recommendedConfig,
  {
    rules: {
      'always-handle-promises': 'warn',
      'semantic-variable-names': 'off'
    }
  }
]

In this example, the configuration array contains just one configuration object. The configuration object will be merged with the default config to set always-handle-promises violations to warnings and to disable the semantic-variable-names rule for all files.

LinterConfig Objects

LinterConfig objects are validated against a LinterConfigSchema zod schema which has a very similar shape to ESLint Configuration Objects.

export type LinterConfig = {
  files?: string[] // array of globs to search for source files
  ignores?: [] // array of globs to ignore for source files
 
  ruleFiles?: [] // array of globs to find project-specific rule md files
  ruleDefinitions?: RuleDefinition[] // custom rules (extensible to non-md formats)
 
  // enable / disable rules
  rules?: Record<string, 'error' | 'warn' | 'off'>
 
  // customize linter options (debug, cache dir, logging, etc)
  linterOptions?: LinterOptions
 
  // customize LLM model and provider options
  // most important are: model, weakModel, apiKey, and apiBaseUrl
  llmOptions?: LLMOptions
 
  // optional, file/folder/glob-specific rule overrides
  overrides?: Array<{
    include?: string[] // array of glob files to apply this override to
    exclude?: string[] // array of glob files to exclude from this override
    rules?: Record<string, 'error' | 'warn' | 'off'>
  }>
}

See the source for more details.

Custom Rules

By default, ruleFiles will search [ '.gptlint/**/*.md' ] for project-specific rule definition markdown files.

You can override this with the ruleFiles config setting or with the --rules (-r) CLI flag.

Code-Based Custom Rules

You can also specify code-based custom RuleDefinition objects which are normal JS/TS objects with hooks for fully customizing linting behavior.

An example of a code-based rule (the equivalent of a plugin in eslint) is effective-tsconfig, which has a project scope and uses the preProcessProject hook to resolve a project’s tsconfig.json file and check for best practices.

Here’s an example:

my-custom-rule.js
/** @type {import('gptlint').RuleDefinition} */
export default {
  name: 'my-custom-rule',
  title: 'Example rule',
  level: 'error',
  scope: 'file',
 
  preProcessFile: async ({ file, rule, cache, config, cwd }) => {
    return {
      lintErrors: [
        {
          message: 'This is an example custom lint error',
          level: 'error'
        }
      ]
    }
  }
}
gptlint.config.js
import { recommendedConfig } from 'gptlint'
import myCustomRule from './my-custom-rule.js'
 
/** @type {import('gptlint').GPTLintConfig} */
export default [
  ...recommendedConfig,
  {
    ruleDefinitions: [myCustomRule]
  }
]

Example Config Files

Using gpt-4-turbo-preview as the strong model:

gptlint.config.js
import { recommendedConfig } from 'gptlint'
 
/** @type {import('gptlint').GPTLintConfig} */
export default [
  ...recommendedConfig,
  {
    llmOptions: {
      model: 'gpt-4-turbo-preview',
      weakModel: 'gpt-3.5-turbo'
    }
  }
]

Using Anthropic Claude via OpenRouter:

See Using Anthropic for more info.

gptlint.config.js
import { recommendedConfig } from 'gptlint'
 
/** @type {import('gptlint').GPTLintConfig} */
export default [
  ...recommendedConfig,
  {
    llmOptions: {
      apiBaseUrl: 'https://openrouter.ai/api/v1',
      model: 'anthropic/claude-3-opus:beta',
      weakModel: 'anthropic/claude-3-haiku:beta',
      // Optional
      kyOptions: {
        headers: {
          // Optional, for including your app on openrouter.ai rankings.
          'HTTP-Referer': 'https://gptlint.dev',
          // Optional, shows in rankings on openrouter.ai.
          'X-Title': 'gptlint'
        }
      }
    }
  }
]

Differences from ESLint Config Format

Currently, all gptlint config objects are merged together into a single, flat, final config. This differs from ESLint’s config array in that individual ESLint config objects can target different files with different config settings. Here we chose to use an optional overrides field so you can customize rule settings for specific files.

💡

If you’re ever not sure how your config is being resolved or why you’re seeing unexpected behavior, double-check the output of gptlint --print-config.