---
changelog:
  category: Release
  version: ultracite@7.9.0
date: '2026-07-05T07:31:51Z'
seo:
  description: >-
    Update Biome to 2.5.2 and enable the newly-stabilized rules. This adds
    coverage for the rules promoted out of nursery in Biome 2.5.0, including
    noShadow…
title: ultracite@7.9.0
type: changelog
---
## Minor Changes

- aea7fc0: Update Biome to 2.5.2 and enable the newly-stabilized rules. This adds coverage for the rules promoted out of nursery in Biome 2.5.0, including `noShadow`, `noUnnecessaryConditions`, `noUnusedInstantiation` (formerly `noFloatingClasses`), `useArrayFind`, `useDestructuring`, `useGlobalThis`, `useErrorCause`, `noNestedPromises`, GraphQL validation rules, and the recommended Vue/Next.js domain rules.
- 2687cf9: Align the ESLint and Biome presets with the oxlint preset, which is now the benchmark for rule decisions across linters. ESLint: rules that oxlint deliberately disables are now off (`no-console`, `no-continue`, `id-length`, `new-cap`, `max-depth`, `no-implicit-coercion`, `no-underscore-dangle`, `init-declarations`, `n/no-sync`, `promise/always-return`, `promise/catch-or-return`, `import-x/no-commonjs`, `import-x/no-dynamic-require`, `import-x/no-nodejs-modules`, `import-x/unambiguous`, `import-x/no-anonymous-default-export`, `@typescript-eslint/explicit-member-accessibility`, `@typescript-eslint/explicit-module-boundary-types`, `@typescript-eslint/no-require-imports`, and the `unicorn` rules `explicit-length-check`, `max-nested-calls`, `no-process-exit`, `prefer-global-this`, `prefer-string-raw`, `prefer-top-level-await`); `consistent-type-definitions` now enforces `interface` instead of `type`, matching oxlint and Biome; `no-void` allows statement position to coexist with `no-floating-promises`; `import-x/no-named-as-default` is enabled; and `curly` and `no-unexpected-multiline` are re-enabled past `eslint-config-prettier`. Biome: `noAwaitInLoops` and `noIncrementDecrement` are now errors and the `useSortedKeys` assist is on (matching `no-await-in-loop`, `no-plusplus`, and `sort-keys` in the other presets), while `useGlobalThis` is off (matching `unicorn/prefer-global-this`).
- 73c1993: Require ESLint 10 for ESLint setups. The plugin suite upgrade (notably `eslint-plugin-unicorn` 70 and `eslint-plugin-astro` 2) requires ESLint 10, but `ultracite init` still installed `eslint@^9.0.0`, which crashed at config load time. Init now installs `eslint@^10.0.0` and `@eslint/js@^10.0.0`, and the presets are fixed for ESLint 10 compatibility: `settings.react.version` is pinned to `19.0.0` instead of `"detect"` (detection uses an API removed in ESLint 10), `react/jsx-filename-extension` and `react/forward-ref-uses-ref` are disabled (their implementations use removed APIs; the former is already off in the oxlint preset and the latter is covered by `react-doctor/no-react19-deprecated-apis`), the react config re-applies `eslint-config-prettier` so JSX formatting rules stay off (several crash under ESLint 10), and `import-x/no-unused-modules` is disabled (it is a warning-emitting no-op under ESLint 10). Note that some plugins (`eslint-plugin-github`, `eslint-plugin-react`, `eslint-plugin-jsx-a11y`, `eslint-plugin-solid`, `@tanstack/eslint-plugin-start`) have not yet updated their declared peer ranges to include ESLint 10 even though they work at runtime, so strict package managers may report peer dependency warnings.
- 4cfdf3d: Add `eslint-plugin-jsdoc` to the ESLint preset. The oxlint preset already enforces a set of jsdoc rules, but the ESLint preset had no jsdoc coverage at all. The plugin is now installed by `ultracite init` for ESLint setups and enables the same rule selection the oxlint preset enforces (`check-access`, `check-property-names`, `check-tag-names`, `empty-tags`, `implements-on-classes`, `no-defaults`, and the `require-*` description/name/type rules), keeping the two presets in lockstep.
- 0b8fc12: Upgrade the ESLint plugin suite and enable the new rules that ship with it. Notable bumps: `eslint-plugin-unicorn` 64 → 70 (adds a large batch of new correctness and quality rules), `eslint-plugin-astro` 1 → 2 (adds `no-omitted-end-tags`, now requires ESLint 10), `eslint-plugin-sonarjs` 4.0 → 4.1 (adds test-assertion and ReDoS rules like `super-linear-regex`), `eslint-plugin-svelte` 3.19 → 3.20 (adds `no-at-const-tags`), plus `@typescript-eslint`, `eslint-plugin-import-x`, `eslint-plugin-n`, `@vitest/eslint-plugin`, and others. Two Unicorn rules that were renamed are re-mapped in the config (`prefer-dom-node-dataset` → `dom-node-dataset`, `prevent-abbreviations` → `name-replacements`). Two new Unicorn rules are disabled: `prefer-temporal` (since `Temporal` still lacks broad runtime support) and `no-asterisk-prefix-in-documentation-comments` (it fights the conventional JSDoc comment style).
- 4440393: Bring the oxlint preset closer to ESLint parity with two new presets that run ESLint plugins through oxlint's JS plugin support: `ultracite/oxlint/github` (eslint-plugin-github) and `ultracite/oxlint/sonarjs` (eslint-plugin-sonarjs, 187 rules — type-aware rules are excluded since the JS plugin bridge provides no type information, and `no-reference-error` is off because the bridge provides no globals). `ultracite init` now adds both presets to generated oxlint configs and installs the two plugins; existing configs are untouched until the next `init`, and either preset can be dropped from `extends` to opt out (the plugins add roughly 1–3s to a lint run for the JS runtime bridge). Rule decisions mirror the oxlint benchmark in both directions: the ESLint preset now disables `sonarjs/file-header` (it errored on every file), `sonarjs/arrow-function-convention` (fights the formatter), `sonarjs/cyclomatic-complexity`, `sonarjs/max-lines`, `sonarjs/max-lines-per-function`, `sonarjs/nested-control-flow` (duplicates of core rules the preset disables), `sonarjs/shorthand-property-grouping` (conflicts with `sort-keys`), and `github/no-dataset` (conflicts with `unicorn/prefer-dom-node-dataset`), and sets `sonarjs/cognitive-complexity` to 20 to match Biome's `noExcessiveCognitiveComplexity`. Switching linters with `init` no longer removes dependencies that the newly selected linter still needs.
- f7025b1: Extend cross-linter parity to the framework presets and add an automated parity check. The oxlint react preset now explicitly lists all 102 non-nursery react/react-perf/jsx-a11y rules (previously only ~20 were configured, so most a11y and correctness rules silently never ran) and the next preset lists all 21 nextjs rules, with decisions matching the ESLint presets. The revived exhaustiveness test (the `oxlint --rules` markdown output it parsed is empty as of oxlint 1.72, so it was passing vacuously) also caught five newly stabilized rules which are now enabled: `getter-return`, `no-unreachable`, `oxc/branches-sharing-code`, `unicorn/prefer-export-from`, and `unicorn/prefer-single-call`. ESLint preset fixes that fell out of the audit: `no-loss-of-precision` and `no-duplicate-imports` are re-enabled for TypeScript files (their `@typescript-eslint` twins were removed in v8, leaving TS uncovered), `no-duplicate-imports` gets `allowSeparateTypeImports` to match oxlint, the react/vue configs now only re-apply the `react/`-`vue/`-prefixed entries of `eslint-config-prettier` so they can't clobber unrelated rules, the svelte preset keeps the formatting rules disabled that `eslint-plugin-svelte`'s own prettier preset lists, and `astro/semi` is off (Prettier owns formatting). A new `compare-rule-parity` script runs as part of `validate:configs`: it resolves the effective ESLint rule sets with ESLint's own config resolution, normalizes names to oxlint's, and fails on any divergence not recorded in an explicit allowlist — currently just two entries (`sonarjs/no-reference-error`, `unicorn/number-literal-case`), both with documented reasons.
- 223233f: Add [React Doctor](https://www.react.doctor) rules to the ESLint and Oxlint React, Next.js, and TanStack presets. This enables React Doctor's own rules — the "You Might Not Need an Effect" family (`no-fetch-in-effect`, `no-derived-state`, `no-mirror-prop-effect`, etc.) plus its render-performance, hydration, server-component, security, and framework-specific rules — via `eslint-plugin-react-doctor` and the `oxlint-plugin-react-doctor` JS plugin. Rules that React Doctor ports from `eslint-plugin-react`, `eslint-plugin-react-hooks`, and `eslint-plugin-jsx-a11y` are intentionally left off to avoid duplicate diagnostics with the plugins Ultracite already ships.

## Patch Changes

- d247ff2: Migrate stale linter and formatter configuration when switching toolchains during init. Running `ultracite init` now removes config files and dependencies for unselected Biome, ESLint/Prettier/Stylelint, or Oxlint/Oxfmt setups before writing the selected toolchain config.
- e24068b: Sort `package.json` keys when using Biome
