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:
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:
/** @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'
}
]
}
}
}
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:
import { recommendedConfig } from 'gptlint'
/** @type {import('gptlint').GPTLintConfig} */
export default [
...recommendedConfig,
{
llmOptions: {
model: 'gpt-4o',
weakModel: 'gpt-4o'
}
}
]
Using Anthropic Claude via OpenRouter:
See Using Anthropic for more info.
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
.