TL;DR: ESLint reads your JavaScript or TypeScript code without running it and flags potential bugs, anti-patterns, and style violations. It integrates with VS Code to show warnings as red underlines in real time, and can fix many issues automatically with eslint --fix. For vibe coders, it is a free automated second pair of eyes on every line of AI-generated code.
Why AI Coders Need to Know This
AI tools generate code quickly, but they make specific classes of mistakes that ESLint catches reliably:
- Unused variables: AI declares variables it never uses — common in refactored code
- React hook rule violations: Calling hooks inside conditions or loops (causes hard-to-debug bugs)
- Missing
await: Some ESLint configs can flag un-awaited promises - Deprecated API usage: Using old patterns the ecosystem has moved away from
- Inconsistent code style: Mixed quote styles, missing semicolons, inconsistent spacing
Without ESLint, these issues hide until they cause bugs in production or make code reviews painful. With ESLint, they get flagged the moment the AI generates them — before you even save the file.
ESLint is used by 98% of major JavaScript and TypeScript projects. It is not optional infrastructure for serious development — it is table stakes.
How ESLint Works
ESLint performs static analysis — it reads your code as text, parses it into an AST (Abstract Syntax Tree), and applies rules to that tree. It does not run your code. This means it can check for problems instantaneously, without needing a server or browser.
Three ways you interact with ESLint:
- In the editor: The ESLint VS Code extension shows red and yellow underlines as you type. Hover for the rule name and explanation.
- In the terminal:
npx eslint .checks all files and lists every violation with file, line number, and rule name. - In CI:
npx eslint . --max-warnings 0fails your build pipeline if any ESLint violations exist, blocking bad code from being merged.
Real Scenario
You asked Cursor to refactor a React component. The AI rewrote it and moved some logic around. One of the hook calls ended up inside an if-statement. React requires hooks to be called unconditionally — this is a subtle bug that will cause a crash only under specific conditions. ESLint catches it immediately.
Prompt I Would Type
Add ESLint to my Next.js TypeScript project:
- Use the recommended config for Next.js and TypeScript
- Add the React hooks rules plugin
- Configure it to error on unused variables and warn on console.log
- Set up the VS Code extension integration
- Add an npm script: "lint": "eslint . --ext .ts,.tsx"
What AI Generated
# Install ESLint and plugins
npm install --save-dev eslint @eslint/js \
typescript-eslint \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-config-next
// eslint.config.js — ESLint 9 flat config format
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import reactHooks from 'eslint-plugin-react-hooks';
import next from '@next/eslint-plugin-next';
export default tseslint.config(
// Base recommended rules
js.configs.recommended,
...tseslint.configs.recommended,
// Next.js specific rules
{
plugins: { '@next/next': next },
rules: { ...next.configs.recommended.rules }
},
// React Hooks rules
{
plugins: { 'react-hooks': reactHooks },
rules: reactHooks.configs.recommended.rules
},
// Custom rules
{
rules: {
'no-unused-vars': 'off', // Use TS version instead
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_', // Ignore _prefixed params
varsIgnorePattern: '^_'
}],
'no-console': ['warn', { // Warn on console.log
allow: ['warn', 'error'] // Allow console.warn/error
}],
'@typescript-eslint/no-explicit-any': 'warn',
}
},
// Ignore patterns
{ ignores: ['.next/', 'node_modules/', 'dist/'] }
);
// package.json scripts
{
"scripts": {
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix"
}
}
// .vscode/settings.json — auto-fix on save
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "typescript", "javascriptreact", "typescriptreact"]
}
Understanding Each Part
Rules and severity levels
Each ESLint rule has a severity:
"error"— Red underline. Failseslint --max-warnings 0. Blocks CI."warn"— Yellow underline. Noted but does not fail CI."off"— Rule disabled entirely.
Use "error" for things that will definitely break your app. Use "warn" for things that are bad practice but not immediately broken. The goal is zero errors, then gradually zero warnings.
eslint --fix
Many ESLint rules are auto-fixable. Running npx eslint . --fix applies safe automatic fixes — removing unused imports, adding missing semicolons, converting var to const. It will not fix everything, but it handles the tedious mechanical issues.
The React Hooks rules
The eslint-plugin-react-hooks plugin enforces the Rules of Hooks — React's requirements for where and how hooks can be called:
- Only call hooks at the top level of a function component (not inside loops, conditions, or nested functions)
- Only call hooks from React function components or custom hooks
Violating these rules causes React to maintain the wrong internal state. The error only manifests under specific runtime conditions, making it extremely hard to debug without ESLint flagging it at the source.
The _ prefix convention
argsIgnorePattern: '^_' means variables starting with underscore are exempt from the "unused variable" rule. This is the universal convention for "I know this is unused, intentionally." Common in callbacks where you need the second parameter but not the first:
// Without the pattern, ESLint would error on 'event'
array.forEach((_item, index) => {
console.log(index); // only using index, not _item
});
What AI Gets Wrong With ESLint
Mixing old .eslintrc and new flat config
ESLint 9 uses eslint.config.js. ESLint 8 and earlier used .eslintrc.json or .eslintrc.js. AI generates both formats interchangeably. They are not compatible. For new projects, use the flat config format. For existing projects that use .eslintrc, do not mix in flat config files.
Disabling rules instead of fixing the code
AI sometimes responds to ESLint errors by adding // eslint-disable-next-line comments instead of fixing the underlying issue. Disabling a rule is occasionally appropriate (false positives), but it is often a code smell. Prefer fixing the code.
Plugin version mismatches
ESLint plugins have peer dependency requirements. AI installs plugin versions that may not be compatible with your ESLint version, causing cryptic initialization errors. Check the plugin's documentation for the compatible ESLint version range.
ESLint with AI Rule
After every AI coding session that adds new files, run npx eslint . --fix before committing. This catches the class of AI mistakes ESLint is designed for, auto-fixes what it can, and leaves a clean commit for anything it cannot.
What to Learn Next
- What Is Prettier? — ESLint's partner for code formatting.
- What Is Git? — Add ESLint to pre-commit hooks with Husky.
- VS Code for AI Coders — Configure ESLint in your editor for real-time feedback.
- What Is TypeScript? — TypeScript + ESLint is the strongest combination for code quality.
Next Step
If you do not have ESLint installed: run npm init @eslint/config@latest in your project directory. It will ask a few questions and set up a working config automatically. Then install the ESLint VS Code extension and watch the red underlines appear.
FAQ
ESLint is a static analysis tool that reads your JavaScript or TypeScript code and flags potential errors, anti-patterns, and style violations before you run it. It integrates with VS Code to show warnings in real time and can auto-fix many issues with eslint --fix.
ESLint catches bugs and quality issues (unused variables, hook violations, bad patterns). Prettier handles formatting only (spacing, quotes, line breaks). They complement each other — use both. Configure ESLint to defer formatting decisions to Prettier to avoid conflicts.
Yes. Install typescript-eslint to enable TypeScript support. It provides a TypeScript parser and TypeScript-specific rules that can use type information to catch more subtle bugs than the base ESLint rules alone.
Yes, always. AI tools generate code that looks correct but often contains unused variables, React hook violations, or deprecated API usage. ESLint catches these automatically in real time and during CI, giving you a free automated review layer on top of AI generation.
ESLint 9 replaced the old .eslintrc files with a new eslint.config.js format. It is more explicit, uses standard JavaScript imports, and is simpler to compose from multiple sources. New projects should use flat config. If your project has .eslintrc.json, it is using the old format — it still works but will be deprecated.