A batteries-included, TypeScript-aware linting CLI and ESLint flat config bundle for use in Matrix AI JavaScript/TypeScript projects.
- Type-aware linting powered by
@typescript-eslintusing one or moretsconfig.jsonfiles - Built-in support for React, Tailwind, JSX a11y, Prettier, and Matrix AI custom rules
- Supports Prettier formatting for Markdown and SVG, ShellCheck for shell scripts, nixfmt for Nix files, and SQLFluff for SQL files
- Single command to lint JavaScript/TypeScript, Markdown, SVG, shell scripts, Nix files, and SQL files
- Customizable via
matrixai-lint-config.jsonand extensible with your own ESLint config - CLI options to override config and enable auto-fix
npm install --save-dev @matrixai/lintmatrixai-lintWith autofix:
matrixai-lint --fix| Flag | Description |
|---|---|
| (no flag) | Uses built-in Matrix AI ESLint config |
--fix |
Enables auto-fixing via ESLint and Prettier |
--user-config |
Deprecated ESLint-only alias that detects a root flat config; use --eslint-config |
--eslint-config <path> |
Explicitly use a custom ESLint config file |
--eslint <targets> |
ESLint targets (files, roots, or globs); implies ESLint domain selection |
--markdown <targets> |
Markdown targets (files, roots, or globs); implies markdown domain selection |
--svg <targets> |
SVG targets (files, roots, or globs); implies SVG domain selection |
--nix <targets> |
Nix targets (files, roots, or globs); implies nix domain selection |
--sql <targets> |
SQL targets (files, roots, or globs); implies SQL domain selection |
--shell <targets> |
Shell targets (files, roots, or globs); implies shell domain selection |
--domain <id...> |
Run only selected domains (eslint, shell, markdown, svg, nix, sql) |
--skip-domain <id...> |
Skip selected domains (eslint, shell, markdown, svg, nix, sql) |
--list-domains |
Print available domains and short descriptions, then exit 0 |
--explain |
Print per-domain decision details before execution |
-v, --verbose |
Increase log verbosity (repeat for more detail) |
Domain selection behavior:
- With no selectors and no domain-specific target flags, all built-in domains run by default.
- Passing
--eslintand/or--shellimplies explicit domain selection from those flags.--eslint ...runs ESLint only.--shell ...runs shell only.- Passing both runs both.
- Passing
--markdownimplies markdown domain selection.--markdown ...runs markdown only.- Combined with other target flags, only those targeted domains run.
- Passing
--svgimplies SVG domain selection.--svg ...runs SVG only.- Combined with other target flags, only those targeted domains run.
- Passing
--niximplies nix domain selection.--nix ...runs nix only.- Combined with other target flags, only those targeted domains run.
- Passing
--sqlimplies SQL domain selection.--sql ...runs SQL only.- Combined with other target flags, only those targeted domains run.
shellcheckis optional only for default auto-run shell execution.- If shell is explicitly requested (
--shell ...or--domain shell), missingshellcheckis a failure.
- If shell is explicitly requested (
nixfmtis optional only for default auto-run nix execution.- If nix is explicitly requested (
--nix ...or--domain nix), missingnixfmtis a failure.
- If nix is explicitly requested (
sqlfluffis optional only for default auto-run SQL execution.- If SQL is explicitly requested (
--sql ...or--domain sql), missingsqlfluffis a failure.
- If SQL is explicitly requested (
--shellaccepts target paths and glob patterns.- Directories are used as roots.
- File paths and glob patterns are reduced to search roots, then
*.shfiles are discovered under those roots.
--markdownaccepts target paths and glob patterns.- Directories are used as roots.
- File paths and glob patterns are reduced to search roots, then
*.md/*.mdxfiles are discovered under those roots. - Root-level
README.mdandAGENTS.mdare always auto-included when present.
--svgaccepts target paths and glob patterns.- Directories are used as roots.
- File paths and glob patterns are reduced to search roots, then
*.svgfiles are discovered under those roots. - By default, SVG domain scope is
./src,./specs,./pages,./public,./static,./docs, and./assets.
--nixaccepts target paths and glob patterns.- Directories are used as roots.
- File paths and glob patterns are reduced to search roots, then
*.nixfiles are discovered under those roots. - By default, nix domain scope is
flake.nix,shell.nix,default.nix, andnix/**/*.nix. - When
--nixis provided, explicit nix targets replace these defaults.
--sqlaccepts target paths and glob patterns.- Directories are used as roots.
- File paths and glob patterns are reduced to search roots, then
*.sqlfiles are discovered under those roots. - By default, SQL domain scope is
./src,./scripts,./tests,./sql,./migrations,./db,./database,./prisma,./supabase, and root-level*.sqlfiles. - When
--sqlis provided, explicit SQL targets replace these defaults.
When you run bare matrixai-lint or bare matrixai-lint --fix with no
domain-specific target flags, all built-in domains run, but each domain decides
its own effective scope:
eslint: computed from resolvedtsconfigPathsandforceInclude. With nomatrixai-lint-config.jsonand no explicitdomains.eslint.tsconfigPaths, this means the roottsconfig.jsonis used by default. The effective ESLint patterns come from thattsconfig.jsoninclude/excludeplus anyforceIncludeentries. If no usable TypeScript-driven scope can be derived, ESLint falls back to./src,./scripts, and./tests.shell:./src,./scripts,./testsmarkdown:./README.md,./AGENTS.md,./specs,./pages,./blog, and./docs. Root-levelREADME.mdandAGENTS.mdare always auto-included when present.svg:./src,./specs,./pages,./public,./static,./docs, and./assets.nix:./flake.nix,./shell.nix,./default.nix, and./nix/**/*.nixsql:./src,./scripts,./tests,./sql,./migrations,./db,./database,./prisma,./supabase, and root-level*.sqlfiles
Use matrixai-lint --explain to print the per-domain decision details and see
which scope was selected at runtime.
The scripts in this repository's package.json are wrappers for
developing this package itself; they are not the generic package defaults.
npm run lintandnpm run lintfixexplicitly pass--eslint "{src,scripts,tests}/**/*.{js,mjs,ts,mts,jsx,tsx}"and--shell src scripts tests.- That means this repository's npm scripts override the generic default scope
for the
eslintandshelldomains. - In those scripts,
markdown,svg,nix, andsqlstill use their built-in default scopes.
-
Only ESLint on a subset of files:
matrixai-lint --eslint "src/**/*.{ts,tsx}" --domain eslint -
Only shell scripts under specific roots:
matrixai-lint --shell scripts packages/*/scripts -
Markdown only:
matrixai-lint --domain markdown
-
Markdown only under selected roots:
matrixai-lint --markdown standards templates README.md
-
SVG only under selected roots:
matrixai-lint --svg specs assets public
-
Nix only (default nix scope):
matrixai-lint --domain nix
-
Nix only under selected roots/patterns:
matrixai-lint --nix nix modules flake.nix
-
SQL only under selected roots/patterns:
matrixai-lint --sql db migrations './sql/**/*.sql' -
Mixed scoped run (ESLint + shell only):
matrixai-lint --eslint "src/**/*.{ts,tsx}" --shell scripts
matrixai-lint --fix
matrixai-lint --eslint-config ./eslint.config.js --fix
matrixai-lint --eslint "src/**/*.{ts,tsx}" --shell scripts
matrixai-lint --markdown standards templates README.md
matrixai-lint --svg specs assets public
matrixai-lint --nix nix flake.nix
matrixai-lint --sql db migrations './sql/**/*.sql'
matrixai-lint --domain eslint markdown svg sql
matrixai-lint --domain nix
matrixai-lint --skip-domain markdown
matrixai-lint --list-domains
matrixai-lint --explain --domain eslint
matrixai-lint -v -v --domain markdownmatrixai-lint invokes SQLFluff from the downstream project root without an
explicit --config argument. SQLFluff therefore performs its normal native
configuration discovery, including project files such as .sqlfluff,
pyproject.toml, setup.cfg, and tox.ini.
Downstream projects should declare their SQL dialect and rule policy in one of
those native SQLFluff files. matrixai-lint --fix runs sqlfluff fix --force,
while a non-fix run uses sqlfluff lint.
matrixai-lint ships an ESLint Flat Config array and types for TypeScript
projects configured as NodeNext.
// eslint.config.js
import { config } from '@matrixai/lint';
export default config;// eslint.config.js
import matrixai from '@matrixai/lint/configs/eslint.js';
export default matrixai;matrixai-lint-config.json is an orchestration and scope configuration file. It
selects the files visible to each domain; it does not contain ESLint, Prettier,
ShellCheck, nixfmt, or SQLFluff rule settings. Keep rule configuration in each
tool's native downstream configuration file.
The ESLint domain is TypeScript-aware and uses tsconfig.json to determine how
to parse files. By default it looks for tsconfig.json in the project root. A
project with multiple TypeScript configurations can list them explicitly.
This config uses a versioned schema and must explicitly declare "version": 2:
{
"version": 2,
"root": ".",
"domains": {
"eslint": {
"targets": ["./src", "./scripts"],
"tsconfigPaths": [
"./tsconfig.base.json",
"./packages/core/tsconfig.json"
],
"forceInclude": ["scripts", "src/overrides"]
},
"shell": { "targets": ["./scripts"] },
"markdown": { "targets": ["./docs", "./README.md"] },
"svg": { "targets": ["./assets/**/*.svg"] },
"nix": { "targets": ["./nix", "./flake.nix"] },
"sql": { "targets": ["./db", "./migrations/**/*.sql"] }
}
}| Field | Type | Description |
|---|---|---|
version |
2 |
Required schema version marker |
root |
string |
Optional lint root (defaults to .); domain targets and tsconfig paths are relative to it |
domains.<domain>.targets |
string[] |
Optional files, directories, or globs defining that domain's scope |
domains.eslint.tsconfigPaths |
string[] |
One or more paths to tsconfig.json files |
domains.eslint.forceInclude |
string[] |
Paths to include despite tsconfig excludes; each must be included by at least one tsconfig |
Target precedence is: a domain-specific CLI target option, then
domains.<domain>.targets, then that domain's built-in default search scope.
Config targets affect scope but do not make a domain an explicit CLI request.
Note: If a path in forceInclude is not included in any of the tsconfigPaths,
TypeScript will throw a parsing error.
Rule configuration remains owned by each underlying tool:
| Domain | Downstream rule configuration |
|---|---|
| ESLint | Keep rules in eslint.config.js (or another flat-config file) and pass its path with --eslint-config |
| Markdown and SVG | Prettier discovers native project configs and .editorconfig; the shared config is a fallback when none is found |
| Shell | ShellCheck discovers .shellcheckrc, shellcheckrc, and inline shell directives naturally |
| Nix | nixfmt currently has no project rule configuration layer |
| SQL | SQLFluff discovers .sqlfluff, pyproject.toml, setup.cfg, and tox.ini naturally |
--user-config is a deprecated ESLint-only compatibility alias. Existing
scripts continue to work, but emit a warning. Migrate to
--eslint-config ./eslint.config.js; keep domain targets in
matrixai-lint-config.json. Neither ESLint option alters configuration for the
other domains.
Supported imports:
@matrixai/lint: named exportconfig; typesMatrixAILintCfg,RawMatrixCfg,CLIOptions.@matrixai/lint/configs/eslint.js: default export of the ESLint Flat Config array (same shape asconfig).@matrixai/lint/configs/prettier.config.js: reusable Prettier options object.
The exported config is intended as a composable base preset for downstream
eslint.config.js files, not as an internal-only implementation detail.
Any package import path not listed above is internal and not a stable public API.
Golden commands:
npm run buildnpm run lintnpm run lintfixnpm run docs
Notes:
npm run lintandnpm run lintfixinvokenpm run preparefirst so the compiled CLI indist/bin/matrixai-lint.jsstays up to date while keeping TypeScript incremental rebuilds fast.
For the authoritative contributor guidance see AGENTS.md.
Docs: https://matrixai.github.io/js-lint/
Publishing is handled automatically by the staging pipeline.
Prerelease:
# npm login
npm version prepatch --preid alpha # premajor/preminor/prepatch
git push --follow-tagsRelease:
# npm login
npm version patch # major/minor/patch
git push --follow-tagsManually:
# npm login
npm version patch # major/minor/patch
npm run build
npm publish --access public
git push
git push --tags