ultracite@8.1.0
Minor Changes
-
daf7b0f: Update Biome to 2.6.3. Biome 2.6 renamed
useSortedClassestouseTailwindSortedClassesand moved itsfunctionsoption to the top-leveltailwind.mergeFunctions, so the 8.0 core preset failed to load with “Found an unknown keyuseSortedClasses”. The core preset now uses the new name and lists the same functions undertailwind.mergeFunctionsand, forcvaandtv,tailwind.variantFunctions, which sorts the classes in their variant objects. The rule also switched to Tailwind CSS v4’s class order, soultracite fixre-sorts class lists whose order changed the first time it runs with Biome 2.6.Biome 2.6 also promoted 59 nursery rules to stable groups. The presets turn on the ones that match rules the Oxlint presets enable, or that have no Oxlint counterpart and fit the preset:
- Core:
noLoopFunc,noUnnecessaryTemplateExpression,useArraySome,useRegexpTest,useMathMinMax,noExcessiveNestedCallbacks(with a limit of 10, matchingmax-nested-callbacks),useDomNodeTextContent,useDomQuerySelector,useImportsFirst,useNamedCaptureGroup,useUnicodeRegex,useVarsOnTop,useThisInClassMethods,useReduceTypeParameter,useIframeSandbox,noDuplicateFieldDefinitionNamesfor GraphQL,noDuplicateSelectorsanduseBaselinefor CSS, andnoEmptyObjectKeysandnoTopLevelLiteralsfor JSON. - React:
noComponentHookFactories,noJsxNamespace,noJsxLeakedDollar,noReactStringRefsanduseReactAsyncServerFunction. - Vue:
noVueImportCompilerMacros,noVueRefAsOperand,noVueVOnNumberValues,useVueValidVFor,useScopedStyles,useVueConsistentDefinePropsDeclarationanduseVueNextTickPromise. - Astro:
useScopedStyles, which reports<style is:global>. - Svelte:
noInlineStyles, matching ESLint’ssvelte/no-inline-styles. - Qwik:
useQwikLoaderLocation. - Jest and Vitest:
noConditionalExpect,noIdenticalTestTitle,useExpect,useTestHooksInOrder,useTestHooksOnTop, anduseConsistentTestItset totest()at the top level andit()insidedescribe, matchingconsistent-test-it’s defaults.
noInlineStylesstays off outside Svelte,noExcessiveSelectorClassesstays off because it has no default limit, andnoUntrustedLicensesstays off because it readsnode_modules, which the preset ignores.GraphQL files are now sorted. The core preset has always turned on
useSortedSelectionSet, but Biome only runs assist actions on GraphQL files whengraphql.assist.enabledis set, so it never ran. The preset now sets it and turns on Biome 2.6’suseGraphqlSortedDefinitions,useGraphqlSortedVariablesanduseGraphqlSortedArguments, whose fixesultracite fixapplies. Biome marks the selection-set fix unsafe, because GraphQL returns fields in the order they’re selected, so selection sets are reported byultracite checkand only sorted byultracite fix --unsafe.Biome 2.6 formats and lints YAML, SCSS and Markdown. YAML and SCSS files are now formatted like the rest of the project. The core preset turns Biome’s Markdown formatter off, because in 2.6.3 it drops the space before some inline code spans and changes the rendered text, so
.mdfiles are left as they were. It turns on Markdown frontmatter parsing, so the linter reads a leading---block as frontmatter rather than a heading.Requires @biomejs/biome >= 2.6.2
- Core:
-
d8124d5: Ultracite now requires Node.js 22.22.2 or later on Node 22, or 24.15 or later; Bun is unchanged.
eslint-plugin-jsdoc, which every ESLint setup installs, has declared that range since version 64, so on older Node versions npm and pnpm warned when installing it and Yarn 1 refused to install it. Two ESLint framework plugins declare more:@darraghor/eslint-plugin-nestjs-typed(thenestjspreset) asks for Node.js 24 andeslint-plugin-astro(theastropreset) for 22.22.3 or 24.16. Both run on older versions, but Yarn 1 enforces what they declare. -
9a1ce92: Format
.astrofiles with Oxfmt. When the project or one of its workspaces uses Astro,ultracite initturns on Oxfmt’sastrooption in the rootoxfmt.config.tsand installs@astrojs/compiler-rs, the compiler that Oxfmt’s bundledprettier-plugin-astroloads. Until now, Oxfmt skipped.astrofiles. For Astro 6 and earlier, which keep line breaks between tags as spaces, it writesastro: { compressHTML: "html" }so formatting can’t change what a page renders. Anastrovalue already in the config is kept, soastro: falsestill opts out.ultracite upgradekeeps the compiler at the version this release was tested with, and switching from Oxlint to another linter removes it. Existing projects get it by re-runningultracite init, or by settingastro: trueby hand as described in Formatting Astro files. Oxfmt formats.astrofiles from 0.73.0; older releases ignore the option. -
e4be64a: Add
playwright,react-nativeanddrizzleframework presets.ultracite initoffers them, and pre-selects them when the project depends on@playwright/test,react-nativeordrizzle-orm(React Native also pre-selects React). The ESLint presets use each library’s ESLint plugin, the Biome presets use the rules Biome 2.6 made stable, and the Oxlint presets add no plugin rules, because Oxlint has no plugin for these libraries.- Playwright:
ultracite/eslint/playwrightturns on every rule ineslint-plugin-playwrightin test files, exceptno-hooks,require-soft-assertionsandrequire-tags, which would report ordinary tests.ultracite/biome/playwrightturns on Biome’s Playwright rules, such asnoPlaywrightMissingAwaitandnoPlaywrightWaitForTimeout, and the test rules the Jest and Vitest presets use, such asnoFocusedTestsanduseExpect. It leaves outuseConsistentTestIt, because Playwright has noit(). On every linter, a hook that only needstestInfo, as intest.beforeEach(async ({}, testInfo) => ...), no longer trips core’s empty-pattern rule. - React Native:
ultracite/eslint/react-nativeturns on the rules ineslint-plugin-react-nativeand Meta’s@react-native/eslint-plugin, such asno-raw-text,no-unused-stylesandno-deep-imports.eslint-plugin-react-nativehasn’t been updated for ESLint 10, so the preset wraps it with@eslint/compat, whichinitinstalls too, and npm projects get a peer override for it.ultracite/biome/react-nativeturns onnoReactNativeRawText,noReactNativeLiteralColors,noReactNativeDeepImportsanduseReactNativePlatformComponents. Both declare the__DEV__global. - Drizzle: both presets turn on the rules that report a
delete()orupdate()with no.where()(eslint-plugin-drizzleand Biome’snoDrizzleDeleteWithoutWhereandnoDrizzleUpdateWithoutWhere), for objects nameddbortx. Without a name, the ESLint rules report every.delete()call,Map#deleteincluded, and the Biome rules report nothing.
These rules check their libraries’ APIs, which is why they’re in presets rather than in core. On Biome they would otherwise misfire: an explicit severity overrides Biome’s dependency check, so
noReactNativeRawTextin core would report text inside any JSX element, including a<div>. - Playwright:
Patch Changes
-
72890be: Update
eslint-plugin-unicornto 79. The ESLint preset turns on its two new rules,no-unnecessary-default-argumentsandno-repeated-call-wrappers, like every other Unicorn rule. Unicorn 79 stoppedno-top-level-side-effectsfrom reporting unknown calls during module evaluation by default; the preset sets its newcheckUnknownCallsoption, so it keeps reporting them as it did with Unicorn 77.prefer-ternaryandprefer-minimal-ternarynow also merge branches that differ only in the callee or a computed member, such as(test ? a : b)(value).Unicorn 78 also reports code that contains comments, which many rules used to skip, and
prefer-default-parametersnow checks fallback expressions, so existing code can get new reports. Unicorn 79 turns autofixes that could change behaviour in rare cases into suggestions, in rules such asprefer-spreadandprefer-math-min-max. -
72890be: Update the ESLint plugins
initinstalls: typescript-eslint 8.72,eslint-plugin-jsdoc65.4,eslint-plugin-n18.5,eslint-plugin-jest29.17,@vitest/eslint-plugin1.6.28,@next/eslint-plugin-next16.4,@angular-eslint/eslint-plugin22.6,eslint-plugin-svelte3.23.1,eslint-plugin-storybook10.6.3,eslint-plugin-qwik1.20.3,@tanstack/eslint-plugin-query5.104.5,@darraghor/eslint-plugin-nestjs-typed7.5.8,eslint-plugin-react-doctor0.9.18 andprettier-plugin-astro1.1.2, plus the Oxlint JS pluginsoxlint-plugin-react-doctor0.9.18 and@shadcn/lint0.2.3. None of them adds or removes a rule, so the presets are unchanged. The releases fix false positives and add options the presets leave at their defaults, such as typescript-eslint’sawait-thenableallowMixedPromiseArraysand jsdoc’scheck-alignmentignoreEmptyLines. The presets were checked against ESLint 10.13. -
14b8e04: Update oxfmt to 0.74.0. Markdown files are now formatted by oxfmt’s own Markdown formatter instead of its bundled Prettier, so
ultracite fixcan reformat some.mdfiles that were already clean, including sorting imports in JavaScript and TypeScript code blocks..mdxfiles still go through Prettier. The releases also add anastrooption that formats.astrofiles throughprettier-plugin-astro(it needs@astrojs/compiler-rsinstalled in the project) and anassociationsoption that formats files as a chosen language. See the 0.72.0, 0.73.0 and 0.74.0 release notes for the full list of formatting fixes. -
1fa337e: Update oxlint to 1.89.0 and
oxlint-tsgolintto 7.0.2005. The releases add no rules, so the Oxlint presets are unchanged and theoxlintpeer range stays at^1.86.0. Several rules now report cases they used to miss, so upgrading can surface new errors in existing code:prefer-constchecks destructuring assignments inside blocks,sort-keyscompares computed identifier keys,no-param-reassignreports writes to rest parameters, andunicorn/prefer-string-replace-allfollows regexes stored in variables.react/no-unescaped-entities,react/jsx-no-target-blankandunicorn/no-useless-switch-casenow offer suggestions. See the 1.87.0, 1.88.0 and 1.89.0 release notes for the full list. -
5eeb6e5:
ultracite fix --hookno longer fixes the whole project when it can’t read an edited file’s path from the agent’s hook payload. A payload with no path, one in a shape the hook doesn’t know, text that isn’t JSON, or stdin that can’t be read now fixes nothing. The whole-project run it used to fall back to could reformat files the agent never touched. Payloads that name the edited file are fixed as before.