Skip to content

chore(deps): update dependency ultracite to v8 - #32

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/ultracite-8.x
Open

renovate[bot] wants to merge 1 commit into
mainfrom
renovate/ultracite-8.x

Conversation

@renovate

@renovate renovate Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
ultracite (source) ^7.6.1 → ^8.0.0 age adoption passing confidence

Release Notes

haydenbleasel/ultracite (ultracite)

v8.1.1

Compare 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/biome peer range stays at ^2.6.2. The useSortedProperties assist that core turns on now follows stylelint-config-recess-order 7.9.0, so ultracite fix can reorder CSS properties it used to leave alone, such as scroll-behavior, anchor positioning and multi-column layout. It also no longer offers a sort that would change which of two overlapping declarations wins. noShorthandPropertyOverrides also recognises overrides of logical border, corner shape, position-try, text-box and transition-behavior properties. 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 packages init installs: typescript-eslint 8.72.1, eslint-plugin-vue 10.12, eslint-plugin-storybook 10.6.5, @tanstack/eslint-plugin-query 5.105.1, @react-native/eslint-plugin 0.88.1, globals 17.14 and eslint-plugin-react-doctor 0.9.21, plus the Oxlint JS plugin oxlint-plugin-react-doctor 0.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-block reports content outside the top-level blocks of a .vue file, which the compiler drops; vue/no-define-model-default reports a default in defineModel(); and vue/no-props-shadow reports <script setup> declarations that shadow a prop. The new block-lang required and require-explicit-emits ignoreMixins options 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 as useEffect(() => syncFrom(id, setValue), [id]). It is on in the ESLint React preset and in ultracite/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 private in checks and instantiation expressions, a ; dropped before class members named in or instanceof, and its width heuristics now measure display width, so lines with wide characters (such as CJK text) can wrap differently after upgrading. Its prettier-plugin-astro integration now needs @astrojs/compiler-rs 0.5, which is the version ultracite init installs. 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 as const fruit: Fruit = 1, matching the @typescript-eslint rule of the same name that the ESLint type-aware preset already enables. Like the other type-aware rules, it only runs with oxlint --type-aware and oxlint-tsgolint installed, and oxlint 1.90 needs oxlint-tsgolint 7.0.2005 or later. Older oxlint releases fail to parse a config that names the rule, so the oxlint peer range moves to ^1.90.0.

    The release also makes a few rules report cases they used to miss: array-callback-return checks callbacks passed with extra arguments, no-useless-concat sees through parentheses, and jest/no-conditional-expect checks function expression callbacks. See the 1.90.0 release notes.

    Requires oxlint >= 1.90.0

v8.1.0

Compare Source

