mrkeyoor.com_
Wed 05 Aug 05:05 UTC
npmCLI & Toolingupdated 05 Aug 2026

eslint

ESLint is the standard linter for JavaScript: it parses your code into an AST with Espree and reports patterns that are likely bugs or that violate your team's conventions. Every rule is a plugin, so the same tool that flags an unused variable can also enforce React hooks rules or import ordering once you add the right packages. It runs from the CLI, in editors, and in CI, and many rules can rewrite the offending code for you with --fix.

Verdict

Still the default JavaScript linter and the only one with a truly deep rule ecosystem, so most teams should just use it. Go in expecting config migration churn between majors and slower runs than the Rust competition, especially with type-aware rules.

API stability3/5The project follows semver but its own policy states minor releases may report new errors and break lint builds, and the eslintrc-to-flat-config transition forced real migration work on nearly every user and plugin.
Docs5/5eslint.org documents every rule with examples of correct and incorrect code, plus configuration, Node API, and migration guides; the README alone answers most setup questions.
Maintenance5/5Scheduled releases every two weeks, a paid team funded through Open Collective and corporate sponsors under the OpenJS Foundation, and the repo was pushed the same day this was written (August 2026).
Ecosystem5/5At 155M weekly downloads with thousands of plugins and shareable configs, every framework and editor integrates with it; typescript-eslint alone makes it the de facto TypeScript linter too.

Use it if

  • You maintain a team JavaScript or TypeScript codebase and want unused variables, unreachable code, and footguns caught in CI before review
  • You need the plugin ecosystem: React hooks rules, import ordering, accessibility checks, or your own custom rules on top of the core
  • You are cleaning up a legacy codebase and want autofix (--fix) to do the mechanical work across thousands of files
  • You want editor integration that virtually every IDE already ships or supports
Skip it if

Setup reality

npm init @eslint/config@latest scaffolds a working eslint.config.js, and for plain JavaScript that is genuinely it. The friction shows up around the edges: you need Node ^20.19.0, ^22.13.0, or >=24; TypeScript support means adding typescript-eslint and, for type-aware rules, wiring in your tsconfig and accepting slower runs; pnpm users are told to set auto-install-peers and hoisted node-linker in .npmrc to avoid resolution errors; and any plugin that has not migrated to flat config needs a compat shim. Budget the first afternoon for config, not for reading rule docs.

Patterns

Set up ESLint in a new projectinit-project

npm init @eslint/config@latest
# answers a few questions, installs deps,
# and writes eslint.config.js
npx eslint .

This scaffolds flat config; do not copy an old .eslintrc from another project, current majors will not read it.

Minimal flat config with rulesbasic-config

// eslint.config.js
import { defineConfig } from "eslint/config";

export default defineConfig([
  {
    files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
    rules: {
      "prefer-const": "warn",
      "no-constant-binary-expression": "error",
    },
  },
]);

Severity is "off", "warn", or "error"; only "error" makes the CLI exit non-zero, so CI ignores warnings unless you use --max-warnings.

Start from the recommended rule setrecommended-rules

// eslint.config.js
import js from "@eslint/js";
import { defineConfig } from "eslint/config";

export default defineConfig([
  js.configs.recommended,
  {
    rules: {
      "no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
    },
  },
]);

@eslint/js is a separate package now; the old "eslint:recommended" string form belongs to legacy config.

Lint TypeScript with typescript-eslintlint-typescript

// eslint.config.js
import tseslint from "typescript-eslint";

export default tseslint.config(
  ...tseslint.configs.recommended,
  {
    rules: {
      "@typescript-eslint/no-explicit-any": "warn",
    },
  },
);

recommended does not type-check; switch to recommendedTypeChecked plus parserOptions.projectService for type-aware rules, at a real speed cost.

Ignore build output and vendored codeignore-files

// eslint.config.js
import { defineConfig, globalIgnores } from "eslint/config";

export default defineConfig([
  globalIgnores(["dist/", "coverage/", "**/*.min.js"]),
  // ...your other config objects
]);

An ignores key next to files only scopes that one config object; use globalIgnores to exclude files from linting entirely.

Declare browser or Node globalsdefine-globals

// eslint.config.js
import globals from "globals";
import { defineConfig } from "eslint/config";

export default defineConfig([
  {
    files: ["**/*.js"],
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
  },
]);

Without this, no-undef flags window, document, and process; the globals package is a separate install.

Add a plugin (React example)use-plugin

// eslint.config.js
import react from "eslint-plugin-react";
import { defineConfig } from "eslint/config";

export default defineConfig([
  {
    files: ["**/*.{js,jsx}"],
    plugins: { react },
    rules: {
      "react/jsx-key": "error",
    },
    settings: { react: { version: "detect" } },
  },
]);

ESLint parses JSX syntax natively but knows nothing about React semantics; that is exactly what eslint-plugin-react adds.

Auto-fix everything fixableautofix

npx eslint . --fix
# preview without writing:
npx eslint . --fix-dry-run

Only rules marked fixable are rewritten; the rest still print as problems, so a clean --fix run does not mean a clean lint.

Suppress a rule for one linedisable-rule-inline

// eslint-disable-next-line no-console -- CLI output is intentional
console.log(report);

Always name the rule; a bare eslint-disable-next-line silences everything on that line and hides future bugs.

Fail CI on any warningci-strict

npx eslint . --max-warnings 0
# machine-readable output for tooling:
npx eslint . --format json -o eslint-report.json

Exit code is 1 only for errors by default; --max-warnings 0 is how you make warn-level rules block a pipeline.

Alternatives

PackageRegistryPick it when
@biomejs/biomenpmYou want linting and formatting in one fast Rust binary and can live with a smaller rule ecosystem.
oxlintnpmYou want a drop-in speed boost for the common correctness rules on a big repo, possibly running in front of ESLint.
standardnpmYou want zero configuration decisions: it is ESLint underneath with a fixed, non-negotiable rule set.