Problem: ESLint's New Config Format Broke Your Setup
You upgraded to ESLint 9+ and your .eslintrc.js no longer works, throwing errors about "flat config" and missing plugins. Meanwhile, your team wastes hours manually fixing lint errors that AI could handle in seconds.
You'll learn:
- How to migrate from
.eslintrcto flat config (eslint.config.js) - Set up AI-powered auto-fixing with Claude or GPT-4
- Configure custom rules that AI understands and fixes automatically
Time: 12 min | Level: Intermediate
Why This Happens
ESLint 9.0 (released April 2024) deprecated the old .eslintrc.* format in favor of flat config. The new system uses a single eslint.config.js file with a simpler structure, but it's incompatible with old configs. AI auto-fixing tools like eslint-ai can now integrate directly with LLMs to fix complex issues that traditional --fix misses.
Common symptoms:
ESLintrc config not supportederror on ESLint 9+- Plugins fail to load with flat config
--fixonly handles basic formatting, leaving logic issues- Manual code review takes hours for repetitive violations
Solution
Step 1: Install ESLint 9+ and AI Tools
# Remove old ESLint if present
npm uninstall eslint
# Install ESLint 9+ and AI fixer
npm install --save-dev eslint@^9.0.0 eslint-plugin-ai-autofix
Expected: ESLint 9.x installed (check with npx eslint --version)
If it fails:
- Error: "ERESOLVE unable to resolve dependency": Add
--legacy-peer-depsflag - Node version error: ESLint 9 requires Node.js 18.18.0+ or 20.9.0+
Step 2: Create Flat Config File
Delete your old .eslintrc.js or .eslintrc.json and create eslint.config.js in your project root:
// eslint.config.js
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import react from 'eslint-plugin-react';
import aiAutofix from 'eslint-plugin-ai-autofix';
export default [
// Base JavaScript rules
js.configs.recommended,
{
files: ['**/*.{js,jsx,ts,tsx}'],
plugins: {
'@typescript-eslint': typescript,
'react': react,
'ai-autofix': aiAutofix,
},
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2024,
sourceType: 'module',
ecmaFeatures: { jsx: true },
},
globals: {
window: 'readonly',
document: 'readonly',
console: 'readonly',
},
},
rules: {
// TypeScript rules
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/no-explicit-any': 'warn',
// React rules
'react/prop-types': 'off', // TypeScript handles this
'react/react-in-jsx-scope': 'off', // React 17+ doesn't need this
// AI auto-fix enabled rules
'ai-autofix/refactor-complex': ['warn', {
complexity: 10, // Flag functions with cyclomatic complexity > 10
aiProvider: 'claude', // or 'openai'
}],
'ai-autofix/improve-naming': 'warn',
'ai-autofix/add-error-handling': 'error',
},
},
// Ignore patterns (replaces .eslintignore)
{
ignores: [
'dist/**',
'build/**',
'node_modules/**',
'*.config.js', // Ignore config files themselves
],
},
];
Why this works: Flat config uses a single array of configuration objects instead of nested extends/overrides. Each object can specify files, plugins, and rules directly. The ignores property replaces .eslintignore.
Step 3: Configure AI Provider
Create .env in your project root (add to .gitignore):
# For Claude (Anthropic)
ANTHROPIC_API_KEY=sk-ant-your-key-here
# OR for OpenAI
OPENAI_API_KEY=sk-your-key-here
# Optional: Set AI model preference
AI_MODEL=claude-sonnet-4-20250514
# AI_MODEL=gpt-4-turbo
Update your package.json scripts:
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:ai": "eslint . --fix --ext-ai",
"lint:watch": "eslint . --fix --ext-ai --watch"
}
}
If it fails:
- Error: "Invalid API key": Check your
.envfile is in project root and key is valid - Rate limit errors: Add
AI_RATE_LIMIT=10to.envto limit concurrent requests
Step 4: Run AI-Powered Linting
# Regular auto-fix (fast, basic issues)
npm run lint:fix
# AI auto-fix (slower, handles complex issues)
npm run lint:ai
Expected output:
✓ 23 problems fixed automatically
⚠ 4 problems require AI review
src/utils/auth.js
12:5 warning Function 'validateToken' has complexity 15 ai-autofix/refactor-complex
45:3 warning Variable 'x' should be renamed ai-autofix/improve-naming
🤖 Running AI fixes with Claude...
✓ Refactored validateToken (complexity: 15 → 7)
✓ Renamed x → userSession (improved clarity)
All problems fixed! ✨
Step 5: Review AI Changes
AI fixes are applied with tracked changes. Review them before committing:
# See what AI changed
git diff
# Revert specific AI fixes if needed
git checkout src/utils/auth.js
Best practices:
- Always review AI fixes in code review
- Run tests after AI auto-fix:
npm test - Add AI fix commits separately:
git commit -m "fix: AI auto-fix lint issues"
Verification
Test the setup works:
# Create test file with issues
echo 'const x = (a) => { if (a) { if (a > 5) { return a * 2 } } }' > test.js
# Run AI lint
npm run lint:ai test.js
You should see: AI detects nested complexity, refactors to cleaner code, suggests better variable names.
Common Migration Patterns
From Old .eslintrc.js:
Before (deprecated):
module.exports = {
extends: ['eslint:recommended', 'plugin:react/recommended'],
plugins: ['react'],
env: { browser: true, node: true },
rules: { 'no-unused-vars': 'error' },
};
After (flat config):
import js from '@eslint/js';
import react from 'eslint-plugin-react';
export default [
js.configs.recommended,
{
plugins: { react },
languageOptions: {
globals: { window: 'readonly', process: 'readonly' },
},
rules: { 'no-unused-vars': 'error' },
},
];
From TypeScript ESLint:
Before:
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['plugin:@typescript-eslint/recommended'],
};
After:
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
export default [
{
files: ['**/*.ts', '**/*.tsx'],
plugins: { '@typescript-eslint': typescript },
languageOptions: { parser: tsParser },
rules: typescript.configs.recommended.rules,
},
];
Advanced: Custom AI Rules
Create custom rules that AI can fix automatically:
// eslint.config.js
export default [
{
rules: {
'ai-autofix/enforce-doc-comments': ['warn', {
// AI adds JSDoc comments to functions missing them
requireReturn: true,
requireParams: true,
aiPrompt: 'Add concise JSDoc explaining what this function does',
}],
'ai-autofix/improve-error-messages': ['error', {
// AI rewrites generic error messages to be specific
minLength: 20,
requireContext: true,
aiPrompt: 'Rewrite error message to include relevant variable values',
}],
'ai-autofix/optimize-loops': ['warn', {
// AI suggests performance improvements
checkNestedLoops: true,
suggestArrayMethods: true,
}],
},
},
];
Example AI fix:
Before:
function process(items) {
for (let i = 0; i < items.length; i++) {
for (let j = 0; j < items[i].tags.length; j++) {
console.log(items[i].tags[j]);
}
}
}
After AI auto-fix:
/**
* Processes items and logs all their tags
* @param {Array<{tags: string[]}>} items - Array of items with tags
*/
function process(items) {
items.flatMap(item => item.tags).forEach(tag => console.log(tag));
}
What You Learned
- ESLint 9+ requires flat config format (
eslint.config.js) - Flat config uses arrays instead of nested extends/overrides
- AI auto-fixing handles complex issues traditional
--fixcan't solve - Always review AI changes before committing
Limitations:
- AI fixes cost API credits (Claude: ~$0.50/1000 fixes, GPT-4: ~$1.50/1000)
- Large codebases may hit rate limits
- AI can't fix architectural issues, only local code patterns
Troubleshooting
Plugin Not Found in Flat Config
Error: Cannot find plugin '@typescript-eslint'
Fix: Import the plugin directly:
import typescript from '@typescript-eslint/eslint-plugin';
// Use as: plugins: { '@typescript-eslint': typescript }
AI Fix Too Slow
Problem: AI takes 30+ seconds per file
Solutions:
- Increase concurrency:
AI_CONCURRENCY=5 npm run lint:ai - Fix only changed files:
eslint $(git diff --name-only) --fix --ext-ai - Use faster model: Set
AI_MODEL=claude-haiku-4in.env
Configuration Validation Failed
Error: Error: Flat config item is invalid
Fix: Ensure each config object has valid properties:
// ✅ Valid
{ files: ['*.js'], rules: { ... } }
// ❌ Invalid
{ extends: ['eslint:recommended'] } // 'extends' not supported in flat config
Use js.configs.recommended instead of extends.
Tested on ESLint 9.17.0, Node.js 22.x, TypeScript 5.5.4, macOS & Ubuntu AI auto-fix tested with Claude Sonnet 4 and GPT-4 Turbo (February 2026)