Minor Changes
  • daf7b0f: Update Biome to 2.6.3. Biome 2.6 renamed useSortedClasses to useTailwindSortedClasses and moved its functions option to the top-level tailwind.mergeFunctions, so the 8.0 core preset failed to load with "Found an unknown key useSortedClasses". The core preset now uses the new name and lists the same functions under tailwind.mergeFunctions and, for cva and tv, tailwind.variantFunctions, which sorts the classes in their variant objects. The rule also switched to Tailwind CSS v4's class order, so ultracite fix re-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, matching max-nested-callbacks), useDomNodeTextContent, useDomQuerySelector, useImportsFirst, useNamedCaptureGroup, useUnicodeRegex, useVarsOnTop, useThisInClassMethods, useReduceTypeParameter, useIframeSandbox, noDuplicateFieldDefinitionNames for GraphQL, noDuplicateSelectors and useBaseline for CSS, and noEmptyObjectKeys and noTopLevelLiterals for JSON.
    • React: noComponentHookFactories, noJsxNamespace, noJsxLeakedDollar, noReactStringRefs and useReactAsyncServerFunction.
    • Vue: noVueImportCompilerMacros, noVueRefAsOperand, noVueVOnNumberValues, useVueValidVFor, useScopedStyles, useVueConsistentDefinePropsDeclaration and useVueNextTickPromise.
    • Astro: useScopedStyles, which reports <style is:global>.
    • Svelte: noInlineStyles, matching ESLint's svelte/no-inline-styles.
    • Qwik: useQwikLoaderLocation.
    • Jest and Vitest: noConditionalExpect, noIdenticalTestTitle, useExpect, useTestHooksInOrder, useTestHooksOnTop, and useConsistentTestIt set to test() at the top level and it() inside describe, matching consistent-test-it's defaults.

    noInlineStyles stays off outside Svelte, noExcessiveSelectorClasses stays off because it has no default limit, and noUntrustedLicenses stays off because it reads node_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 when graphql.assist.enabled is set, so it never ran. The preset now sets it and turns on Biome 2.6's useGraphqlSortedDefinitions, useGraphqlSortedVariables and useGraphqlSortedArguments, whose fixes ultracite fix applies. Biome marks the selection-set fix unsafe, because GraphQL returns fields in the order they're selected, so selection sets are reported by ultracite check and only sorted by ultracite 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 .md files 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 (the nestjs preset) asks for Node.js 24 and eslint-plugin-astro (the astro preset) for 22.22.3 or 24.16. Both run on older versions, but Yarn 1 enforces what they declare.

  • 9a1ce92: Format .astro files with Oxfmt. When the project or one of its workspaces uses Astro, ultracite init turns on Oxfmt's astro option in the root oxfmt.config.ts and installs @astrojs/compiler-rs, the compiler that Oxfmt's bundled prettier-plugin-astro loads. Until now, Oxfmt skipped .astro files. For Astro 6 and earlier, which keep line breaks between tags as spaces, it writes astro: { compressHTML: "html" } so formatting can't change what a page renders. An astro value already in the config is kept, so astro: false still opts out. ultracite upgrade keeps 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-running ultracite init, or by setting astro: true by hand as described in Formatting Astro files. Oxfmt formats .astro files from 0.73.0; older releases ignore the option.

  • e4be64a: Add playwright, react-native and drizzle framework presets. ultracite init offers them, and pre-selects them when the project depends on @playwright/test, react-native or drizzle-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/playwright turns on every rule in eslint-plugin-playwright in test files, except no-hooks, require-soft-assertions and require-tags, which would report ordinary tests. ultracite/biome/playwright turns on Biome's Playwright rules, such as noPlaywrightMissingAwait and noPlaywrightWaitForTimeout, and the test rules the Jest and Vitest presets use, such as noFocusedTests and useExpect. It leaves out useConsistentTestIt, because Playwright has no it(). On every linter, a hook that only needs testInfo, as in test.beforeEach(async ({}, testInfo) => ...), no longer trips core's empty-pattern rule.
    • React Native: ultracite/eslint/react-native turns on the rules in eslint-plugin-react-native and Meta's @react-native/eslint-plugin, such as no-raw-text, no-unused-styles and no-deep-imports. eslint-plugin-react-native hasn't been updated for ESLint 10, so the preset wraps it with @eslint/compat, which init installs too, and npm projects get a peer override for it. ultracite/biome/react-native turns on noReactNativeRawText, noReactNativeLiteralColors, noReactNativeDeepImports and useReactNativePlatformComponents. Both declare the __DEV__ global.
    • Drizzle: both presets turn on the rules that report a delete() or update() with no .where() (eslint-plugin-drizzle and Biome's noDrizzleDeleteWithoutWhere and noDrizzleUpdateWithoutWhere), for objects named db or tx. Without a name, the ESLint rules report every .delete() call, Map#delete included, 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 noReactNativeRawText in core would report text inside any JSX element, including a <div>.

Patch Changes
  • 72890be: Update eslint-plugin-unicorn to 79. The ESLint preset turns on its two new rules, no-unnecessary-default-arguments and no-repeated-call-wrappers, like every other Unicorn rule. Unicorn 79 stopped no-top-level-side-effects from reporting unknown calls during module evaluation by default; the preset sets its new checkUnknownCalls option, so it keeps reporting them as it did with Unicorn 77. prefer-ternary and prefer-minimal-ternary now 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-parameters now 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 as prefer-spread and prefer-math-min-max.

  • 72890be: Update the ESLint plugins init installs: typescript-eslint 8.72, eslint-plugin-jsdoc 65.4, eslint-plugin-n 18.5, eslint-plugin-jest 29.17, @vitest/eslint-plugin 1.6.28, @next/eslint-plugin-next 16.4, @angular-eslint/eslint-plugin 22.6, eslint-plugin-svelte 3.23.1, eslint-plugin-storybook 10.6.3, eslint-plugin-qwik 1.20.3, @tanstack/eslint-plugin-query 5.104.5, @darraghor/eslint-plugin-nestjs-typed 7.5.8, eslint-plugin-react-doctor 0.9.18 and prettier-plugin-astro 1.1.2, plus the Oxlint JS plugins oxlint-plugin-react-doctor 0.9.18 and @shadcn/lint 0.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's await-thenable allowMixedPromiseArrays and jsdoc's check-alignment ignoreEmptyLines. 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 fix can reformat some .md files that were already clean, including sorting imports in JavaScript and TypeScript code blocks. .mdx files still go through Prettier. The releases also add an astro option that formats .astro files through prettier-plugin-astro (it needs @astrojs/compiler-rs installed in the project) and an associations option 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-tsgolint to 7.0.2005. The releases add no rules, so the Oxlint presets are unchanged and the oxlint peer 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-const checks destructuring assignments inside blocks, sort-keys compares computed identifier keys, no-param-reassign reports writes to rest parameters, and unicorn/prefer-string-replace-all follows regexes stored in variables. react/no-unescaped-entities, react/jsx-no-target-blank and unicorn/no-useless-switch-case now offer suggestions. See the 1.87.0, 1.88.0 and 1.89.0 release notes for the full list.

  • 5eeb6e5: ultracite fix --hook no 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.2

Compare Source

Patch Changes
  • 9f80955: Make ultracite fix --claude and --codex judge 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 tripped prefer-tag-over-role, or a correct <button> missing its type, 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's a11y rules 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 as internalError/io for a file it can't write, are no longer handed to the agent as lint issues.
  • 30e03ef: Give jsx-a11y/label-has-associated-control in ultracite/oxlint/react the 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's noLabelWithoutControl in ultracite/biome/core gets the same label and control components.
  • 947ca03: Turn off promise/prefer-await-to-then in ultracite/oxlint/core and ultracite/eslint/core, and github/no-then in ultracite/oxlint/js-plugins and ultracite/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-return and promise/catch-or-return are now on in both presets, so an unhandled promise chain is still reported. In ESLint, unicorn/prefer-await moves to ultracite/eslint/type-aware, where it uses type information to skip calls that aren't on a promise. The test-file overrides that turned promise/prefer-await-to-then off in the jest and vitest presets are gone, since the rule is off everywhere.
  • c198d06: Stop unicorn/no-useless-undefined in ultracite/oxlint/core from checking function call arguments. A required parameter typed string | undefined has to be passed undefined explicitly, but Oxlint flagged consume(undefined) and ultracite fix rewrote it to consume(), which TypeScript rejects with TS2554. The rule can't see parameter types, so it now runs with checkArguments: false. It still reports let value = undefined, return undefined and the rest of its checks. ultracite/eslint/core sets the same option. eslint-plugin-unicorn already skipped arguments in TypeScript files, and now skips them in JavaScript too. Biome's noUselessUndefined never checked arguments.

v8.0.1

Compare Source

Patch Changes
  • 40d646a: ultracite fix --claude and --codex hand agents better information and report results more accurately:

    • Rule names reach the agent as they're written in the config, such as no-unused-vars and typescript/no-explicit-any, instead of Oxlint's eslint(no-unused-vars).
    • ESLint diagnostics now carry the rule's description and documentation URL, read with the json-with-metadata formatter. Biome diagnostics carry the rule's documentation URL and its description from biome explain, since Biome's JSON reporter includes no help text.
    • The prompt tells the agent that the run is non-interactive, so it explains a decision it can't make in its final message instead of asking a question and waiting for an answer that can't come.
    • Files are handed over in path order, so the same project gets its fix in the same file on every run. Before each file after the first, Ultracite lints it again: an earlier file's fix can clear its issues (breaking an import cycle fixes both files), and the agent was being handed diagnostics that no longer applied. A file with nothing left is skipped.
    • A file the agent deleted, or one that no longer parses, now counts as unfixed. Before, its issues could disappear from the report and show as fixed.
  • 2543859: Update the vendored anti-slop Oxlint plugin to upstream commit 13909c9 and enable its three new rules in the ultracite/oxlint/anti-slop preset. require-readable-spacing restores 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, so ultracite fix restores the spacing without fighting the formatter. no-array-filter-map rejects adjacent eager filter/map passes over arrays, and no-reduce-accumulator-copy rejects reducers that copy their accumulator on every iteration. Expect a one-time whitespace-only diff from ultracite fix after upgrading if you extend the preset (#​803).

  • 0a671cc: On the ESLint toolchain, ultracite fix --hook no 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, and unused-imports/no-unused-imports removed it first. The hook run now turns that rule off, as the Biome hook already skips noUnusedImports (#​483). no-unused-vars still reports the import if it stays unused.

  • de08bd3: The ESLint core preset no longer configures a node resolver for import-x, which needed eslint-import-resolver-node, a package init never installed. The TypeScript resolver it keeps resolves JavaScript files too.

  • c13e042: react/jsx-no-target-blank now checks forms as well as links (forms: true) in the Oxlint and ESLint React presets, as Biome's noBlankTarget already does. The rules file init writes for agents now says to add rel="noopener noreferrer" to target="_blank" links instead of rel="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: The oxlint.config.ts that ultracite init writes now sets env: core.env. Oxlint doesn't carry env through extends, so the browser globals the core preset declares never reached projects, and rules that depend on them stayed quiet: no-implied-eval didn't report setTimeout("…") or setInterval("…"), and no-eval didn't report window.eval(…). Workspace configs written by init now repeat env: root.env alongside ignorePatterns and settings, and an .oxlintrc.json that init migrates keeps its env on top of core's. Re-run ultracite init to update an existing config, or add env: core.env to it yourself.

  • 7984c6e: The Oxlint js-plugins preset now enables the 32 SonarJS rules that the ESLint core preset already runs without type information, including the security rules sonarjs/slow-regex, sonarjs/sql-queries, sonarjs/disabled-auto-escaping and sonarjs/dompurify-unsafe-config. SonarJS marks these rules requiresTypeChecking, 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.0

Compare Source

Major Changes
  • d0875c0: Every agent now reads Ultracite's rules from AGENTS.md. init writes 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:

    • Claude Code reads AGENTS.md only when the project has no CLAUDE.md, so init adds an @AGENTS.md import to the project's CLAUDE.md or .claude/CLAUDE.md when there is one.
    • Gemini CLI reads GEMINI.md by default, so init adds AGENTS.md to context.fileName in .gemini/settings.json, keeping GEMINI.md.
    • Aider gets .aider.conf.yml pointed at AGENTS.md, as before.
    • Replit Agent reads only replit.md, so it keeps a copy of the rules there.

    Firebender now reads AGENTS.md too. The init prompt asks which agents you use and lists AGENTS.md (Universal) plus those four.

    Projects set up by earlier versions move over the next time init runs: it takes Ultracite's block out of .claude/CLAUDE.md, GEMINI.md, .firebender/rules/ultracite.mdc and Aider's ultracite.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.md stops Claude Code from reading AGENTS.md.

    A CLAUDE.md, GEMINI.md or replit.md that is a symbolic link to AGENTS.md, or that AGENTS.md links to, already gives that agent the rules, so init leaves it as it is. init never 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 the ultracite.md that init --agents aider used to write was never loaded. Now init writes the rules to AGENTS.md and merges two keys into .aider.conf.yml: read: AGENTS.md, and lint-cmd set to the project's ultracite 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, a lint-cmd that runs another linter is left alone, and an ultracite.md that holds nothing but the rules is removed. Aider keeps its own option in the init prompt, since the universal AGENTS.md option doesn't write .aider.conf.yml.

    The agent list also uses the current names for Deep Agents, goose and Gemini CLI. Their --agents IDs don't change.

  • f4c8a32: Make every rule in the Biome core preset an error. noSuspiciousSemicolonInJsx came from Biome's recommended set at warning level, so ultracite check passed with it unless the React preset was on. It and the two other rules core inherited from that set, noDuplicateJsxProps and noVoidElementsWithChildren, are now set to error explicitly.

  • ed5ed04: compat/compat is now an error in the ESLint core preset. It was the last warning-level rule in any preset, so ultracite check passed while it reported browser APIs your browserslist targets don't support. Set your targets in a browserslist key in package.json or a .browserslistrc file, 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's defaults there, which include Opera Mini and Chrome 109, so fetch, URL and Array#toSorted() failed in almost every project. Ultracite only sets these targets when it finds no browserslist config from the directory ESLint runs in and no BROWSERSLIST environment 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 set settings.browsers yourself.

  • 16fa476: Lint the scripts in Vue, Svelte and Astro components with the ESLint core rules. Core's globs only matched .js and .ts files, so a .vue file got only the Vue rules, a .svelte file only the Svelte rules, and an .astro file's frontmatter only the Astro rules, while Oxlint already runs its core rules on those scripts. The vue, svelte and astro presets 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.

    • Components now get core's filename rule like any other file, as on Oxlint, so a PascalCase component such as TaskList.vue is reported. SvelteKit route files (+page.svelte) are exempt, and Astro and Nuxt pages ([slug].astro, [id].vue) get the same route-aware pattern as other pages/ files, on ESLint and in Oxlint's JS plugins.
    • In Svelte components and rune modules, prefer-const, unicorn/no-top-level-assignment-in-function and sonarjs/declarations-in-global-scope are off: svelte/prefer-const replaces the first, and the other two misread $props() and $state in a component's scope. SvelteKit's PageProps and LayoutProps, and Astro's Props, are allowed by unicorn/name-replacements.
  • ed5ed04: Cypress and Storybook rules move out of the ESLint core preset into opt-in framework presets, ultracite/eslint/cypress and ultracite/eslint/storybook. Core loaded both plugins for every project, so init installed eslint-plugin-cypress, eslint-plugin-storybook and the whole storybook package for every ESLint setup, whether or not the project used them.

    init now offers cypress and storybook with the other frameworks (--frameworks cypress storybook). It preselects them when cypress or storybook is in package.json, and installs their plugins only when you pick them. To keep linting Cypress specs and stories, add the presets to eslint.config.mjs after core:

    import core from "ultracite/eslint/core";
    import cypress from "ultracite/eslint/cypress";
    import storybook from "ultracite/eslint/storybook";
    
    export default [...core, ...cypress, ...storybook];

    Oxlint and Biome have no Cypress or Storybook rules, so ultracite/oxlint/cypress, ultracite/oxlint/storybook, ultracite/biome/cypress and ultracite/biome/storybook are empty presets that keep the framework selectable with every linter.

  • ed5ed04: ESLint and Stylelint no longer run Prettier as a rule. ultracite check and ultracite fix already run Prettier as their own step, so the prettier/prettier rule from eslint-plugin-prettier and stylelint-prettier formatted and reported every file a second time. The ESLint core preset and the Stylelint preset drop those plugins and keep eslint-config-prettier, so no lint rule fights Prettier, and init no longer installs eslint-plugin-prettier or stylelint-prettier.

    ESLint and Stylelint now report only lint problems. Formatting problems come from the Prettier step of ultracite check, so running eslint or stylelint on their own no longer reports formatting. A config that sets prettier/prettier itself 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. init used to set ESLint's language server as Zed's formatter for JavaScript, TypeScript and TSX, which only applied Prettier through the prettier/prettier rule, 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-running init updates .zed/settings.json, and ultracite upgrade --claude or --codex makes 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-eslint rules, such as no-floating-promises, no-unsafe-return and strict-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 as sonarjs/deprecation, sonarjs/no-ignored-return and unicorn/no-non-function-verb-prefix, move with them. SonarJS rules that use type information only when it's there, such as sonarjs/no-small-switch and its regular expression rules, stay in core.

    The type-checked rules live in a new ultracite/eslint/type-aware preset. Framework plugins with type-checked rules have an add-on after their preset: ultracite/eslint/<framework>/type-aware for angular, jest, nestjs, qwik, tanstack and vitest. init --type-aware adds the preset and the add-ons for the frameworks you pick, and re-running init without the flag keeps them. To keep type-aware linting, add them after core and after each framework:

    import core from "ultracite/eslint/core";
    import typeAware from "ultracite/eslint/type-aware";
    import vitest from "ultracite/eslint/vitest";
    import vitestTypeAware from "ultracite/eslint/vitest/type-aware";
    
    export default [...core, ...typeAware, ...vitest, ...vitestTypeAware];
  • 7965ec2: ultracite fix --hook now 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 as hookSpecificOutput.additionalContext instead. 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 init now asks before it changes files it doesn't own, and asks every question before it writes anything.

    • When you pick a linter other than the one the project uses, an interactive run lists the other linters' config files and packages and asks before removing them. If you keep them, init warns when ultracite check would still find and run the old linter. --yes removes them without asking, as before.
    • An ESLint setup keeps legacy .eslintrc files. ESLint 10 doesn't read them, so they can't conflict with the flat config, and ultracite doctor no longer flags them on an ESLint setup. Moving to Biome or Oxlint still removes them.
    • Init only turns on strictNullChecks in your tsconfig*.json files 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.
    • In a TypeScript project, an interactive run asks whether to turn on type-aware linting when --type-aware isn't passed. A project that already has it keeps it.
  • ed5ed04: ultracite init has a --yes (-y) flag for running without prompts, and --quiet now only controls output.

    • --yes takes the default for every question no flag answers, without asking. Init does this on its own when CI is true or 1, or when there's no terminal to answer prompts in, so it never waits for input in a pipeline.
    • --quiet leaves out the intro banner, spinners and progress messages, and no longer skips the prompts. A script that ran init --quiet to avoid them should pass --yes --quiet.
    • Warnings now print in quiet runs too, such as the one for a check or fix script that init left as it was because it runs another tool.
  • cbb349c: Add three agents, and rename Windsurf to Devin Desktop.

    • init --agents now takes fx (Vercel Labs), antigravity (Antigravity CLI, Google's successor to Gemini CLI for consumer accounts) and grok (Grok Build). All three read AGENTS.md.
    • init --hooks grok writes a post-edit hook to .grok/hooks/ultracite.json in Claude Code's format. Grok Build runs it after each Write or Edit once you trust project hooks with /hooks-trust, and hands the problems ultracite fix --hook leaves back to the model. fix --hook now 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.
    • Windsurf is now Devin Desktop, with the editor and hook ID devin instead of windsurf, 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 its engines field. The CLI's dependencies have needed Node 22 since 7.10.0, so on Node 20 it stopped at startup with TEXT_ENCODINGS.union is not a function, and the oxlint.config.ts that init writes 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-aware now turns on type-aware linting for Oxlint. It used to install oxlint-tsgolint without telling Oxlint to use it, so rules that need type information, such as typescript/no-floating-promises, only ran when you passed --type-aware to ultracite check yourself. Init now also sets options: { typeAware: true } in oxlint.config.ts, so check, fix and the editor extension run them. A config with an options object of its own is left as written, with a note to add typeAware: true to it. Re-running init on a project that has oxlint-tsgolint installed turns it on, which can report new problems.

  • edc6ca6: Update the agents ultracite init sets up to match what's still shipping.

    • Remove Roo Code (shut down in May 2026), Continue (no longer maintained since Cursor acquired it), Firebase Studio (closing in March 2027) and MCPJam (an MCP testing tool rather than a coding agent). --agents roo-code, continue, firebase-studio and mcpjam now write the rules to AGENTS.md, as universal does, with a warning, and the skill installer no longer targets .roo or .continue. Files earlier versions wrote for them, such as .roo/rules/ultracite.md, are left in place.
    • Amazon Q CLI is now Kiro CLI, with the ID kiro-cli instead of amazon-q-cli, which init still accepts with a note to switch. Kiro reads AGENTS.md in both its CLI and IDE and ignores .amazonq/rules once a project has a .kiro folder, so init writes the rules to AGENTS.md (and universal covers it) instead of .amazonq/rules/ultracite.md.
    • Mux is now Xum, with the ID xum instead of mux, which init still accepts with a note to switch.
    • Kimi CLI is now Kimi Code CLI, with the ID kimi-code instead of kimi-cli, and Snowflake Cortex Code is now Snowflake CoCo, with the ID snowflake-coco instead of snowflake-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 that ultracite init sets up now fix only the files you staged, instead of running ultracite fix on the whole project.

    • Husky: the hook passes the staged files to ultracite fix and re-stages them. A file you staged only part of is fixed but no longer re-staged, because git add would also have committed the changes you left unstaged. The hook lists those files so you can review the fixes and stage them yourself.
    • Lefthook: the job runs ultracite fix {staged_files}, so Lefthook passes the staged files that match its globs, and stage_fixed re-stages only those.
    • pre-commit: the hook no longer sets pass_filenames: false, so pre-commit passes the staged files to ultracite fix. It also sets require_serial: true, which keeps it to a single ultracite fix run.

    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, .graphql and .gql. Before, they matched only .js, .jsx, .ts, .tsx, .json, .jsonc and .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, .graphql and .gql, so those files were never fixed on commit. The pre-commit hook uses a files pattern instead of types_or, because pre-commit has no file type tags for .jsonc, .mts, .cts or .gql.

    Re-running ultracite init with 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 init and upgrade now install oxlint, oxfmt and oxlint-tsgolint within caret ranges of the versions the presets were checked against (^1.86.0, ^0.71.0 and ^7.0.2004), instead of the latest release. Biome is still installed at the exact version. oxfmt is still before 1.0, so its caret range holds the minor version: a new oxfmt minor can no longer change how files are formatted the next time you run upgrade, and a new oxlint major can no longer fall outside the supported range. The oxfmt peer range is now >=0.71.0 <1, so ultracite doctor fails on an oxfmt older 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-astro needs)

  • 528a17c: ultracite upgrade now brings your configuration up to date, not just your packages, and replaces the manual upgrade guides.

    • --claude and --codex hand 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), the ultracite/biome/* preset paths and check and fix commands (v7), and this release's changes (v8): removing prettier/prettier from ESLint and Stylelint configs, importing the new Cypress, Storybook and type-aware ESLint presets where the project needs them, turning on Oxlint's typeAware when oxlint-tsgolint is installed, formatting with Prettier in Zed, and adding --yes to init --quiet. It runs as it does for fix --claude, limited to editing files, and Ultraci

[!IMPORTANT]
✂ PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 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.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot force-pushed the renovate/ultracite-8.x branch 2 times, most recently from 5d79e09 to 7826f17 Compare October 20, 2026 20:33
@renovate
renovate Bot force-pushed the renovate/ultracite-8.x branch 4 times, most recently from a520554 to ad84976 Compare October 26, 2026 16:58
@renovate
renovate Bot force-pushed the renovate/ultracite-8.x branch from ad84976 to 9b2ebdb Compare November 1, 2026 21:30
@renovate
renovate Bot force-pushed the renovate/ultracite-8.x branch from 9b2ebdb to c9bab83 Compare November 6, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants