Linter, Formatter and Type Checker Detection — Rules Reference

Rules verified: 2026-10-05 (panopticas 0.0.20) Inventory below generated from: LINTER_RULES in src/panopticas/constants.py

Panopticas detects the configuration and exclusion files of code-quality tooling and tags each with the languages the tool targets, its role, the tool name, and whether the file configures or excludes.

.eslintrc.json   -> ['JavaScript', 'TypeScript', 'linter', 'ESLint', 'config']
.eslintignore    -> ['JavaScript', 'TypeScript', 'linter', 'ESLint', 'ignore']
.rubocop.yml     -> ['Ruby', 'linter', 'formatter', 'RuboCop', 'config']
mypy.ini         -> ['Python', 'typechecker', 'mypy', 'config']
.editorconfig    -> ['formatter', 'EditorConfig', 'config']

This document is the reference and evidence base: what is detected, the source that confirms each convention, and — equally important — what was rejected and why.

How matching works

LINTER_RULES maps a tool to its languages, its roles, and the files that identify it. A single expansion step writes those entries into the same METADATA_RULES tables every other rule uses, so the tags are produced by one code path and the shape cannot drift between tools.

Key Expands into Matched against
config exact_filename_rules the lowercased basename
ignore exact_filename_rules the lowercased basename
path_contains path_contains_rules a substring of the path
extensions extension_rules the file extension

Tags are languages + roles + [tool] + ["config" or "ignore"]. The three roles are linter, formatter and typechecker; a tool may hold more than one, and several do — Ruff, Biome, RuboCop, Standard and SQLFluff all lint and format.

Unlike AI artifact detection, these rules add tags rather than resolving to a single winner, so eslint.config.js is both JavaScript and an ESLint config.

Detection is path-based only

No rule opens a file. This is the same constraint AI detection works under, and it is what makes the per-language shared config files undetectable:

File Really can hold Why it is not tagged
pyproject.toml Ruff, Black, mypy, isort, yapf, Pylint, Pyright which tool is inside is not knowable from the path
setup.cfg Flake8, isort, yapf, mypy same
tox.ini Flake8, Pylint same
package.json Prettier, ESLint, Stylelint, StandardJS same

Tagging any of these as a linter config would mislabel every repository that has one, which is most of them. They keep their existing build and dependency tags only.

The rejected list

Each of these was investigated against the tool’s current documentation and deliberately not added. Re-adding one would mislabel repositories.

Candidate Why rejected
revive (revive.toml) Auto-discovers only $HOME/revive.toml. A user-level path, not a repository artifact — the same trap AI detection warns about. A project-level config exists but must be passed with -config, under any name.
SpotBugs (spotbugs-exclude.xml) Filter files are arbitrarily named and passed with -exclude/-include. The documentation’s myExcludeFilter.xml is illustrative, not a convention.
PMD (ruleset.xml) Ruleset files are arbitrarily named and passed explicitly. No discovered filename.
CodeNarc (codenarc.xml) Rulesets are arbitrary .xml or .groovy files. Detected indirectly through npm-groovy-lint, which does have a fixed config name.
Black Configured only in pyproject.toml. No dedicated file exists to match.
StandardJS Configured only in package.json.
Spotless Configured only in build.gradle / pom.xml.
gofmt, gofumpt, go vet No configuration file at all.
pycodestyle Project-level config lives in setup.cfg or tox.ini; the dedicated file is the user-level ~/.config/pycodestyle.
Sonar, Bandit, Brakeman, GitLeaks Security scanners, out of scope. GitLeaks is already detected separately via .gitleaksignore.

How dprint was settled

dprint was initially left out because its documentation never enumerates the filenames it discovers. The answer is in the source — POSSIBLE_CONFIG_FILE_NAMES in resolve_main_config_path.rs — which lists exactly four names, searched in order while walking up ancestor directories, with no config/ subdirectory. The setup page corroborates the two hidden variants.

Worth noting against the user-level trap that disqualified revive: dprint also reads a global config at ~/.config/dprint/dprint.jsonc, reusing the dprint.jsonc name. That does not disqualify it. revive’s only auto-discovered config is user-level, so a repository rule would be fiction; dprint’s four names are genuinely project-level, and its global config merely shares a name in a different directory.

Two judgement calls worth knowing

checkstyle.xml is not a documented Checkstyle convention — Checkstyle discovers nothing and takes its config as an argument. It is included because the name is unambiguous in practice, and alongside it sit two names that are documented: google_checks.xml and sun_checks.xml ship with the distribution, and config/checkstyle/ is the Gradle Checkstyle plugin’s documented default directory.

tsconfig.json is a compiler configuration, and the TypeScript handbook is explicit that it does not handle linting. It is tagged typechecker because it is nonetheless where a project’s type checking is actually configured (strict, noImplicitAny), which is the thing worth finding. jsconfig.json is the same file applied to a JavaScript project.

Filetypes, not just tags

Extensionless config dotfiles used to report Unknown. They now resolve on one principle: where a tool documents a single content format, map to that format; where several are accepted, the file gets its own name.

Resolves to its documented format Gets its own name
.editorconfig, .flake8, .globalconfig, .pylintrc, pylintrc, .isort.cfg, .style.yapf → INI .eslintrc → ESLintRC (JSON, YAML or JS)
.jshintrc → JSON .prettierrc → Prettierrc (JSON or YAML)
staticcheck.conf → TOML .stylelintrc → StylelintRC (JSON or YAML)
.rufo, Steepfile → Ruby (both are evaluated as Ruby) .eslintignore, .prettierignore, .stylelintignore, .jshintignore, .yapfignore — gitignore-style pattern files
*.ruleset → XML  

