ESLint 02 🛡️ Installation — Node requirements & @eslint/create-config
ESLint is a Node.js package, and its installation is bounded by two constraints that change with every major release: the minimum Node.js version the package supports, and the configuration generator that scaffolds the initial setup. The first constraint is non-negotiable—ESLint will refuse to run on an unsupported Node version. The second is a convenience that has become the recommended installation path: @eslint/create-config, invoked through npm init @eslint/config, walks through a short questionnaire and writes a working flat configuration file.
This chapter covers the Node.js version requirements for current ESLint releases, the exact commands for installing ESLint both locally and globally, and the @eslint/create-config workflow in detail. It explains what the generator asks, what files it produces, how it detects the project’s module system and framework, and why the generated configuration is a starting point rather than a finished setup.
Key point: ESLint v10 requires Node.js ^20.19.0 || ^22.13.0 || >=24. Installing ESLint on an older Node version produces a runtime error, not a warning. Verify the Node version before installing.
Why installation has these constraints
The Node.js support policy problem. ESLint follows a formal Node.js support policy tied to major releases. When a Node.js version reaches end-of-life, the next ESLint major drops support for it. ESLint v9 supported Node.js ^18.18.0, ^20.9.0, or >=21.1.0 . ESLint v10 raised the floor to ^20.19.0, ^22.13.0, or >=24, dropping Node 18 entirely and requiring patch-level minimums within the supported lines . The patch-level minimum for Node 20 (20.19.0) exists because that release enabled native require(esm) support by default, which ESLint v10 relies on .
The configuration format transition problem. ESLint v9 introduced flat config as the default and deprecated the legacy .eslintrc format. The @eslint/create-config utility generates flat config files (eslint.config.js or .mjs). Projects that still need the legacy format must pass --eslintrc explicitly to the generator . This transition is why the installation chapter must cover the config generator: a bare npm install eslint produces no configuration, and ESLint does nothing without one.
The local versus global problem. ESLint’s documentation explicitly recommends against global installation. A global ESLint cannot resolve project-local plugins or shareable configs, because those packages are installed in the project’s node_modules, not the global prefix . The local install ensures that the ESLint version, the plugins, and the configuration all resolve from the same project context.
a. Node.js version requirements
The current ESLint release requires Node.js versions ^20.19.0, ^22.13.0, or >=24, built with SSL and ICU support . Official Node.js distributions include both by default.
# Verify the Node.js version before installing
node --version
# Expected: v20.19.0 or higher, v22.13.0 or higher, or v24+
# If the version is too old, upgrade Node.js first
# Using nvm:
nvm install 22
nvm use 22
The requirement is enforced at runtime. Running ESLint on an unsupported Node version produces an error rather than degraded behavior, which is preferable to silent misbehavior but still blocks installation workflows until the environment is corrected.
b. Local installation
The local install adds ESLint to the project’s devDependencies. The --save-dev flag places it there, which is correct because ESLint is a development tool and should not be part of the production dependency tree.
# Install ESLint locally
npm install --save-dev eslint
# Verify the installed version
npx eslint --version
The local binary lives at node_modules/.bin/eslint. Running it through npx resolves that binary rather than downloading a temporary copy, as long as the local install exists. The documentation notes that global installation is possible but “not recommended,” and that plugins and shareable configs must be installed locally regardless .
c. The @eslint/create-config generator
The recommended installation path is not a bare npm install. It is the configuration generator, which installs ESLint along with any plugins the project needs and writes a flat config file.
# Using npm (requires package.json to exist)
npm init @eslint/config@latest
# Using npx directly
npx @eslint/create-config@latest
The generator checks for Node.js compatibility. Its own prerequisites are ^18.18.0, ^20.9.0, or >=21.1.0, which are lower than ESLint v10’s requirements because the generator may run before the ESLint version is resolved . After the ESLint version is installed, the stricter requirement applies.
The generator asks a sequence of questions to determine the configuration:
✔ How would you like to use ESLint? · problems (or syntax, or style)
✔ What type of modules does your project use? · esm (or commonjs)
✔ Which framework does your project use? · react (or vue, none)
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser (or node)
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm (or yarn, pnpm)
The answers determine which packages are installed (eslint, @eslint/js, globals, typescript-eslint, eslint-plugin-react, and so on) and what the generated eslint.config.js contains . The generator writes a flat config file using the modern export default syntax, with languageOptions for globals and parser settings, and a rules object for any rule customizations.
d. What the generator produces and what it misses
The generated eslint.config.js is a functional starting point, not a complete linting strategy. It enables the recommended rule set for the detected environment and configures the parser and globals. It does not enable type-aware rules (which require a tsconfig.json reference and additional configuration), does not add project-specific rules, and does not integrate with a formatter.
// A generated config typically looks like this:
import js from "@eslint/js";
import globals from "globals";
export default [
js.configs.recommended,
{
languageOptions: {
globals: {
...globals.node,
},
},
rules: {
// project-specific rules go here
},
},
];
The generated file is the foundation. The next chapter covers how to extend it with plugins, custom rules, and the eslint-config-prettier integration that prevents formatting conflicts.
Complete Example Session
# ============================================
# PART 1: VERIFY NODE.JS VERSION
# ============================================
node --version
# Expected output: v20.19.0 or higher, v22.13.0 or higher, or v24+
# If the version is unsupported, upgrade before proceeding.
# ============================================
# PART 2: ENSURE package.json EXISTS
# ============================================
# The generator requires a package.json in the current directory
ls package.json
# If it does not exist:
npm init -y
# ============================================
# PART 3: RUN THE CONFIG GENERATOR
# ============================================
npm init @eslint/config@latest
# The generator installs @eslint/create-config temporarily,
# asks configuration questions, and writes eslint.config.js.
# ============================================
# PART 4: ANSWER THE GENERATOR QUESTIONS
# ============================================
# Example answers for a Node.js ESM project:
# How would you like to use ESLint? → problems
# What type of modules? → esm
# Which framework? → none
# TypeScript? → No
# Where does your code run? → node
# Install dependencies now? → Yes
# Package manager? → npm
# ============================================
# PART 5: INSPECT THE GENERATED CONFIG
# ============================================
cat eslint.config.js
# Expected structure: imports, js.configs.recommended,
# languageOptions with globals, empty rules object.
# ============================================
# PART 6: RUN ESLINT FOR THE FIRST TIME
# ============================================
npx eslint .
# ESLint analyzes all supported files and reports violations.
# A clean run exits with code 0.
# ============================================
# PART 7: FIX AUTO-FIXABLE ISSUES
# ============================================
npx eslint . --fix
# Rules that provide fixes are applied in place.
# Remaining violations are reported.
# ============================================
# PART 8: ADD AN NPM SCRIPT
# ============================================
# package.json:
# "scripts": { "lint": "eslint ." }
npm run lint
# Equivalent to npx eslint .
# ============================================
# PART 9: USE A SHARED CONFIG WITH THE GENERATOR
# ============================================
npm init @eslint/config@latest -- --config eslint-config-standard
# The --config flag specifies an npm-hosted shareable config
# instead of generating rules from scratch.
# ============================================
# PART 10: TROUBLESHOOT A VERSION FAILURE
# ============================================
# If ESLint fails with a Node version error:
# 1. Check node --version
# 2. Upgrade Node.js to a supported version
# 3. Delete node_modules and package-lock.json
# 4. Reinstall: npm install
# 5. Re-run: npx eslint --version
The ten parts covered version verification, package initialization, generator invocation, question answering, config inspection, first run, auto-fix, npm scripting, shared config usage, and version failure troubleshooting.
Quick Reference
Node.js requirements
| ESLint version | Node.js requirement |
|---|---|
| v10.x | ^20.19.0 || ^22.13.0 || >=24 |
| v9.x | ^18.18.0 || ^20.9.0 || >=21.1.0 |
Installation commands
| Method | Command |
|---|---|
| Generator (npm) | npm init @eslint/config@latest |
| Generator (npx) | npx @eslint/create-config@latest |
| Local install only | npm install --save-dev eslint |
| Global install (not recommended) | npm install --global eslint |
Generator options
| Flag | Effect |
|---|---|
--config <name> | Use a specific shareable config from npm |
--eslintrc | Generate legacy .eslintrc format instead of flat config |
Generated files
| File | Purpose |
|---|---|
eslint.config.js | Flat config (default output) |
eslint.config.mjs | ESM flat config (if project type is module) |
Best Practices
✅ Do This:
# Verify Node.js version before installing
node --version # ✅
# Use the config generator for new projects
npm init @eslint/config@latest # ✅
# Install ESLint locally, not globally
npm install --save-dev eslint # ✅
# Run the generated config against the project immediately
npx eslint . # ✅
❌ Don’t Do This:
# Install ESLint globally and expect plugins to resolve
npm install --global eslint # ❌
# Run the generator without a package.json
npm init @eslint/config@latest # ❌ (fails)
# Ignore the Node version requirement
node --version # v18.x # ❌
# Treat the generated config as complete without review
cat eslint.config.js # no project-specific rules # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
npm init @eslint/config fails | No package.json in the directory | Run npm init -y first |
| ESLint throws Node version error | Node.js is below the required minimum | Upgrade Node.js to a supported version |
| Plugins cannot be found | ESLint installed globally, plugins installed locally | Install ESLint locally; remove global install |
| Generated config uses wrong module type | Answer to “module type” question was incorrect | Re-run generator or edit eslint.config.js manually |
eslint.config.js not recognized | ESLint v8 installed instead of v9/v10 | Verify npx eslint --version; upgrade if needed |
Real-World Examples
1. Check Node.js version
node --version
2. Run the config generator
npm init @eslint/config@latest
3. Run the generator with npx directly
npx @eslint/create-config@latest
4. Use a shareable config
npm init @eslint/config@latest -- --config eslint-config-standard
5. Generate legacy eslintrc format
npm init @eslint/config@latest -- --eslintrc
6. Install ESLint locally without the generator
npm install --save-dev eslint
7. Verify ESLint version
npx eslint --version
8. Inspect the generated config
cat eslint.config.js
9. Run ESLint with auto-fix
npx eslint . --fix
10. Add a lint script to package.json
{ "scripts": { "lint": "eslint ." } }
Visual
The installation and configuration flow
┌─────────────────────────────────────────────────────────────┐
│ ESLINT INSTALLATION FLOW │
│ │
│ 1. Verify Node.js version │
│ │ │
│ ▼ │
│ 2. Ensure package.json exists │
│ │ │
│ ▼ │
│ 3. Run npm init @eslint/config@latest │
│ │ │
│ ├── Answer module type question │
│ ├── Answer framework question │
│ ├── Answer TypeScript question │
│ └── Answer environment question │
│ │ │
│ ▼ │
│ 4. Generator installs dependencies │
│ │ │
│ ▼ │
│ 5. Generator writes eslint.config.js │
│ │ │
│ ▼ │
│ 6. npx eslint . (verify it works) │
└─────────────────────────────────────────────────────────────┘
Node.js version support across ESLint majors
┌─────────────────────────────────────────────────────────────┐
│ NODE.JS SUPPORT BY ESLINT VERSION │
│ │
│ ESLint v9.x │
│ ^18.18.0 || ^20.9.0 || >=21.1.0 │
│ Supports Node 18, 20, 21+ │
│ │
│ ESLint v10.x │
│ ^20.19.0 || ^22.13.0 || >=24 │
│ Drops Node 18 (EOL April 2025) │
│ Requires Node 20.19.0+ (require(esm) support) │
│ Requires Node 22.13.0+ (LTS patch level) │
│ │
│ The pattern: each major release tracks Node.js EOL dates. │
└─────────────────────────────────────────────────────────────┘
What the generator asks and produces
┌─────────────────────────────────────────────────────────────┐
│ GENERATOR QUESTION → CONFIG OUTPUT │
│ │
│ "Module type?" │
│ esm → import syntax in config, ESM parser │
│ commonjs → require in config, script parser │
│ │
│ "Framework?" │
│ react → eslint-plugin-react, react hooks rules │
│ vue → eslint-plugin-vue │
│ none → no framework plugin │
│ │
│ "TypeScript?" │
│ yes → typescript-eslint, parser, type-aware rules │
│ no → default parser │
│ │
│ "Where does code run?" │
│ browser → browser globals (window, document) │
│ node → node globals (process, __dirname) │
└─────────────────────────────────────────────────────────────┘
Local vs global resolution
┌─────────────────────────────────────────────────────────────┐
│ WHY LOCAL INSTALLATION IS REQUIRED │
│ │
│ Project structure: │
│ project/ │
│ ├── node_modules/ │
│ │ ├── eslint/ ← local ESLint │
│ │ └── eslint-plugin-react/ ← local plugin │
│ ├── eslint.config.js │
│ └── package.json │
│ │
│ Global ESLint tries to resolve eslint-plugin-react: │
│ /usr/local/lib/node_modules/eslint-plugin-react │
│ → Not found (plugin is in project/node_modules) │
│ → Error │
│ │
│ Local ESLint resolves the plugin from the same node_modules │
│ tree. That is why the docs say: install locally. │
└─────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| ESLint v10 Node requirement | ^20.19.0 || ^22.13.0 || >=24 |
| ESLint v9 Node requirement | ^18.18.0 || ^20.9.0 || >=21.1.0 |
| Recommended install command | npm init @eslint/config@latest |
| Direct generator command | npx @eslint/create-config@latest |
| Local install only | npm install --save-dev eslint |
| Generated file | eslint.config.js (flat config) |
| Legacy format flag | --eslintrc |
| Global install | Not recommended |
Key takeaways:
- Node.js version is a hard gate. ESLint v10 requires
^20.19.0 || ^22.13.0 || >=24. Verify the version before installing, because the failure mode is a runtime error, not a warning. - The patch-level minimums exist for a reason. Node 20.19.0 enabled
require(esm)by default, and ESLint v10 depends on it. Older patch releases in the same major line are unsupported. - The config generator is the recommended installation path.
npm init @eslint/config@latestinstalls ESLint, asks about the project, and writes a workingeslint.config.jsin one step. - The generator produces a starting point, not a finished configuration. It enables recommended rules for the detected environment but does not add project-specific rules, type-aware analysis, or formatter integration.
- Local installation is not optional for plugins. A global ESLint cannot resolve plugins installed in a project’s
node_modules. The documentation explicitly recommends against global installation for this reason. - The legacy
.eslintrcformat still exists but is no longer the default. Projects that need it must pass--eslintrcto the generator.
Remember: ESLint installation is two decisions in one step: the Node.js version determines whether ESLint can run, and the generator determines what ESLint will check. Verify the version first, because a version mismatch blocks everything else. Then run the generator, answer its questions accurately, and inspect the generated config before treating it as final. The generator saves the boilerplate, but it does not know your project’s conventions, your framework’s specific pitfalls, or whether you use a formatter. Those decisions belong to the configuration chapter, not the installation chapter.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!