Nim Lint is an independent JavaScript and TypeScript linter with its own rule engine, diagnostics, configuration, CLI, and safe fix pipeline. It uses a maintained parser for syntax, but does not use ESLint's rule runtime or configuration engine.
Status: working v0.1.0 foundation. It covers a deliberately small, syntax-aware rule set and does not replace type checking or aim for ESLint parity.
Node.js 22.12 or newer and npm are required. From a checkout:
npm ci
npm run build
node dist/cli.js srcTo test a package install locally, run npm pack, then install the generated tarball in another project. After npm publication, install it with npm install --save-dev nim-lint. Confirm package name availability and release access before the first publication.
node dist/cli.js .
node dist/cli.js src --format json
node dist/cli.js src --fix
node dist/cli.js src/index.ts --config nim-lint.config.json
node dist/cli.js 'src/**/*.tsx'
node dist/cli.js --helpAn installed package provides the nim-lint executable. Inputs may be files, directories, or globs and may be combined. Supported extensions are .js, .jsx, .ts, and .tsx. The CLI recursively discovers files in directories, skips node_modules, dist, coverage, and .git by default, and reports missing or unreadable inputs without stopping other files. Symlink inputs are currently rejected. A directory with no supported files succeeds without output.
Exit codes: 0 if no error diagnostics remain, 1 if errors remain, and 2 for configuration or file execution errors. Warnings alone return 0. JSON output contains a stable version 1 object with diagnostics and errors arrays; see API documentation.
Create nim-lint.config.json in the working directory, or pass --config with a path. No JavaScript is executed to load configuration.
{
"rules": {
"no-debugger": "error",
"no-unreachable": "error",
"no-duplicate-imports": "warning",
"prefer-const": "off"
},
"ignore": ["generated/**", "coverage/**"]
}Unknown keys, unknown rule IDs, and invalid severities are errors. Ignore patterns use glob syntax relative to the working directory. Built-in ignores always apply. See configuration for precedence and defaults.
import { lintText, lintFiles } from 'nim-lint';
const result = await lintText('debugger;', 'example.ts');
const project = await lintFiles(['src'], { fix: false });
console.log(result.diagnostics, project.errors);lintText is async and performs no filesystem access. It accepts per-rule severities and fix: true; when a fix changes the text, output contains the final source. lintFiles loads configuration, discovers files, and writes changed files only when fix: true. See API documentation for types and location conventions.
| Rule | Default | Scope |
|---|---|---|
no-debugger |
error | debugger statements |
no-unreachable |
error | statements after a direct return, throw, break, or continue in the same block |
no-duplicate-imports |
warning | repeated compatible value or type import declarations |
no-constant-condition |
warning | literal boolean conditions in if and conditional expressions |
no-empty-block |
warning | empty blocks without comments, excluding catch bodies |
prefer-const |
warning | initialized simple let bindings with no detected writes |
Only prefer-const supplies an automatic fix. Fixes are opt-in, validated, applied without overlap, and re-linted with a ten-pass limit. See rule details for precise coverage and exclusions.
npm run typecheck
npm test
npm run test:coverage
npm run build
npm run lint
npm run test:packagetest:package builds no code; run npm run build first. It packs and installs the tarball into a temporary consumer project, then checks public import, CLI, JSON, exit codes, and fix idempotence. Architecture describes the module boundaries. Roadmap tracks remaining release work.