.cfg and .conf are mapped by basename rather than by extension, because both are used for arbitrary formats elsewhere — the same reasoning that already applied to setup.cfg.

Module extensions

Closing this gap also meant adding four extensions that were missing from EXT_FILETYPES altogether, and which are not linter-specific at all:

Extension Language Meaning
.mjs JavaScript always an ES module
.cjs JavaScript always CommonJS
.mts TypeScript TypeScript emitting an ES module
.cts TypeScript TypeScript emitting CommonJS

These exist because Node needs to know a file’s module system before parsing it, and .js alone does not say. Config authors reach for them to escape the "type" field in package.json, which is why eslint.config.mjs and .prettierrc.cjs are so common. Both pairs match GitHub Linguist, which types all four as programming.

Sources

Every convention above was checked against the tool’s own current documentation:

Tool Source
ESLint Configuration files (flat), v8 configuration files (eslintrc)
Prettier Configuration file
Stylelint Configure
Biome Configure Biome
oxlint Linter config
TypeScript tsconfig.json
dprint Setup and POSSIBLE_CONFIG_FILE_NAMES in resolve_main_config_path.rs
EditorConfig editorconfig.org
Ruff Configuration
Flake8 Configuring flake8
Pylint Running pylint
mypy The mypy configuration file
Pyright Configuration
isort Config files
yapf README
Prospector Profiles
golangci-lint Configuration file
staticcheck Configuration
RuboCop Configuration
Standard README
Reek README
Rufo README
erb_lint README
Steep README
Sorbet CLI
Checkstyle Gradle Checkstyle plugin
npm-groovy-lint Documentation
Roslyn Configuration files for code analysis rules
StyleCop Configuration

Re-verifying

Config filenames change. ESLint replaced .eslintrc with flat config and dropped .eslintignore; Stylelint’s docs warn its legacy locations “may be removed in the future”. Legacy names are kept deliberately — a repository that still has .eslintrc.json is still a repository using ESLint.

When re-verifying, check each source above for new accepted extensions, and re-read the rejected list before adding anything in it.

Inventory

* marks a path fragment rather than a filename.

JavaScript, TypeScript and CSS

Tool Role Language tags Config Ignore
ESLint linter JavaScript, TypeScript eslint.config.js, eslint.config.mjs, eslint.config.cjs, eslint.config.ts, eslint.config.mts, eslint.config.cts, .eslintrc, .eslintrc.js, .eslintrc.cjs, .eslintrc.yaml, .eslintrc.yml, .eslintrc.json .eslintignore
Prettier formatter JavaScript, TypeScript, CSS .prettierrc, .prettierrc.json, .prettierrc.yml, .prettierrc.yaml, .prettierrc.json5, .prettierrc.js, .prettierrc.mjs, .prettierrc.cjs, .prettierrc.ts, .prettierrc.mts, .prettierrc.cts, .prettierrc.toml, prettier.config.js, prettier.config.mjs, prettier.config.cjs, prettier.config.ts, prettier.config.mts, prettier.config.cts .prettierignore
Stylelint linter CSS stylelint.config.js, stylelint.config.mjs, stylelint.config.cjs, stylelint.config.ts, .stylelintrc, .stylelintrc.js, .stylelintrc.mjs, .stylelintrc.cjs, .stylelintrc.yml, .stylelintrc.yaml, .stylelintrc.json .stylelintignore
Biome linter, formatter JavaScript, TypeScript, CSS biome.json, biome.jsonc, .biome.json, .biome.jsonc —
oxlint linter JavaScript, TypeScript .oxlintrc.json, .oxlintrc.jsonc, oxlint.config.ts, oxlint.config.mts —
dprint formatter JavaScript, TypeScript dprint.json, dprint.jsonc, .dprint.json, .dprint.jsonc —
JSHint linter JavaScript .jshintrc .jshintignore
TypeScript typechecker TypeScript, JavaScript tsconfig.json, jsconfig.json —
EditorConfig formatter (none) .editorconfig —

Python

Tool Role Language tags Config Ignore
Ruff linter, formatter Python ruff.toml, .ruff.toml —
Flake8 linter Python .flake8 —
Pylint linter Python pylintrc, .pylintrc, pylintrc.toml, .pylintrc.toml —
mypy typechecker Python mypy.ini, .mypy.ini —
Pyright typechecker Python pyrightconfig.json —
isort formatter Python .isort.cfg —
yapf formatter Python .style.yapf .yapfignore
Prospector linter Python .prospector.yaml, .prospector.yml —

Go

Tool Role Language tags Config Ignore
golangci-lint linter Go .golangci.yml, .golangci.yaml, .golangci.toml, .golangci.json —
staticcheck linter Go staticcheck.conf —

Ruby

Tool Role Language tags Config Ignore
RuboCop linter, formatter Ruby .rubocop.yml .rubocop_todo.yml
Standard linter, formatter Ruby .standard.yml .standard_todo.yml
Reek linter Ruby .reek.yml —
Rufo formatter Ruby .rufo —
erb_lint linter Ruby .erb_lint.yml —
Steep typechecker Ruby steepfile —
Sorbet typechecker Ruby sorbet/* —

Java

Tool Role Language tags Config Ignore
Checkstyle linter Java checkstyle.xml, google_checks.xml, sun_checks.xml, config/checkstyle/* —

Groovy

Tool Role Language tags Config Ignore
npm-groovy-lint linter Groovy .groovylintrc.json, .groovylintrc.js, .groovylintrc.yml —

C# and .NET

Tool Role Language tags Config Ignore
Roslyn linter C#, .NET .globalconfig, *.ruleset —
StyleCop linter C#, .NET stylecop.json, .stylecop.json —

SQL

Tool Role Language tags Config Ignore
SQLFluff linter, formatter SQL .sqlfluff .sqlfluffignore