Repository navigation
chore(deps): update dependency ultracite to v8 - #32
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
renovate
Bot
force-pushed
the
renovate/ultracite-8.x
branch
2 times, most recently
from
October 20, 2026 20:33
5d79e09 to
7826f17
Compare
renovate
Bot
force-pushed
the
renovate/ultracite-8.x
branch
4 times, most recently
from
October 26, 2026 16:58
a520554 to
ad84976
Compare
renovate
Bot
force-pushed
the
renovate/ultracite-8.x
branch
from
November 1, 2026 21:30
ad84976 to
9b2ebdb
Compare
renovate
Bot
force-pushed
the
renovate/ultracite-8.x
branch
from
November 6, 2026 00:51
9b2ebdb to
c9bab83
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This PR body was truncated due to platform limits.
This PR contains the following updates:
^7.6.1→^8.0.0Release Notes
haydenbleasel/ultracite (ultracite)
v8.1.1Compare Source
Patch Changes
79d73d9: Update Biome to 2.6.4. The release adds 30 nursery rules, which the Biome presets leave off, and promotes or removes none, so the presets are unchanged and the@biomejs/biomepeer range stays at^2.6.2. TheuseSortedPropertiesassist that core turns on now followsstylelint-config-recess-order7.9.0, soultracite fixcan reorder CSS properties it used to leave alone, such asscroll-behavior, anchor positioning and multi-column layout. It also no longer offers a sort that would change which of two overlapping declarations wins.noShorthandPropertyOverridesalso recognises overrides of logical border, corner shape,position-try,text-boxandtransition-behaviorproperties. The Markdown formatter stays off in core: 2.6.4 fixes the dropped space before inline code, but it still rewrites a literal[ ]in prose to[]. See the 2.6.4 release notes.3572b86: Update the ESLint packagesinitinstalls: typescript-eslint 8.72.1,eslint-plugin-vue10.12,eslint-plugin-storybook10.6.5,@tanstack/eslint-plugin-query5.105.1,@react-native/eslint-plugin0.88.1,globals17.14 andeslint-plugin-react-doctor0.9.21, plus the Oxlint JS pluginoxlint-plugin-react-doctor0.9.21. The presets were checked against ESLint 10.14.The Vue preset turns on
eslint-plugin-vue's three new rules automatically:vue/no-content-outside-blockreports content outside the top-level blocks of a.vuefile, which the compiler drops;vue/no-define-model-defaultreports adefaultindefineModel(); andvue/no-props-shadowreports<script setup>declarations that shadow a prop. The newblock-langrequiredandrequire-explicit-emitsignoreMixinsoptions stay at their defaults: the first would reject components without a given block, and the second skips components that use mixins.react-doctor 0.9.21 adds
react-doctor/forwarded-set-state-in-effect, which reports a state setter passed from an effect to a helper that calls it synchronously, such asuseEffect(() => syncFrom(id, setValue), [id]). It is on in the ESLint React preset and inultracite/oxlint/js-plugins. Setters handed to subscriptions, timers and listeners aren't reported.6675a90: Update oxfmt to 0.75.0. The release changes no options. It fixes a run of formatting bugs, among them parentheses dropped around privateinchecks and instantiation expressions, a;dropped before class members namedinorinstanceof, and its width heuristics now measure display width, so lines with wide characters (such as CJK text) can wrap differently after upgrading. Itsprettier-plugin-astrointegration now needs@astrojs/compiler-rs0.5, which is the versionultracite initinstalls. See the 0.75.0 release notes for the full list.3e83844: Update oxlint to 1.90.0 and enable its new type-aware rule,typescript/no-unsafe-enum-assignment, in the core Oxlint preset. It reports a value assigned, returned or passed where an enum is expected when it doesn't share that enum's type, such asconst fruit: Fruit = 1, matching the@typescript-eslintrule of the same name that the ESLint type-aware preset already enables. Like the other type-aware rules, it only runs withoxlint --type-awareandoxlint-tsgolintinstalled, and oxlint 1.90 needsoxlint-tsgolint7.0.2005 or later. Older oxlint releases fail to parse a config that names the rule, so theoxlintpeer range moves to^1.90.0.The release also makes a few rules report cases they used to miss:
array-callback-returnchecks callbacks passed with extra arguments,no-useless-concatsees through parentheses, andjest/no-conditional-expectchecks function expression callbacks. See the 1.90.0 release notes.Requires oxlint >= 1.90.0
v8.1.0Compare Source
Minor Changes
daf7b0f: Update Biome to 2.6.3. Biome 2.6 renameduseSortedClassestouseTailwindSortedClassesand 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:
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.noComponentHookFactories,noJsxNamespace,noJsxLeakedDollar,noReactStringRefsanduseReactAsyncServerFunction.noVueImportCompilerMacros,noVueRefAsOperand,noVueVOnNumberValues,useVueValidVFor,useScopedStyles,useVueConsistentDefinePropsDeclarationanduseVueNextTickPromise.useScopedStyles, which reports<style is:global>.noInlineStyles, matching ESLint'ssvelte/no-inline-styles.useQwikLoaderLocation.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
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: Addplaywright,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.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.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.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>.Patch Changes
72890be: Updateeslint-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 pluginsinitinstalls: 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, soultracite 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 andoxlint-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.v8.0.2Compare Source
Patch Changes
9f80955: Makeultracite fix --claudeand--codexjudge each retry by what the previous edit actually did. An issue that's still reported gets the old note asking for a structurally different approach, but one that only appeared after the edit is now handed back as new, with the agent told to build on the fix rather than undo it. Before, a correct ARIA button pattern that then trippedprefer-tag-over-role, or a correct<button>missing itstype, was treated as a failed fix and thrown away. When an issue needs a person's decision, the agent now lists it at the end of its final message. Ultracite stops retrying it and shows the agent's explanation in the summary, where it used to be discarded. The handoff also gets three fixes. Biome'sa11yrules now reach the agent with their help text and documentation link, which a pattern that didn't allow digits in a rule group had dropped. A path Oxlint has no files to lint, such as a Markdown file, no longer crashes the run. And Biome's internal errors, such asinternalError/iofor a file it can't write, are no longer handed to the agent as lint issues.30e03ef: Givejsx-a11y/label-has-associated-controlinultracite/oxlint/reactthe options the ESLint react preset already sets:<Label>counts as a label,<Input>,<Select>,<Textarea>,<Checkbox>and<Radio>count as controls, and a control is found up to three levels deep. Oxlint used to miss a<Label>with no control, and flagged an<Input>inside a<label>, or an input nested three deep, as unlabelled. Biome'snoLabelWithoutControlinultracite/biome/coregets the same label and control components.947ca03: Turn offpromise/prefer-await-to-theninultracite/oxlint/coreandultracite/eslint/core, andgithub/no-theninultracite/oxlint/js-pluginsandultracite/eslint/core. Both rules match.then(),.catch()and.finally()by method name, without type information, so they flagged APIs that aren't promises, such as Zod's.catch()fallback. They also flagged a fire-and-forget promise given a.catch()handler. Oxlint closed the false positive as not planned.promise/always-returnandpromise/catch-or-returnare now on in both presets, so an unhandled promise chain is still reported. In ESLint,unicorn/prefer-awaitmoves toultracite/eslint/type-aware, where it uses type information to skip calls that aren't on a promise. The test-file overrides that turnedpromise/prefer-await-to-thenoff in the jest and vitest presets are gone, since the rule is off everywhere.c198d06: Stopunicorn/no-useless-undefinedinultracite/oxlint/corefrom checking function call arguments. A required parameter typedstring | undefinedhas to be passedundefinedexplicitly, but Oxlint flaggedconsume(undefined)andultracite fixrewrote it toconsume(), which TypeScript rejects with TS2554. The rule can't see parameter types, so it now runs withcheckArguments: false. It still reportslet value = undefined,return undefinedand the rest of its checks.ultracite/eslint/coresets the same option. eslint-plugin-unicorn already skipped arguments in TypeScript files, and now skips them in JavaScript too. Biome'snoUselessUndefinednever checked arguments.v8.0.1Compare Source
Patch Changes
40d646a:ultracite fix --claudeand--codexhand agents better information and report results more accurately:no-unused-varsandtypescript/no-explicit-any, instead of Oxlint'seslint(no-unused-vars).json-with-metadataformatter. Biome diagnostics carry the rule's documentation URL and its description frombiome explain, since Biome's JSON reporter includes no help text.2543859: Update the vendoredanti-slopOxlint plugin to upstream commit13909c9and enable its three new rules in theultracite/oxlint/anti-sloppreset.require-readable-spacingrestores blank lines around structural boundaries — top-level declarations, multiline bindings, control flow, returns, and blocks — a pattern AI-generated code tends to pack together, while consecutive single-line bindings stay grouped at any scope (dmmulroy/anti-slop#45). Its autofix only inserts whitespace and never removes existing blank lines, soultracite fixrestores the spacing without fighting the formatter.no-array-filter-maprejects adjacent eagerfilter/mappasses over arrays, andno-reduce-accumulator-copyrejects reducers that copy their accumulator on every iteration. Expect a one-time whitespace-only diff fromultracite fixafter upgrading if you extend the preset (#803).0a671cc: On the ESLint toolchain,ultracite fix --hookno longer deletes an import an agent has just added. A post-edit hook runs between the agent's edits, so the import is unused until the code that uses it lands, andunused-imports/no-unused-importsremoved it first. The hook run now turns that rule off, as the Biome hook already skipsnoUnusedImports(#483).no-unused-varsstill reports the import if it stays unused.de08bd3: The ESLint core preset no longer configures anoderesolver forimport-x, which neededeslint-import-resolver-node, a packageinitnever installed. The TypeScript resolver it keeps resolves JavaScript files too.c13e042:react/jsx-no-target-blanknow checks forms as well as links (forms: true) in the Oxlint and ESLint React presets, as Biome'snoBlankTargetalready does. The rules fileinitwrites for agents now says to addrel="noopener noreferrer"totarget="_blank"links instead ofrel="noopener", which Oxlint and ESLint report because it still sends the referrer. It also says to avoid import cycles again, which the Oxlint and ESLint core presets report.9853406: Theoxlint.config.tsthatultracite initwrites now setsenv: core.env. Oxlint doesn't carryenvthroughextends, so the browser globals the core preset declares never reached projects, and rules that depend on them stayed quiet:no-implied-evaldidn't reportsetTimeout("…")orsetInterval("…"), andno-evaldidn't reportwindow.eval(…). Workspace configs written byinitnow repeatenv: root.envalongsideignorePatternsandsettings, and an.oxlintrc.jsonthatinitmigrates keeps itsenvon top of core's. Re-runultracite initto update an existing config, or addenv: core.envto it yourself.7984c6e: The Oxlintjs-pluginspreset now enables the 32 SonarJS rules that the ESLint core preset already runs without type information, including the security rulessonarjs/slow-regex,sonarjs/sql-queries,sonarjs/disabled-auto-escapingandsonarjs/dompurify-unsafe-config. SonarJS marks these rulesrequiresTypeChecking, but they also check the syntax tree, so they work through Oxlint's JS plugin bridge. The preset had left out every marked rule.v8.0.0Compare Source
Major Changes
d0875c0: Every agent now reads Ultracite's rules fromAGENTS.md.initwrites the rules there once, whichever agents you pick, and only adds a file for the four agents that need one more step to see them:AGENTS.mdonly when the project has noCLAUDE.md, soinitadds an@AGENTS.mdimport to the project'sCLAUDE.mdor.claude/CLAUDE.mdwhen there is one.GEMINI.mdby default, soinitaddsAGENTS.mdtocontext.fileNamein.gemini/settings.json, keepingGEMINI.md..aider.conf.ymlpointed atAGENTS.md, as before.replit.md, so it keeps a copy of the rules there.Firebender now reads
AGENTS.mdtoo. Theinitprompt asks which agents you use and listsAGENTS.md(Universal) plus those four.Projects set up by earlier versions move over the next time
initruns: it takes Ultracite's block out of.claude/CLAUDE.md,GEMINI.md,.firebender/rules/ultracite.mdcand Aider'sultracite.md, removes a file left with nothing else in it, and adds the import or settings that agent needs. That happens whenever one of those files still holds the rules, whichever agents you pick, since a leftover.claude/CLAUDE.mdstops Claude Code from readingAGENTS.md.A
CLAUDE.md,GEMINI.mdorreplit.mdthat is a symbolic link toAGENTS.md, or thatAGENTS.mdlinks to, already gives that agent the rules, soinitleaves it as it is.initnever writes through or removes a symbolic link to another file; it prints what to add to that file instead.3ee5b8c: Aider now loads Ultracite's rules and lints each file it edits. Aider reads no instructions file on its own, so theultracite.mdthatinit --agents aiderused to write was never loaded. Nowinitwrites the rules toAGENTS.mdand merges two keys into.aider.conf.yml:read: AGENTS.md, andlint-cmdset to the project'sultracite fix, which Aider runs on every file it edits, asking the model to fix whatever is left. The rest of the file, comments included, stays as written, alint-cmdthat runs another linter is left alone, and anultracite.mdthat holds nothing but the rules is removed. Aider keeps its own option in theinitprompt, since the universalAGENTS.mdoption doesn't write.aider.conf.yml.The agent list also uses the current names for Deep Agents, goose and Gemini CLI. Their
--agentsIDs don't change.f4c8a32: Make every rule in the Biome core preset an error.noSuspiciousSemicolonInJsxcame from Biome's recommended set at warning level, soultracite checkpassed with it unless the React preset was on. It and the two other rules core inherited from that set,noDuplicateJsxPropsandnoVoidElementsWithChildren, are now set toerrorexplicitly.ed5ed04:compat/compatis now an error in the ESLint core preset. It was the last warning-level rule in any preset, soultracite checkpassed while it reported browser APIs your browserslist targets don't support. Set your targets in abrowserslistkey inpackage.jsonor a.browserslistrcfile, or turn the rule off in your config if the project only runs on a server.A project that sets no targets is now checked against Baseline Widely available browsers (
baseline widely available). eslint-plugin-compat used browserslist'sdefaultsthere, which include Opera Mini and Chrome 109, sofetch,URLandArray#toSorted()failed in almost every project. Ultracite only sets these targets when it finds no browserslist config from the directory ESLint runs in and noBROWSERSLISTenvironment variable, since the plugin would add them to your own targets rather than replace them. In a monorepo that sets targets only in its packages, add them at the root too, or setsettings.browsersyourself.16fa476: Lint the scripts in Vue, Svelte and Astro components with the ESLint core rules. Core's globs only matched.jsand.tsfiles, so a.vuefile got only the Vue rules, a.sveltefile only the Svelte rules, and an.astrofile's frontmatter only the Astro rules, while Oxlint already runs its core rules on those scripts. Thevue,svelteandastropresets now apply core's rules to their components, including the TypeScript rules, with the type-checked ones off because a script block isn't part of a tsconfig.TaskList.vueis reported. SvelteKit route files (+page.svelte) are exempt, and Astro and Nuxt pages ([slug].astro,[id].vue) get the same route-aware pattern as otherpages/files, on ESLint and in Oxlint's JS plugins.prefer-const,unicorn/no-top-level-assignment-in-functionandsonarjs/declarations-in-global-scopeare off:svelte/prefer-constreplaces the first, and the other two misread$props()and$statein a component's scope. SvelteKit'sPagePropsandLayoutProps, and Astro'sProps, are allowed byunicorn/name-replacements.ed5ed04: Cypress and Storybook rules move out of the ESLint core preset into opt-in framework presets,ultracite/eslint/cypressandultracite/eslint/storybook. Core loaded both plugins for every project, soinitinstalledeslint-plugin-cypress,eslint-plugin-storybookand the wholestorybookpackage for every ESLint setup, whether or not the project used them.initnow offerscypressandstorybookwith the other frameworks (--frameworks cypress storybook). It preselects them whencypressorstorybookis inpackage.json, and installs their plugins only when you pick them. To keep linting Cypress specs and stories, add the presets toeslint.config.mjsaftercore:Oxlint and Biome have no Cypress or Storybook rules, so
ultracite/oxlint/cypress,ultracite/oxlint/storybook,ultracite/biome/cypressandultracite/biome/storybookare empty presets that keep the framework selectable with every linter.ed5ed04: ESLint and Stylelint no longer run Prettier as a rule.ultracite checkandultracite fixalready run Prettier as their own step, so theprettier/prettierrule fromeslint-plugin-prettierandstylelint-prettierformatted and reported every file a second time. The ESLint core preset and the Stylelint preset drop those plugins and keepeslint-config-prettier, so no lint rule fights Prettier, andinitno longer installseslint-plugin-prettierorstylelint-prettier.ESLint and Stylelint now report only lint problems. Formatting problems come from the Prettier step of
ultracite check, so runningeslintorstylelinton their own no longer reports formatting. A config that setsprettier/prettieritself now fails with an unknown-rule error: remove that setting, or install the plugin and register it in your own config to keep it.Zed formats with Prettier on the ESLint toolchain.
initused to set ESLint's language server as Zed's formatter for JavaScript, TypeScript and TSX, which only applied Prettier through theprettier/prettierrule, so in v8 Zed would have applied ESLint's fixes without formatting. It now keeps ESLint's fixes as code actions and sets"formatter": "prettier", so Zed's Prettier integration formats afterwards with your project's Prettier config and plugins. Re-runninginitupdates.zed/settings.json, andultracite upgrade --claudeor--codexmakes the same change.ed5ed04: The ESLint rules that need type information are now opt-in, as they already are on Oxlint and Biome. The core preset no longer turns on the project service or the type-checked@typescript-eslintrules, such asno-floating-promises,no-unsafe-returnandstrict-boolean-expressions, so it lints TypeScript without a tsconfig and without building a TypeScript program, which is much faster. Where a type-checked rule replaced a core ESLint rule on TypeScript files (no-implied-eval,no-throw-literal,prefer-destructuring,prefer-promise-reject-errors,require-await), core now runs the ESLint rule, as Oxlint does without type information. The 37 SonarJS rules and one Unicorn rule that do nothing without type information, such assonarjs/deprecation,sonarjs/no-ignored-returnandunicorn/no-non-function-verb-prefix, move with them. SonarJS rules that use type information only when it's there, such assonarjs/no-small-switchand its regular expression rules, stay in core.The type-checked rules live in a new
ultracite/eslint/type-awarepreset. Framework plugins with type-checked rules have an add-on after their preset:ultracite/eslint/<framework>/type-awareforangular,jest,nestjs,qwik,tanstackandvitest.init --type-awareadds the preset and the add-ons for the frameworks you pick, and re-runninginitwithout the flag keeps them. To keep type-aware linting, add them aftercoreand after each framework:7965ec2:ultracite fix --hooknow hands the problems it can't fix back to the agent. In Claude Code, CodeBuddy, Codex, Deep Agents, Grok Build and VS Code's Local agent (which runs the GitHub Copilot hook), the hook prints everything the linter and formatter report to stderr and exits with code 2 when problems remain, which those hosts show to the agent so it fixes them in its next step. Devin reads exit code 2 as "block", so under Devin the hook exits with 0 and passes the problems ashookSpecificOutput.additionalContextinstead. Cursor and the Copilot CLI and cloud agent don't pass a hook's output to the agent, so their hooks keep the previous output and exit code.ed5ed04:ultracite initnow asks before it changes files it doesn't own, and asks every question before it writes anything.ultracite checkwould still find and run the old linter.--yesremoves them without asking, as before..eslintrcfiles. ESLint 10 doesn't read them, so they can't conflict with the flat config, andultracite doctorno longer flags them on an ESLint setup. Moving to Biome or Oxlint still removes them.strictNullChecksin yourtsconfig*.jsonfiles when type-aware linting is on, since only the type-aware rules need it, and an interactive run lists the files and asks first. It used to change every tsconfig on every run.--type-awareisn't passed. A project that already has it keeps it.ed5ed04:ultracite inithas a--yes(-y) flag for running without prompts, and--quietnow only controls output.--yestakes the default for every question no flag answers, without asking. Init does this on its own whenCIistrueor1, or when there's no terminal to answer prompts in, so it never waits for input in a pipeline.--quietleaves out the intro banner, spinners and progress messages, and no longer skips the prompts. A script that raninit --quietto avoid them should pass--yes --quiet.checkorfixscript that init left as it was because it runs another tool.cbb349c: Add three agents, and rename Windsurf to Devin Desktop.init --agentsnow takesfx(Vercel Labs),antigravity(Antigravity CLI, Google's successor to Gemini CLI for consumer accounts) andgrok(Grok Build). All three readAGENTS.md.init --hooks grokwrites a post-edit hook to.grok/hooks/ultracite.jsonin Claude Code's format. Grok Build runs it after eachWriteorEditonce you trust project hooks with/hooks-trust, and hands the problemsultracite fix --hookleaves back to the model.fix --hooknow recognises Grok's own tool names (search_replace,hashline_edit), which it used to skip. Grok also reads.claude/settings.json, but runs a hook once when several files give it the same event, command and matcher, as the Claude Code and Grok Build hooks do, so a project can have both.devininstead ofwindsurf, which init still accepts with a note to switch. Its hook now goes in.devin/hooks.v1.json, which Devin Local reads.ed5ed04: Ultracite now requires Node.js 22.18 or later, or Bun, and says so in itsenginesfield. The CLI's dependencies have needed Node 22 since 7.10.0, so on Node 20 it stopped at startup withTEXT_ENCODINGS.union is not a function, and theoxlint.config.tsthatinitwrites needs Node 22.18 to load on the Node 22 line. Node 20 reached end of life in April 2026.Requires Node.js >= 22.18.0
ed5ed04:ultracite init --type-awarenow turns on type-aware linting for Oxlint. It used to installoxlint-tsgolintwithout telling Oxlint to use it, so rules that need type information, such astypescript/no-floating-promises, only ran when you passed--type-awaretoultracite checkyourself. Init now also setsoptions: { typeAware: true }inoxlint.config.ts, socheck,fixand the editor extension run them. A config with anoptionsobject of its own is left as written, with a note to addtypeAware: trueto it. Re-runninginiton a project that hasoxlint-tsgolintinstalled turns it on, which can report new problems.edc6ca6: Update the agentsultracite initsets up to match what's still shipping.--agents roo-code,continue,firebase-studioandmcpjamnow write the rules toAGENTS.md, asuniversaldoes, with a warning, and the skill installer no longer targets.rooor.continue. Files earlier versions wrote for them, such as.roo/rules/ultracite.md, are left in place.kiro-cliinstead ofamazon-q-cli, which init still accepts with a note to switch. Kiro readsAGENTS.mdin both its CLI and IDE and ignores.amazonq/rulesonce a project has a.kirofolder, so init writes the rules toAGENTS.md(anduniversalcovers it) instead of.amazonq/rules/ultracite.md.xuminstead ofmux, which init still accepts with a note to switch.kimi-codeinstead ofkimi-cli, and Snowflake Cortex Code is now Snowflake CoCo, with the IDsnowflake-cocoinstead ofsnowflake-cortex. The old IDs still work, with a note to switch. AMP is now Amp; its ID doesn't change.ed5ed04: The pre-commit hooks thatultracite initsets up now fix only the files you staged, instead of runningultracite fixon the whole project.ultracite fixand re-stages them. A file you staged only part of is fixed but no longer re-staged, becausegit addwould also have committed the changes you left unstaged. The hook lists those files so you can review the fixes and stage them yourself.ultracite fix {staged_files}, so Lefthook passes the staged files that match its globs, andstage_fixedre-stages only those.pass_filenames: false, so pre-commit passes the staged files toultracite fix. It also setsrequire_serial: true, which keeps it to a singleultracite fixrun.Since the globs now decide which files get fixed, the Lefthook job and the pre-commit hook match every file type the linters and formatters handle:
.js,.jsx,.mjs,.cjs,.ts,.tsx,.mts,.cts,.json,.jsonc,.css,.scss,.less,.vue,.svelte,.astro,.html,.md,.mdx,.yaml,.yml,.graphqland.gql. Before, they matched only.js,.jsx,.ts,.tsx,.json,.jsoncand.css. The lint-staged glob, which already passed only the staged files that match it, now covers the same types too; it used to leave out.mjs,.cjs,.mts,.cts,.less,.vue,.svelte,.astro,.html,.yaml,.yml,.graphqland.gql, so those files were never fixed on commit. The pre-commit hook uses afilespattern instead oftypes_or, because pre-commit has no file type tags for.jsonc,.mts,.ctsor.gql.Re-running
ultracite initwith the same integrations updates the hooks, globs and file types that earlier versions wrote, in place. Hooks, globs and types you wrote or edited yourself are left alone.ed5ed04:ultracite initandupgradenow installoxlint,oxfmtandoxlint-tsgolintwithin caret ranges of the versions the presets were checked against (^1.86.0,^0.71.0and^7.0.2004), instead of the latest release. Biome is still installed at the exact version.oxfmtis still before 1.0, so its caret range holds the minor version: a newoxfmtminor can no longer change how files are formatted the next time you runupgrade, and a newoxlintmajor can no longer fall outside the supported range. Theoxfmtpeer range is now>=0.71.0 <1, soultracite doctorfails on anoxfmtolder than 0.71.0 and warns on 1.0 or later.Requires oxfmt >= 0.71.0 and < 1.0.0
Requires prettier >= 3.5.3 (the version
prettier-plugin-astroneeds)528a17c:ultracite upgradenow brings your configuration up to date, not just your packages, and replaces the manual upgrade guides.--claudeand--codexhand the configuration changes a project still needs to that agent's CLI, after Ultracite and the toolchain are installed. The agent gets the upgrade guide for each major release the configuration predates: Biome 2's config format (v5), the per-framework presets (v6), theultracite/biome/*preset paths andcheckandfixcommands (v7), and this release's changes (v8): removingprettier/prettierfrom ESLint and Stylelint configs, importing the new Cypress, Storybook and type-aware ESLint presets where the project needs them, turning on Oxlint'stypeAwarewhenoxlint-tsgolintis installed, formatting with Prettier in Zed, and adding--yestoinit --quiet. It runs as it does forfix --claude, limited to editing files, and UltraciConfiguration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.