Eeslint

eslint/v9-to-v10

Migrate ESLint projects from v9 to v10 — runs all four v9-to-v10 codemods in a single pass

transformationmigrationeslintv9v10recipe
PublicBundle
7 executions

Run locally

npx codemod @eslint/v9-to-v10

@eslint/v9-to-v10

Migrate ESLint projects from v9 to v10 in a single command. This recipe runs all four v9-to-v10 codemods in sequence.

Usage

bash

What This Recipe Does

This recipe combines the following four codemods into one workflow:

CodemodWhat it handles
@eslint/v9-to-v10-configRemove legacy env vars (ESLINT_USE_FLAT_CONFIG) and deprecated CLI flags from shell scripts, package.json scripts, and CI/CD YAML
@eslint/v9-to-v10-custom-rulesMigrate deprecated context methods and SourceCode methods in custom rule implementations
@eslint/v9-to-v10-ruletesterRemove properties from RuleTester test cases that ESLint v10 now rejects
@eslint/v9-to-v10-linter-apiFix removed Linter/ESLint constructor options, deprecated instance methods, and stricter built-in rule schemas

Steps (in order)

#StepTransform
1Remove legacy flags (JS/TS)ESLINT_USE_FLAT_CONFIG, ESLINT_FLAGS values, --no-eslintrc, --env, --rulesdir, --ignore-path, --resolve-plugins-relative-to from child_process calls
2Remove legacy flags (JSON)Same removals in package.json scripts values
3Remove legacy flags (YAML)Same removals in CI run: steps
4Replace context methodscontext.getFilename()context.filename, getCwd()cwd, etc.; parserOptionslanguageOptions.parserOptions
5Replace SourceCode methodsgetTokenOrCommentBefore/After()getTokenBefore/After({ includeComments: true }); isSpaceBetweenTokens()isSpaceBetween()
6Clean up valid test casesRemove errors and output from valid cases in ruleTester.run()
7Clean up invalid test casesRemove type from error objects in invalid cases in ruleTester.run()
8Fix Linter constructorRemove configType, useFlatConfig; strip deprecated flag values; flag deprecated methods
9Fix rule optionsfunc-names 4th element, no-invalid-regexp duplicate flags, radix deprecated string options
10Fix LintMessageRemove nodeType property from LintMessage objects; flag .nodeType member accesses

After Running

Search for TODO comments added by this recipe and address them manually:

TODO commentAction required
configType "eslintrc" is removedRewrite the integration to use flat config (eslint.config.js)
defineParser() removed in ESLint v10Register parsers in eslint.config.js languageOptions.parser
defineRule() removed in ESLint v10Register rules in eslint.config.js plugins
defineRules() removed in ESLint v10Register rules in eslint.config.js plugins
getRules() removed in ESLint v10Use ESLint.getRulesMetaForResults() instead
LintMessage.nodeType was removedRemove the surrounding expression that reads .nodeType
context.parserPath removed in ESLint v10Use context.languageOptions.parser (object, not path string)
getJSDocComment removed in ESLint v10Use sourceCode.getCommentsBefore(node) with a third-party JSDoc library
"as-needed" is removed in ESLint v10Remove "as-needed" from the radix config or disable the rule

Limitations

The following cases require manual attention and are not auto-transformed:

  • /* eslint-env */ comments — not removed; add the corresponding globals to eslint.config.js using the globals package
  • Template strings with interpolations in execSync/exec calls — skipped; inspect and update manually
  • loadESLint({ useFlatConfig, ...extras }) — not transformed when extra options are present alongside useFlatConfig
  • Aliased ESLint imports (import { Linter as L } from 'eslint') — linter-api transforms are not applied to renamed bindings
  • func-names with nested options objects — only flat option objects are matched
  • radix: ['error', 'always', ...]'always' is only stripped when it is the sole option in the array

Resources

Ready to contribute?

Build your own codemod and share it with the community.