#1137907a0073 Thanks @Netail! - Added the nursery rule useLayeredStyles, which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.
#11667e997900 Thanks @devtechedge! - Added the nursery rule useBetterDomTraversing, which prefers .firstChild, .firstElementChild, .closest(), and merged .querySelector() calls over positional DOM traversal.
#11657e322040 Thanks @ematipico! - Fixed #7495: noUselessConstructor now ignores TypeScript constructors that forward at least one argument to super, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.
#1163100dbd3a Thanks @ematipico! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.
#11628a2f8ff7 Thanks @dyc3! - Added the nursery rule noXorAsExponentiation, which reports the bitwise XOR operator ^ between two decimal integer literals, where the exponentiation operator ** was likely intended.
#11676840a52a Thanks @dyc3! - Fixed #11672 and #11671 by disabling the experimental capitalized-call and effect-dependency checks in useReactCompiler, matching their exclusion from upstream's recommended lint preset. Valid calls such as Intl.NumberFormat() and captures of variables declared inside effects no longer produce these diagnostics.
#1166049485ed Thanks @ematipico! - Fixed #11653: Astro template suppression comments ({/* biome-ignore lint: reason */}) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.
#1163062e1fc5 Thanks @dyc3! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.
#11658ed4bfa4 Thanks @fredrikblau! - Fixed #11644: useHeadingContent no longer reports headings that render their text with a directive: set:html and set:text in Astro files, v-html and v-text in Vue files.
interfaceContext{doSomething():Promise<void>;}declarefunctiontest(callback:(ctx: Context)=>Promise<void>):void;test(async(ctx)=>{ctx.doSomething();// now reported as a floating promise
});
#11698b019982 Thanks @denbezrukov! - Fixed parsing of unquoted CSS URLs beginning with @ or !, such as url(@/assets/icon.svg) and url(!font.woff2). Preserved escaped and non-ASCII whitespace in raw URLs during formatting.
#11622c23e4c7 Thanks @Netail! - Added the nursery rule noUnsafeIframeSandbox, which reports iframe elements whose sandbox attribute combines allow-scripts and allow-same-origin, since that combination lets the embedded document remove its own sandboxing.
#116704969ee1 Thanks @ematipico! - Fixed #7527: suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressing noTsIgnore now places the biome-ignore comment before @ts-ignore.
#11440b88f1ea Thanks @Princesseuh! - Fixed Astro attribute names being split on : and . inside an expression, such as {x && <button x-on:keyup.enter={go} client:load.foo />}.
#11440b88f1ea Thanks @Princesseuh! - Fixed a bare > in the children of an Astro expression being treated as markup, such as {x && <div>a > b</div>}.
#11440b88f1ea Thanks @Princesseuh! - Fixed HTML comments inside an Astro expression failing to parse. They are now read as trivia, wherever they appear among the children.
{x && <div><!-- first -->text<!-- last --></div>}
{cond && <a></a><!-- c --><b></b>}
#11440b88f1ea Thanks @Princesseuh! - Fixed is:raw children inside an Astro expression being read as JSX, such as {x && <div is:raw>{not js} < & text</div>}.
#11440b88f1ea Thanks @Princesseuh! - Fixed an apostrophe or quote in the text of a JSX element inside an Astro expression ending the expression early, such as {items.map((i) => <li>it's {i}</li>)}.
#11440b88f1ea Thanks @Princesseuh! - Fixed the children of a <script> or <style> inside an Astro expression being read as JSX. Their contents are text, so braces and comparisons no longer have to be escaped.
{cond && <style>a { color: red }</style>}
{cond && <script>let x = {a: 1};</script>}
#11440b88f1ea Thanks @Princesseuh! - Added support for template literal attribute values inside an Astro expression, such as {x && <C data-x=`t${x}` />}.
#11440b88f1ea Thanks @Princesseuh! - Fixed unquoted attribute values being rejected inside an Astro expression, such as {x && <a class=foo maxlength=255 href=/about>go</a>}.
#11440b88f1ea Thanks @Princesseuh! - Fixed a template literal nested inside ${} breaking the rest of an Astro file, such as const href = `/blog${page === 0 ? '' : `/${page + 1}`}`;.
#11440b88f1ea Thanks @Princesseuh! - Fixed a quote inside a regex character class breaking the rest of an Astro file, such as const unsafe = /[/"]/;.
#1150854f3a2e Thanks @dyc3! - Added the nursery rule useFlatMathMinMax. Because Math.min() and Math.max() accept any number of arguments, the rule reports unnecessary nested calls to the same method:
Math.max(Math.max(a,b),c);
The fix flattens this expression to Math.max(a, b, c).
#11585c5c8315 Thanks @Netail! - Fixed #11475: noUnresolvedImports no longer reports Bun runtime built-in modules (bun, bun:bundle, bun:ffi, bun:jsc, bun:sqlite, bun:test).
#1136852a57b3 Thanks @Austin1serb! - Fixed #6830: Biome now reports a diagnostic for excessively deep syntax instead of overflowing the native stack while releasing the parsed tree.
#115961fc42ed Thanks @dyc3! - Added the nursery rule noThisOutsideOfClass. The rule reports this outside class members and TypeScript functions with an explicit this parameter.
functionPerson(name){this.name=name;}
#115552516335 Thanks @dyc3! - Fixed #11529, where noFloatingPromises missed unhandled Promise chains when the imported function's module belonged to an import cycle. Cyclic modules now preserve types for exports that do not participate in recursive type dependencies.
#115180fee70c Thanks @HarperZ9! - Fixed #11500: the formatter now prints the declare modifier before accessibility modifiers on class properties. private declare readonly name: string is now formatted as declare private readonly name: string, matching Prettier and TypeScript's canonical modifier order.
#115801277af2 Thanks @ematipico! - Fixed #5091: Biome no longer moves comments next to the < of a generic, which causes invalid TypeScript syntax:
#11492f2a07aa Thanks @santichausis! - Fixed #11454: noMisplacedAssertion now recognises @fast-check/vitest's test.prop(...) (and .concurrent.prop, .skip.prop, etc.) as a test function, the same way it already recognises test.each. The JS formatter picks up the same recognition, so a curried test.prop(...)(...) call is now formatted with the regular breakable argument layout used for test.each/test.for, instead of the single-line-hugging layout used for plain it/test calls.
For example, Biome no longer reports the assertion below as misplaced:
#11559472dbc2 Thanks @levrik! - Fixed a false positive in noVueDuplicateKeys where a <script setup> variable initialized from props was reported as a duplicate of the prop it derives from. Biome now exempts any variable whose initializer references props, instead of only recognizing defineProps() and toRefs(props).
For example, Biome no longer reports foo below as a duplicate key:
#1153397e76c0 Thanks @ematipico! - Fixed #11520, where the Biome scanner would start analysing dependencies multiple times, leading to long and unresponsive sessions.
#1156418a0e1f Thanks @Netail! - Fixed the diagnostic range of noInferrableTypes so it now highlights only the type instead of including the leading : colon, spaces and comments.
#11540124fdaa Thanks @ematipico! - Fixed #11537: noShorthandPropertyOverrides now compares declarations only within the same block. The rule no longer reports @supports feature queries and correctly checks nested, @keyframes, and @page blocks.
#115327ceb0ee Thanks @dyc3! - Fixed #11528: noFloatingPromises no longer reports statement-level await expressions that handle Promise values, including overloaded calls returning Promise aliases. Awaited values that resolve to arrays of Promises remain reported because their element Promises are not handled by await.
#114743c6412e Thanks @dyc3! - Fixed #10241. Biome no longer reports unsupported text expression diagnostics for double-curly text in vanilla HTML, and the formatter preserves adjacent curly-brace text.
#115936c7fd27 Thanks @dyc3! - Added the nursery rule noVueDeprecatedScopedSlots. It reports deprecated $scopedSlots references in Vue templates and component objects, and offers an unsafe replacement with $slots. For example, Biome now reports this.$scopedSlots.default inside a Vue component.
#11440b88f1ea Thanks @Princesseuh! - Fixed the formatter crashing on an Astro or Svelte expression spanning several lines in a file with CRLF line endings, such as <p>{a +\r\n b}</p>.
#11581f4e5ebb Thanks @dyc3! - Added the nursery rule useModernMathApis. The rule reports legacy mathematical patterns that have direct modern Math equivalents.
Math.sqrt(a*a+b*b);
#11597a20f44a Thanks @Netail! - Added the nursery rule noBunModules, which forbids the use of Bun builtin modules (e.g. bun:sqlite, bun:ffi).
#115457d54688 Thanks @dyc3! - Fixed #11542: Biome now reports HTML comments between Svelte tag attributes as parse errors.
#11582b6611dd Thanks @ematipico! - Fixed #3862. Biome now parses legacy Internet Explorer filter and -ms-filter values such as progid:DXImageTransform... and alpha(opacity=40).
#1157565da251 Thanks @dyc3! - Improved the Tailwind parser's ability to recover from parsing failures. Whitespace now always allows the parser to recover and start parsing a new class.
#115760f78499 Thanks @ematipico! - Fixed #3515 and #10395, where Biome could corrupt Unicode characters while writing source received through standard input to standard output. Characters such as ⚠ and ✔ are now preserved.
#11565ee69e0e Thanks @ematipico! - Fixed #11525. Now the configuration schema correctly provides auto-completion for linter domains.
#11583b19390c Thanks @dyc3! - Fixed #11352: useExplicitLengthCheck no longer reports length-like properties used as value-producing || fallbacks or optional chains, and it no longer offers fixes for value-producing && checks or unsafe negations.
#11562753e955 Thanks @ematipico! - Fixed an issue where the Biome Language Server would start with logging level set to debug. This would cause logs to grow exponentially in long sessions.
#112177d3ee9c Thanks @dyc3! - Fixed handling of biome-ignore format suppression comments on TypeScript declared class properties with string literal names.
#11497f5d7896 Thanks @dyc3! - Added the noInvalidFileInputAccept nursery rule. The rule reports invalid literal accept values on file inputs in JSX and HTML, and normalizes common mistakes.
<inputtype="file"accept="image/jpg"/>
#11345ac58958 Thanks @jakeleventhal! - Improved type inference performance by avoiding resolution of unused members in object arguments.
#115542d55931 Thanks @Netail! - Added the new nursery rule useReactNamingConvention, which enforces naming conventions for React values assigned from createContext, useId, and useRef. A value from createContext must be a PascalCase component name ending with Context, a value from useId must be named id or end with Id, and a value from useRef must be named ref or end with Ref.
#1143788f805e Thanks @Princesseuh! - Fixed #9944: adjacent elements inside an Astro expression now parse as an implicit fragment instead of raising an error.
{options.map(() =>
<div />
<div />
)}
#1143788f805e Thanks @Princesseuh! - Fixed Astro templates rejecting unclosed HTML void elements, such as {cond && <br>}.
#11398afc4615 Thanks @dyc3! - Fixed #11389: Files passed through --stdin-file-path now use full HTML support for Astro, Svelte, and Vue when it is enabled.
#11526372cd68 Thanks @dyc3! - Fixed noVueRefAsOperand to track Vue refs through declaration aliases and toRefs() properties, and to recognize useTemplateRef() results. The rule no longer reports false positives such as plain ref transfers, plain toRefs() property access, defineModel() modifiers, or the supported .effect member as operands.
The refactor enabling these fixes also improves the performance of the rule.
#11458a7cd286 Thanks @dyc3! - Fixed #11436: GritQL snippets such as export { $specifiers } from $source now match named re-exports with aliases, inline type modifiers, and multiple specifiers.
#11515382b15d Thanks @dyc3! - Fixed #11390, where noFloatingPromises performed expensive full type inference for calls to non-Promise methods declared on third-party TypeScript classes. The rule now classifies those calls using targeted type information.
#115166f40e82 Thanks @levrik! - Fixed noVueRefAsOperand so it no longer reports a callback parameter (e.g. from .find(), .map()) as an unwrapped ref value just because it's nested inside a ref(), computed(), or similar call.
Previously, item here was incorrectly treated as a ref value because the rule attributed it to the outer computed() call.
#11495496268d Thanks @Netail! - Fixed useGraphqlNamingConvention so it no longer reports GraphQL enum value definitions with comments & descriptions and now displays a more accurate diagnostic range.
#113225c353e6 Thanks @jp-knj! - Added a new nursery rule noAstroSetHtmlDirective, which disallows Astro's set:html directive because untrusted content can introduce cross-site scripting vulnerabilities.
For example, the following snippet triggers the rule:
#114763270ca4 Thanks @dyc3! - Fixed #10330: Vue interpolation delimiters now stay attached to whitespace-sensitive element boundaries and adjacent inline siblings, wrapping their expression when needed to fit the configured line width. Interpolations followed by text now also converge after one formatting pass.
#111913e5367f Thanks @ematipico! - Added the nursery rule noUndeclaredCustomProperties, which reports references to custom properties that are not defined in available CSS, static HTML-like style attributes, or JSX string style attributes.
For example, the following snippet triggers the rule:
a{color:var(--undefined-color);}
#114357754894 Thanks @levrik! - Fixed: Variables and imports used as custom Vue directives are no longer reported as unused.
#1146766b282c Thanks @dyc3! - Fixed #11464: Biome now parses parenthesized object literals returned from arrow functions when they contain a conditional expression and a nested arrow function.
#11502652aedb Thanks @levrik! - noGlobalAssign no longer reports assignments to a Vue <script setup> binding from a template expression, when the binding's name happens to match a built-in global (e.g. open, parent, top).
For example, this no longer triggers a diagnostic:
#114038f7786f Thanks @Princesseuh! - Fixed a bare < in Astro text being treated as the start of a tag, such as <p>5 < 6 and 7 > 6</p>. As in HTML, a < that cannot open a tag is text and needs no escaping.
#114383133ffa Thanks @Princesseuh! - Fixed #8294: an Astro expression holding only a comment is no longer reported as a parse error, which also stopped the whole file from being formatted.
<div>{/* a note */}</div>
<div class={/* a note */}>x</div>
#114038f7786f Thanks @Princesseuh! - Fixed #9165: an empty Astro expression such as <div>{}</div> no longer fails to parse. Astro renders {} as nothing.
#114038f7786f Thanks @Princesseuh! - Fixed an Astro frontmatter block being cut short by a closing tag inside a string or comment.
---
const a = "</script>";
// </script> in a comment
---
#114038f7786f Thanks @Princesseuh! - Fixed --- being read as an Astro frontmatter fence when markup precedes it. Astro only recognizes frontmatter at the very start of a file, so a file opening with a comment now has no frontmatter, and its --- lines are content.
<!-- c -->
---
this is text, not frontmatter
---
#114038f7786f Thanks @Princesseuh! - Fixed an Astro frontmatter block ending early on a line that merely starts with a dash.
---
--count;
---
#114038f7786f Thanks @Princesseuh! - Fixed the children of an Astro element carrying is:raw being parsed as markup instead of raw text. This now also covers <script> and <style>, whose contents Astro emits verbatim rather than processing, so they are no longer linted as JavaScript or CSS.
#114038f7786f Thanks @Princesseuh! - Fixed Astro rejecting attribute names that start with a colon, such as :href.
#114038f7786f Thanks @Princesseuh! - Fixed the Astro parser failing to recover from a malformed closing tag such as <div></{<//, so that a later mistake is reported where it happens rather than cascading.
#114038f7786f Thanks @Princesseuh! - Fixed { inside an Astro <math> element opening an expression. MathML is foreign content where Astro parses no expressions, so LaTeX such as R^{2x} now survives as text. <svg> is unaffected.
#114038f7786f Thanks @Princesseuh! - Fixed {{ at the start of an Astro expression being read as an interpolation. Astro has no {{ }} syntax, so {{ a: 1 }} and <Comp a={{ b: 1 }} /> are object literals.
#114038f7786f Thanks @Princesseuh! - Fixed expressions inside an Astro <pre> or <textarea> being read as raw text. Astro parses both as ordinary elements, so their markup and interpolations are now parsed, and a variable used only inside one is no longer reported as unused.
#114038f7786f Thanks @Princesseuh! - Added support for template literal attribute values in Astro, such as <div class=`a ${b} c`>.
#114038f7786f Thanks @Princesseuh! - Fixed Astro rejecting HTML5 unquoted attribute values that contain `, =, ' or ", such as <a href=a=b> and <a href=a'b>.
#11431c065f99 Thanks @levrik! - Fixed #11429: Variables and imports used by Vue same-name bindings such as :disabled or v-bind:disabled are no longer reported as unused.
#11409405dedb Thanks @ematipico! - Fixed a memory leak in the LSP server where memory usage kept growing over long editor sessions.
#11422a51eff7 Thanks @dyc3! - Fixed #11416: Biome no longer crashes when parsing incomplete {let} or {const} declarations in Svelte files.
#1137834b715c Thanks @Netail! - Added extra rule sources from @eslint/css. biome migrate eslint detects rules in your eslint configurations more reliably.
#114038f7786f Thanks @Princesseuh! - Fixed {#, {/, {: and {@ being read as Svelte block openings in every HTML-like file. They are now Svelte-only, so in HTML, Vue and Angular files a sequence such as {#if x} is ordinary text instead of a parse error.
#114438d45229 Thanks @ematipico! - Fixed #11390: noFloatingPromises no longer performs unnecessary type inference on call arguments when checking methods of non-generic class instances created with new.
#114259c2667b Thanks @dyc3! - Fixed #6426: GritQL plugins now match and rewrite metavariables embedded in quoted strings.
#1132141386f3 Thanks @dyc3! - Fixed #11315: The CSS parser now recovers at declaration boundaries after bogus declarations, allowing subsequent valid declarations to be parsed.
#1124857b197e Thanks @yanthomasdev! - Expanded the environment variable metadata used by biome rage to include BIOME_BINARY, BIOME_LOG_FILE, and RUST_BACKTRACE as well as reworded explanations for better readability.
#113276771cf5 Thanks @dyc3! - The HTML formatter now preserves meaningful blank lines in HTML, including spacing after elements with trailing spaces and blank lines between comment groups.
<div>
<!-- first group -->
+
<!-- second group -->
</div>
#10312ba8aa18 Thanks @dyc3! - Added the nursery rule useTailwindShorthandClasses, which suggests shorter Tailwind utility classes. For example, the rule suggests replacing w-4 h-4 with size-4.
#11333715e0cd Thanks @kkkhs! - Fixed #11328: lint/nursery/useExpect now recognizes Vitest Browser Mode expect.element() calls as assertions.
#113439b98211 Thanks @johncarmack1984! - Fixed #11311: the CSS parser now accepts Tailwind container-query variant names in @variant, such as @xl and @max-xl. These previously produced a parse error and a noUnknownAtRules diagnostic.
#1130036430eb Thanks @dyc3! - Fixed the HTML formatter's whitespace handling for marquee, noscript, video, audio, and object elements.
- <marquee behavior="alternate"> This text will bounce </marquee>
+ <marquee behavior="alternate">This text will bounce</marquee>
#112996559e6c Thanks @jp-knj! - Added the nursery rule useAstroClientOnlyDirectiveValue, which reports Astro client:only directives without an initializer.
For example, <Component client:only /> triggers the rule.
functionfactory(){constuseColors=true;// no longer reported
constuseStore=createStore({count:0});// no longer reported
constuseData=()=>useState(null);// still reported
returnuseColors;}
#1132141386f3 Thanks @dyc3! - Fixed #11315: Invalid CSS declarations in HTML style attributes now produce parser diagnostics instead of causing a panic.
#1132567c3bf0 Thanks @dyc3! - Fixed HTML text wrapping to account for the width of an adjacent closing tag, avoiding lines that exceed the configured width when the final word and tag must move together.
<a-long-long-long-element
- >foo bar foo bar foo bar foo bar foo bar foo bar foo bar</a-long-long-long-element
+ >foo bar foo bar foo bar foo bar foo bar foo
+ bar</a-long-long-long-element
>
#11367fe5b5d4 Thanks @ematipico! - Fixed TypeScript compilerOptions.paths resolution when mapping targets omit ./. Biome now resolves these targets relative to their configured path base.
#11312e65f07e Thanks @xosnos! - Added a new nursery rule useControlLabel for both HTML and JSX, which reports interactive control elements (button, menuitem) without an accessible label.
<button/>
#1136413853b1 Thanks @ematipico! - Fixed SVG parsing for files with an XML declaration followed by a PUBLIC doctype, such as <?xml version="1.0"?><!DOCTYPE svg PUBLIC "a" "b">.
#11301610ee28 Thanks @dyc3! - Fixed parent tag wrapping when an HTML element starts or ends with a block-like or hidden child such as source, track, or param.
#111436be7be1 Thanks @vznh! - Fixed #11017: noUselessUndefined no longer reports return undefined when the enclosing function has a return type annotation other than undefined or void.
#11234caefe39 Thanks @subotac! - Fixed #11228: CSS block comments between a declaration colon and value now preserve their source indentation.
#11285bca1f73 Thanks @denbezrukov! - Fixed #11280: CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name.
#11173481d008 Thanks @Austin1serb! - Fixed #10242: JavaScript GritQL patterns with multiple metavariables now match snippets consistently in WebAssembly.
#1118723c0369 Thanks @ematipico! - Added the nursery rule noInvalidPropertyInitValue, which reports an @property whose initial-value does not match its syntax descriptor. For example, the following declaration triggers the rule because red is not a <length>:
#112274d603b0 Thanks @saberoueslati! - Fixed #11178: noUndeclaredVariables no longer reports Vue's built-in instance properties, such as $slots and $attrs, in template expressions or $event in inline event-handler expressions. The instance properties are still reported inside <script setup>, where they are not defined.
#1118723c0369 Thanks @ematipico! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the syntax descriptor of @property rules.
#10822c171b3b Thanks @pkallos! - Added the option ignoreIfStatements to useNullishCoalescing. Biome now flags if statements that only assign to a nullish variable (such as if (!a) { a = b }) and can rewrite them to ??=. When enabled, Biome ignores those if statements.
#10094e007143 Thanks @THEjacob1000! - Added the nursery rule noTailwindArbitraryValue. Biome now reports Tailwind CSS arbitrary values such as w-[400px], including in HTML/JSX class attributes, configured utility functions, and tagged templates.
#8239a519f9d Thanks @cormacrelf! - Fixed #8233, where Biome CLI in
stdin mode didn't work correctly when handling files in projects with nested
configurations. For example, with the following structure, --stdin-file-path=subdirectory/... would not use the nested configuration in subdirectory/biome.json:
biome format --write --stdin-file-path=subdirectory/lib.js < subdirectory/lib.js
Now, the nested configuration is correctly picked up and applied.
In addition, Biome now shows a warning if --stdin-file-path is provided but
that path is ignored and therefore not formatted or fixed.
#111388c2c6bd Thanks @ematipico! - Fixed noUnnecessaryConditions: Biome now chooses the same function overload as TypeScript when an argument is a callback, so conditions that were previously missed are reported.
The following code is now invalid, because a parameter typed () => void accepts an async callback and schedule therefore returns string:
#11079607afd2 Thanks @dyc3! - The HTML formatter now lays out the srcset attribute of <img> and <source> as the list of candidates it is. Runs of whitespace between candidates collapse, and once the list no longer fits on one line each candidate goes on its own line with the descriptors aligned:
#11124d890b39 Thanks @denbezrukov! - Fixed CSS formatting of line comments between a declaration colon and value to preserve their source indentation.
.test {
background:
- /////// foo
- // bar
+ /////// foo
+ // bar
radial-gradient(circle, #​000, transparent);
}
#111133d8ab73 Thanks @denbezrukov! - Fixed CSS formatting of long block comments between comma-separated property values:
.foo {
box-shadow:
- 1000px /* long long long long long long long long long long long long comment */ 1000px /* long long long long long long long long long comment */ 2px color(srgb 0.555555555 0.555555555 0.555555555),
+ 1000px
+ /* long long long long long long long long long long long long comment */
+ 1000px /* long long long long long long long long long comment */ 2px
+ color(srgb 0.555555555 0.555555555 0.555555555),
1px 1px black;
}
#11127da5c1a5 Thanks @dyc3! - The HTML formatter now picks the quote character for an attribute by counting the quotes in the value rather than looking only for a double quote. ' and " count as the characters they stand for, and only the character that ends up as the delimiter stays escaped:
Entities that are not quotes, such as & or &[#​39](https://github.com/biomejs/biome/issues/39);, are left exactly as written.
#1119377035bb Thanks @dyc3! - Fixed the HTML formatter collapsing the blank line between an element and the text that follows it. A blank line before text is now kept, the way one before another element already was:
<div>foo</div>
-
text
#11106ad80f57 Thanks @dyc3! - The HTML formatter now writes the HTML5 doctype in lowercase, matching Prettier:
- <!DOCTYPE html>
+ <!doctype html>
This only applies to a plain .html file whose doctype stands alone. A doctype that names a DTD keeps the case it was written with, since the rest of the declaration is not lowercased either:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
A .vue, .svelte, or .astro file keeps whatever the author wrote.
#1118860679db Thanks @dyc3! - Fixed the HTML formatter printing a comment twice when it ended the line of the last element in a document:
- text<!-- a --><!-- a -->
+ text<!-- a -->
#110774dcd0d9 Thanks @dyc3! - Fixed a bug where the HTML formatter collapsed the whitespace inside <textarea>, <xmp> and <plaintext>, changing what the page renders.
- <textarea>
- line one
- line two </textarea>
+ <textarea>line one line two</textarea>
Biome now prints the content of these elements exactly as it appears in the source, matching the existing behavior for <pre>.
#11194abfbb11 Thanks @dyc3! - Fixed the HTML formatter refusing to format a Svelte file containing an array pattern that skips a position:
{#eachanimalsas[,value]}<p>{value}</p>{/each}
#10094e007143 Thanks @THEjacob1000! - Fixed useSortedClasses to correctly detect unsorted classes in static member expression tagged templates (e.g. tw.div\...``). Previously, these were silently skipped due to surrounding whitespace trivia not being stripped from the tag name.
#1107810da30e Thanks @dyc3! - Fixed Vue single-file components failing to parse when they contain a custom block such as <i18n> or <docs>, or a <template> written in another language. Their content is no longer read as HTML, so a block may hold whatever its own tooling expects:
Previously both blocks produced a parse error and the whole file was left unformatted. Biome now prints their content unchanged while still formatting the opening tag.
#111556ee17ea Thanks @dyc3! - Improved performance when printing diagnostics to the console.
#11160217f8ad Thanks @dyc3! - Improved the performance of noFloatingPromises by skipping type inference for assignment statements, which are always considered handled.
#1015250a9bd8 Thanks @Zelys-DFKH! - Fixed #10131: Biome now correctly parses curried arrow functions in ternary consequents when the inner arrow's parameters use a destructuring pattern, e.g. cond ? (x) => ({ a, b }) => body : alt.
#105335809875 Thanks @Mokto! - Fixed #10515: biome check --write was not idempotent on Svelte files — multi-line template literals in <script> blocks and block comments in <style> blocks gained an extra indent level on every run.
#110400abb620 Thanks @Mokto! - Fixed an issue where the HTML formatter would duplicate a comment placed directly before a Svelte {@const ...} or {@debug ...} block. The duplication compounded on every subsequent --write, causing the file to grow exponentially.
#108586d18204 Thanks @ruidosujeira! - Fixed #10839: Svelte {#each} array destructuring no longer includes spaces inside square brackets, and multiline bind function expressions now indent their getter, setter, and function body correctly.
#110092c36626 Thanks @ematipico! - Improved the accuracy of type-aware lint rules by resolving more inferred types. For example, noFloatingPromises now detects floating Promises returned by aliased callbacks and arrays of Promises created by async mapping callbacks.
#109739cb044c Thanks @ematipico! - Fixed false positives in noMisleadingReturnType when generic-constraint, normalization, substitution, or structural return-type comparison cannot complete. The rule now suppresses diagnostics rather than suggesting a return type derived from partial information. For example, this unresolved return type is no longer reported:
#1107115047a2 Thanks @dyc3! - The HTML parser now accepts mixed-case doctype declarations.
#11030cc90e65 Thanks @marschattha! - The rdjson reporter now populates the severity field of each diagnostic (ERROR, WARNING, or INFO), so tools consuming Reviewdog Diagnostic Format output no longer need to assume a default severity.
#110092c36626 Thanks @ematipico! - Fixed a performance regression in type-aware JavaScript lint rules by inferring only requested types and memoizing export resolution.
#11056903b177 Thanks @dyc3! - Added support for Svelte declaration tags using let and const. Biome can now parse, format, and lint bindings declared in these tags.
#1104589c27c6 Thanks @ematipico! - Improved the performance of Biome formatter up to ~7% across the board.
#9806781d68d Thanks @dyc3! - Added the nursery rule noJsRestrictedProperties, which ports ESLint's no-restricted-properties rule. Biome now flags restricted member access and object destructuring, and biome migrate eslint preserves the rule's options.
#10972ab8c21b Thanks @ematipico! - Fixed useExhaustiveSwitchCases for unions of bigint literals. The rule now reports missing bigint cases and compares bigint literals by value, including binary, octal, hexadecimal, and separator-containing spellings. For example, this switch now reports the missing 2n case:
#10972ab8c21b Thanks @ematipico! - Fixed false positives in noBaseToString and useNullishCoalescing when member, stringification, or nullish inference cannot complete. These rules now suppress diagnostics instead of reporting from partial type information. For example, neither expression is reported when a recursive type cannot be fully resolved:
#10957cf263c4 Thanks @dyc3! - Fixed noThenProperty failing to detect Object.fromEntries, Object.defineProperty, and Reflect.defineProperty calls with comments between their tokens.
#10983edc0ed7 Thanks @ayaangazali! - Fixed #10980: useAriaPropsSupportedByRole no longer reports false positives when the attribute that determines an element's implicit ARIA role is written as a shorthand attribute, such as <a {href} aria-label="..."> in Astro and Svelte files.
Shorthand attributes are now taken into account when computing the implicit role, so the anchor above correctly resolves to the link role instead of generic.
#1088989526e3 Thanks @denbezrukov! - Fixed CSS formatter casing for syntax-owned names while preserving author-defined names, including scoped keyframes and container scroll-state queries.
#10964794ccd0 Thanks @denbezrukov! - Fixed CSS formatting for comments between declaration values and !important.
-a { color: /* before */ /* after */ red !important; }
+a { color: /* before */ red /* after */ !important; }
#10993b7a9694 Thanks @denbezrukov! - Fixed the CSS formatter to preserve comments on the correct side of selector combinators and before declaration blocks.
This syntax is valid Vue and equivalent to v-bind="props", so the parser now accepts it (along with the longhand v-bind:="props") instead of crashing while building a diagnostic for a missing argument.
#109367df46f5 Thanks @ematipico! - Improved generic tuple inference for useIncludes. The rule now recognizes specialised tuple element types returned through generic aliases.
#1096972d309b Thanks @ematipico! - Fixed an issue where Biome logs became too verbose, dumping information not relevant to user's operations.
e62f6b6 Thanks @ematipico! - Fixed #10963: Biome no longer panics when a type-aware rule such as noFloatingPromises checks a call to a function with multiple call signatures imported from another module.
#10931899c60d Thanks @ematipico! - Fixed check --write command. Now the command reports code frame of the formatted code, if the formatter is enabled.
#10904ceee4f4 Thanks @qzwxsaedc! - Fixed #10892: noUnnecessaryConditions no longer reports a false positive when checking a member of a discriminated union that is accessed through a default type-only namespace import. The following code is no longer flagged:
#10962f0a67f2 Thanks @ematipico! - Biome no longer removes embedded styles and scripts in HTML files.
#110005039a1e Thanks @ematipico! - Fixed a bug where closing one editor stopped a shared Biome daemon used by other editors. LSP proxy processes now exit when either the editor or daemon disconnects.
#109924bf9b21 Thanks @ematipico! - Fixed noMisusedPromises: The rule now reports Promise-returning callbacks where a synchronous callback is expected when calls use tuple spreads or tuple rest parameters, including generic and deeply nested tuples, and when constructor signatures come from interface or object types. Recursive or excessively nested tuple spreads use a conservative fallback so analysis terminates.
For example, the following callback is now reported.
#10915b3b12b3 Thanks @Functionhx! - Added the rule noNegationInEqualityCheck. The rule flags negated expressions on the left side of strict equality checks like !foo === bar — due to operator precedence this evaluates as (!foo) === bar which is almost always a mistake for foo !== bar.
The rule provides an unsafe fix that flips the operator.
#10970bd1038b Thanks @ematipico! - Improved overload selection for noMisusedPromises. Biome now handles overloaded calls, overloaded constructors, rest parameters, union arguments, and generic constraints without selecting an incompatible signature. For example, noMisusedPromises now reports the async callback passed to the synchronous overload:
#10931899c60d Thanks @ematipico! - Fixed an orchestration issue that could lead to deadlocks when type-aware rules are enabled.
#1096972d309b Thanks @ematipico! - Hardened the Biome Language Server by improving its synchronisation logic.
#10972ab8c21b Thanks @ematipico! - Fixed false positives in noMisusedPromises and useAwaitThenable when Promise or thenable inference cannot complete. These rules now suppress diagnostics instead of treating incomplete type information as a definite result. For example, useAwaitThenable no longer reports await value when the value's thenability is unknown:
The rule's fix now wraps the comment in a real JSX expression container ({/* comment */}) instead of re-inserting the braces as plain JSX text, so the fixed code is no longer reported again by the same rule.
#10891ecca79e Thanks @ematipico! - Fixed #10885: prevented a module-inference regression introduced by a housekeeping change.
#1088660c8043 Thanks @dyc3! - Fixed #10727: Biome now breaks the arguments of curried test.each, it.each, describe.each, and test.for calls when they exceed the configured line width.
- test.each([[1, 2]])("a description that is long enough to push the hugged opening line beyond the print width", (a, b) => {
- expect(a).toBe(b);
- });
+ test.each([[1, 2]])(
+ "a description that is long enough to push the hugged opening line beyond the print width",
+ (a, b) => {
+ expect(a).toBe(b);
+ },
+ );
#1089501a85f0 Thanks @ematipico! - Biome will now remove stale Unix daemon sockets from older Biome versions when starting a newer daemon.
#1081586613d5 Thanks @WaterWhisperer! - Fixed a parser panic reported in #10708: Biome now recovers when unsupported CSS Modules @value rules or scoped @keyframes names end at EOF.
#10534da9b403 Thanks @Mokto! - Fixed noUnusedVariables false positives in Svelte files: Svelte store subscriptions ($store references in templates now keep the underlying store binding from being flagged), and $bindable() props that are only written to in the script block (write-only is intentional for bindable props) are no longer reported as unused.
#10827098ba41 Thanks @Aqu1bp! - Fixed #10698: The noUnsafeOptionalChaining rule now reports unsafe optional chains wrapped in TypeScript as, satisfies, type assertion, and instantiation expressions, such as new (value?.constructor as Constructor)().
#107733c6513d Thanks @otkrickey! - Fixed #10772: useVueValidVOn no longer reports a missing handler for v-on directives using a verb modifier (.stop / .prevent) without an expression, e.g. <div @click.stop></div>. The rule also accepts the arg-less object syntax <div v-on="$listeners"></div> instead of reporting a missing event name.
#10721d83c66b Thanks @minseong0324! - Improved type-aware lint rule inference for built-in globals and indexed function calls. Biome now resolves Error(...), new Error(...), optional Error#stack, and calls through indexed function values such as handlers[0]() more accurately.
#108656450276 Thanks @ematipico! - Fixed #10845. Biome Language Server no longer goes in deadlock when the scanner is enabled.
#1085393d8e53 Thanks @Netail! - Fixed #10840: Astro shorthand attribute syntax is now correctly being parsed from embedded nodes.
#10820bba3092 Thanks @JamBalaya56562! - Fixed #10619: noProcessEnv now also reports computed (bracket) member access. Previously only dot access was checked, so process["env"] and env["NODE_ENV"] (where env is imported from node:process) were missed. Both static and computed accesses are now reported.
#10875b12e486 Thanks @dyc3! - Fixed #10795: --profile-rules now reports timings for each plugin separately as plugin/<pluginName>, matching the naming used by plugin suppressions, instead of aggregating all plugins under a single plugin/plugin entry.
#10877d6bc447 Thanks @ematipico! - Fixed biome-zed#164: Biome no longer inserts stray whitespace when format-on-type runs after closing delimiters such as ), ], and }.
#10867a21463e Thanks @dyc3! - Fixed #10864: Biome no longer crashes when checking or linting HTML files with unquoted attribute values such as <textarea rows=4></textarea>.
#10595f458028 Thanks @pkallos! - Added the option ignoreBooleanCoercion to useNullishCoalescing. When enabled, Biome ignores || and ||= used inside a Boolean() call, where coalescing on falsy values is intentional.
#107984a32b63 Thanks @pkallos! - Added the option ignorePrimitives to useNullishCoalescing. When enabled, Biome ignores ||, ||=, and ternary expressions whose non-nullish operands are all primitives the option opts out of. Use true to ignore all primitives, or an object selecting string, number, boolean, or bigint.
#10796f1b3ab2 Thanks @ematipico! - Fixed #10768. Improved the performance of the Biome Language Server by cancelling certain in-flight operations when there are fast updates.
#10719aa649b5 Thanks @minseong0324! - Fixed noMisleadingReturnType false positive on returns that use a widening type assertion: "a" as string is no longer reported as misleading. The rule now also reports a literal-pinning assertion such as false as false, matching the existing as const behavior.
// No longer flagged (returns are `string`):
functiongetValue(b: boolean):string{if(b)return"a"asstring;return"b"asstring;}// Now also reported, like `as const` (returns `false`):
functionisReady():boolean{returnfalseasfalse;}
#106788f073a7 Thanks @PranavAchar01! - Fixed #7718: Biome now correctly parses CSS nesting selectors when & appears as a trailing sub-selector after a type selector, e.g. h1& { color: red; }.
#107565ec965a Thanks @denbezrukov! - Fixed CSS formatter output for selector lists with allowWrongLineComments and // comments after a selector comma. Biome now keeps the selector before the line comment inline instead of breaking it across descendant combinators.
#107576232fcd Thanks @PranavAchar01! - Fixed #8269: the CSS parser now accepts Tailwind @variant and @utility names that start with a digit, such as the 2xl breakpoint.
@utilitycontainer{@variant2xl{max-width:1400px;}}
#10777575ced6 Thanks @WaterWhisperer! - Fixed an issue reported in #10708: the GitLab reporter now handles --verbose diagnostics filtering correctly.
#102810efe244 Thanks @Zelys-DFKH! - Fixed a bug where GritQL patterns rejected positional (unkeyed) arguments.
#10758e36fd8a Thanks @henrybrewer00-dotcom! - Fixed #10697: The formatter no longer removes the parentheses around an await or yield expression used as the target of a TypeScript instantiation expression. For example, (await makeFactory)<Value> is no longer reformatted to await makeFactory<Value>, which would change the meaning of the code.
#105863617094 Thanks @IxxyDev! - Fixed #9568: noFloatingPromises no longer reports a false positive when calling an overloaded function and the selected overload does not return a promise.
functionbestEffort(cb:()=>Promise<number>):Promise<number>;functionbestEffort(cb:()=>number):number;functionbestEffort(cb:()=>number|Promise<number>,):Promise<number>|number{returncb()asPromise<number>|number;}// This resolves to the second overload, which returns `number`, so it is no
// longer flagged as a floating promise.
bestEffort(()=>42);
#10680771daa4 Thanks @WaterWhisperer! - Fixed #10635: Biome now recognizes chained
table tests such as test.concurrent.each() and it.concurrent.each() as test calls, fixing noMisplacedAssertion false positives and improving formatting for those test declarations.
#1075934570b5 Thanks @henrybrewer00-dotcom! - Fixed #10636: noStaticElementInteractions no longer reports a false positive for event handlers on Svelte special elements such as <svelte:window>, <svelte:document>, and <svelte:body>. These are not real DOM elements, so they are now ignored by the rule.
#10741bd2364e Thanks @JamBalaya56562! - Fixed #6686: the rage command now respects the --config-path option and the BIOME_CONFIG_PATH environment variable when loading the Biome configuration. Previously it always used the default configuration resolution and reported the configuration as Not set when no biome.json existed in the working directory.
#10606a4cc4ab Thanks @Mokto! - Fixed false positives in noUnusedImports, noUnusedVariables, and useImportType for Svelte components that use both a <script module> and a <script> block. The two blocks compile to a single module and share a top-level scope, so a binding (import, function, or variable) declared in one block and used only in the other is no longer reported as unused.
#1076736d5aa7 Thanks @otkrickey! - Fixed #10754: useVueValidVBind no longer reports the Vue 3.4+ same-name shorthand as missing a value. :foo and v-bind:foo are now accepted as equivalent to :foo="foo", while v-bind, v-bind:[dynamicArg], and :[dynamicArg] without a value continue to be reported.
#10807d97fffe Thanks @ematipico! - Fixed an issue where .scss files were incorrectly analyzed when running biome check.
#1067253c6efc Thanks @ematipico! - Fixed a bug where Biome incorrectly formatted snippets that have parsing errors.
#10719aa649b5 Thanks @minseong0324! - Fixed useAwaitThenable false positive when awaiting a custom thenable that is not the global Promise. A value with a callable then member is now recognized as awaitable.
#10770dd1429c Thanks @ematipico! - Improved the Biome Language Server DX by orchestrating certain operations, so that they won't block the editor during typing. This improvement is more visible in large documents.
#10473d9b5133 Thanks @Mokto! - Improved noUnusedImports, noUnusedVariables, noUnusedFunctionParameters, and useImportType for Svelte, Vue, and Astro files (with html.experimentalFullSupportEnabled). Bindings used only in the template — including component tags, attribute interpolations, directives, bind: shorthand, and snippet parameters — are no longer reported as unused, while genuinely unused ones still are.
#10796f1b3ab2 Thanks @ematipico! - Fixed an issue where the Biome Language Server didn't enable project or type-aware lint rules, even when they were explicitly enabled.
#10774bde945b Thanks @pattrickrice! - Fixed #10268 where a race condition resulted in internal errors such as: The file biome.json does not exist in the workspace.
#1137907a0073 Thanks @Netail! - Added the nursery rule useLayeredStyles, which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.
#11667e997900 Thanks @devtechedge! - Added the nursery rule useBetterDomTraversing, which prefers .firstChild, .firstElementChild, .closest(), and merged .querySelector() calls over positional DOM traversal.
#11657e322040 Thanks @ematipico! - Fixed #7495: noUselessConstructor now ignores TypeScript constructors that forward at least one argument to super, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.
#1163100dbd3a Thanks @ematipico! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.
#11628a2f8ff7 Thanks @dyc3! - Added the nursery rule noXorAsExponentiation, which reports the bitwise XOR operator ^ between two decimal integer literals, where the exponentiation operator ** was likely intended.
#11676840a52a Thanks @dyc3! - Fixed #11672 and #11671 by disabling the experimental capitalized-call and effect-dependency checks in useReactCompiler, matching their exclusion from upstream's recommended lint preset. Valid calls such as Intl.NumberFormat() and captures of variables declared inside effects no longer produce these diagnostics.
#1166049485ed Thanks @ematipico! - Fixed #11653: Astro template suppression comments ({/* biome-ignore lint: reason */}) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.
#1163062e1fc5 Thanks @dyc3! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.
#11658ed4bfa4 Thanks @fredrikblau! - Fixed #11644: useHeadingContent no longer reports headings that render their text with a directive: set:html and set:text in Astro files, v-html and v-text in Vue files.
interfaceContext{doSomething():Promise<void>;}declarefunctiontest(callback:(ctx: Context)=>Promise<void>):void;test(async(ctx)=>{ctx.doSomething();// now reported as a floating promise
});
#11698b019982 Thanks @denbezrukov! - Fixed parsing of unquoted CSS URLs beginning with @ or !, such as url(@/assets/icon.svg) and url(!font.woff2). Preserved escaped and non-ASCII whitespace in raw URLs during formatting.
#11622c23e4c7 Thanks @Netail! - Added the nursery rule noUnsafeIframeSandbox, which reports iframe elements whose sandbox attribute combines allow-scripts and allow-same-origin, since that combination lets the embedded document remove its own sandboxing.
#116704969ee1 Thanks @ematipico! - Fixed #7527: suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressing noTsIgnore now places the biome-ignore comment before @ts-ignore.
#9539f0615fd Thanks @ematipico! - Added a new reporter called concise. When --reporter=concise is passed the commands format, lint, check and ci, the diagnostics are printed in a compact manner:
! index.ts:2:10: lint/correctness/noUnusedImports: Several of these imports are unused.
! main.ts:9:7: lint/correctness/noUnusedVariables: This variable f is unused.
× index.ts:8:5: lint/suspicious/noImplicitAnyLet: This variable implicitly has the any type.
× main.ts:2:10: lint/suspicious/noRedeclare: Shouldn't redeclare 'z'. Consider to delete it or rename it.
#94952056b23 Thanks @aviraldua93! - Added the useKeyWithClickEvents a11y lint rule for HTML files (.html, .vue, .svelte, .astro). This is a port of the existing JSX rule. The rule enforces that elements with an onclick handler also have at least one keyboard event handler (onkeydown, onkeyup, or onkeypress) to ensure keyboard accessibility.
Inherently keyboard-accessible elements (<a>, <button>, <input>, <select>, <textarea>, <option>) are excluded, as are elements hidden from assistive technologies (aria-hidden) or with role="presentation" / role="none".
<!-- Invalid: no keyboard handler --><divonclick="handleClick()">Click me</div><!-- Valid: has keyboard handler --><divonclick="handleClick()"onkeydown="handleKeyDown()">Click me</div><!-- Valid: inherently keyboard-accessible --><buttononclick="handleClick()">Submit</button>
#91529ec8500 Thanks @ematipico! - Added new nursery lint rule noUndeclaredClasses for HTML, JSX, and SFC files (Vue, Astro, Svelte). The rule detects CSS class names used in class="..." (or className) attributes that are not defined in any <style> block or linked stylesheet reachable from the file.
<!-- .typo is used but never defined --><html><head><style>.button{color:blue;}</style></head><body><divclass="button typo"></div></body></html>
#91529ec8500 Thanks @ematipico! - Added new nursery lint rule noUnusedClasses for CSS. The rule detects CSS class selectors that are never referenced in any HTML or JSX file that imports the stylesheet. This is a project-domain rule that requires the module graph.
/* styles.css — .ghost is never used in any importing file */.button{color:blue;}.ghost{color:red;}
#95466567efa Thanks @nhedger! - Added a biome upgrade command for standalone installations. It upgrades Homebrew installs with brew upgrade biome, updates manually installed binaries from the latest GitHub release, and tells npm users to upgrade with their package manager instead.
#9716701767a Thanks @faizkhairi! - Added the HTML version of the useHeadingContent rule. The rule now enforces that heading elements (h1-h6) have content accessible to screen readers in HTML, Vue, Svelte, and Astro files.
<!-- Invalid: empty heading --><h1></h1><!-- Invalid: heading hidden from screen readers --><h1aria-hidden="true">invisible content</h1><!-- Valid: heading with text content --><h1>heading</h1><!-- Valid: heading with accessible name --><h1aria-label="Screen reader content"></h1>
#9582f437ef8 Thanks @rahuld109! - Added the HTML version of the useKeyWithMouseEvents rule. The rule now enforces that onmouseover is accompanied by onfocus and onmouseout is accompanied by onblur in HTML, Vue, Svelte, and Astro files.
<!-- Invalid: onmouseover without onfocus --><divonmouseover="handleMouseOver()"></div><!-- Valid: onmouseover paired with onfocus --><divonmouseover="handleMouseOver()"onfocus="handleFocus()"></div>
#92751fdbcee Thanks @ff1451! - Added the new assist action useSortedTypeFields, which sorts the fields of GraphQL object types, interface types and input object types alphabetically, e.g. name, age, id becomes age, id, name.
#1056178075b7 Thanks @Conaclos! - Added a new style option to useExportType,
which enforces a style for exporting types.
This is the same option as the one provided by useImportType.
#8987d16e32b Thanks @DerTimonius! - Ported the useValidAnchor rule to HTML. This rule enforces that all anchors are valid and that they are navigable elements.
#100690eb9310 Thanks @Netail! - Added the HTML lint rule noStaticElementInteractions, which enforces that static, visible elements (such as <div>) that have click handlers use the valid role attribute.
With the option enabled, the following example is considered valid and is ignored by the rule:
consttruthy=!!value;
#9700894f3fb Thanks @ematipico! - The Biome Language server now supports the "go-to definition" feature.
When the cursor of the mouse is hovering an entity (variable, CSS class, type, etc.), and the command CTRL + click is triggered, the editor jumps to where this entity is defined, if the language server can find it.
Here's what Biome is able to resolve:
Variables and types used in JavaScript modules, defined in the same file or imported from another module.
JSX Components used in JavaScript modules, defined in the same file or imported from another module.
CSS classes used in JSX and HTML-ish files (Vue, Svelte and Astro), and defined in CSS files.
Components used in HTML-ish files and defined in other HTML-ish.
Variables used in HTML-ish files and defined in the same file or imported from another module (JavaScript or HTML-ish).
#93662ca1117 Thanks @dyc3! - Added the html.parser.vue configuration option. When enabled, it adds support for the parsing of Vue in .html files. Most Vue users don't need to enable this option since Vue files typically use the .vue extension, but it can be useful for projects that embed Vue syntax in regular HTML files.
#907374b20ee Thanks @chocky335! - Added support for applying GritQL plugin rewrites as code actions. GritQL plugins that use the rewrite operator (=>) now produce fixable diagnostics for JavaScript, CSS, and JSON files. By default, plugin rewrites are treated as unsafe fixes and require --write --unsafe to apply. Plugin authors can pass fix_kind = "safe" to register_diagnostic() to mark a fix as safe, allowing it to be applied with just --write.
Example plugin (useConsoleInfo.grit):
language js
`console.log($msg)` as $call where {
register_diagnostic(span = $call, message = "Use console.info instead of console.log.", severity = "warn", fix_kind = "safe"),
$call => `console.info($msg)`
}
Running biome check --write applies safe rewrites. Unsafe rewrites (the default, or fix_kind = "unsafe") still require --write --unsafe.
#9384f4c9edc Thanks @Conaclos! - Added the sortBareImports option to organizeImports,
which allows bare imports to be sorted within other imports when set to false.
- import "b";
import "a";
+ import "b";
import { A } from "a";
+ import "./file";
import { Local } from "./file";
- import "./file";
#8731e7872bf Thanks @siketyan! - Added the watch mode (--watch) to the CLI for check/format/lint commands. By enabling this option, Biome will re-run the check automatically when any file in the workspace has changed after the first run.
#9967e9b6c17 Thanks @dyc3! - Added HTML support for noExcessiveLinesPerFile. Biome now reports HTML files that exceed the configured line limit, including when skipBlankLines is enabled.
#9491b3eb63c Thanks @IxxyDev! - Added the HTML lint rule noAriaUnsupportedElements. This rule enforces that elements that do not support ARIA roles, states, and properties (meta, html, script, style) do not have role or aria-* attributes.
<!-- Invalid: meta does not support aria attributes --><metacharset="UTF-8"role="meta"/>
#9306afd57a6 Thanks @viraxslot! - Added the noNoninteractiveTabindex lint rule for HTML. This rule enforces that tabindex is not used on non-interactive elements, as it can cause usability issues for keyboard users.
#92766d041d9 Thanks @IxxyDev! - Added the HTML lint rule noRedundantRoles. This rule enforces that explicit role attributes are not the same as the implicit/default role of an HTML element. It supports HTML, Vue, Svelte, and Astro files.
<!-- Invalid: role="button" is redundant on <button> --><buttonrole="button"></button>
#981369aadc2 Thanks @ematipico! - Added a new linter configuration called preset. With the new option, users can enable different kinds of rules at once.
The following presets are available:
"recommended": it enables all Biome-recommended rules, or recommended rules of a group;
"all": it enables all Biome rules, or enables all rules of a group;
"none": it disables all Biome rules, or disable all rules of a group.
You can enable recommended rules:
{"linter":{"rules":{"preset":"recommended"}}}
You can enable all rules at once:
{linter:{rules:{preset:"all",// enables all rules
},},}
Or enable all rules for a group:
{linter:{rules:{style:{preset:"all",// enables all rules in the style group
},},},}
This new option, however, doesn't affect how nursery rules work. Nursery rules must be enabled singularly, due to their nature.
This new option is meant to replace recommended, so make sure to run the migrate command.
#839613785fc Thanks @apple-yagi! - Biome now supports pnpm catalogs (default and named) when resolving dependencies for linting. This behavior is opt-in and requires setting javascript.resolver.experimentalPnpmCatalogs to true.
#9853816302f Thanks @Netail! - Added the new assist action useSortedSelectionSet, which sorts GraphQL selection sets alphabetically, e.g. name, age, id becomes age, id, name.
Invalid:
query{nameageid}
#100749c7c6eb Thanks @georgephillips! - Added a kind field to the ImportMatcher used by the organizeImports assist action. The new field selects imports by their syntactic kind and currently supports bare (matching side-effect imports such as import "polyfill") with optional ! negation (!bare). The matcher composes with the existing type and source fields, so users can express patterns such as "only bare imports that import a CSS file" ({ "kind": "bare", "source": "**/*.css" }).
#9171ce65710 Thanks @chocky335! - Added includes option for plugin file scoping. Plugins can now be configured with glob patterns to restrict which files they run on. Use negated globs for exclusions.
#94961dfb829 Thanks @aviraldua93! - Added HTML support for the noAriaHiddenOnFocusable accessibility lint rule, which enforces that aria-hidden="true" is not set on focusable elements. Focusable elements include native interactive elements (<button>, <input>, <select>, <textarea>), elements with href (<a>, <area>), elements with tabindex >= 0, and editing hosts (contenteditable). Includes an unsafe fix to remove the aria-hidden attribute.
<!-- Invalid: aria-hidden on a focusable element --><buttonaria-hidden="true">Submit</button><!-- Valid: aria-hidden on a non-focusable element --><divaria-hidden="true">decorative content</div>
#9761cbbb7d5 Thanks @Maximiliano-Zeballos! - Ported the useValidAriaProps lint rule to HTML. This rule checks that all aria-* attributes used in HTML elements are valid ARIA attributes as defined by the WAI-ARIA specification.
#9928aa82576 Thanks @aviraldua93! - Ported useValidAriaValues to HTML. Biome now validates static aria-* attribute values in HTML elements against WAI-ARIA types, catching invalid values such as aria-hidden="yes".
#10121450f8e1 Thanks @jongwan56! - Biome now applies Git's local exclude file when VCS ignore files are enabled. Files listed in .git/info/exclude are skipped the same way as files listed in .gitignore, including in linked worktrees.
#9397d5913c9 Thanks @mvarendorff! - Added ignore option to the noUnusedVariables rule. The option allows excluding identifiers by providing a list of ignored names. It also allows excluding kinds of identifiers from this rule entirely, which may be useful when loading classes dynamically.
For example, unused classes as well as all unused variables, functions, etc. called "unused" may be ignored entirely with the following configuration:
{"ignore":{"*":["unused"],"class":["*"]}}
#1008971a21f0 Thanks @Netail! - Added the lint rule noLabelWithoutControl to HTML, which enforces that a label element or component has a text label and an associated input.
#102341a51569 Thanks @ematipico! - Added the delimiterSpacing formatter option. This option inserts spaces inside delimiters (after the opening delimiter and before the closing delimiter) when the content fits on a single line. Empty delimiters are not affected, and no space is added before the opening delimiter. The specific delimiters affected depend on the language. It can be configured globally via formatter.delimiterSpacing or per-language via javascript.formatter.delimiterSpacing, json.formatter.delimiterSpacing, and css.formatter.delimiterSpacing. Defaults to false.
When enabled, Biome inserts spaces inside parentheses (e.g., foo( a, b )), square brackets (e.g., [ a, b ]), template literal interpolations (e.g., ${ expr }), and the logical NOT operator (e.g., ! x, but in chains only after the last one: !! x). Only applies when the content fits on a single line. Empty delimiters and the space before the opening delimiter are not affected.
- if (condition) {}
+ if ( condition ) {}
- `Hello ${name}!`
+ `Hello ${ name }!`
JSX
When enabled, Biome inserts spaces inside JSX expression braces (e.g., attr={ value }) and spread attributes (e.g., { ...props }). Only applies when the content fits on a single line. Empty delimiters are not affected.
- <Foo bar={value} />
+ <Foo bar={ value } />
TypeScript
When enabled, Biome inserts spaces inside TypeScript angle brackets (e.g., foo< T >()), indexed access types (e.g., T[ K ]), mapped types, tuple types, type parameters, and index signatures. Only applies when the content fits on a single line. Empty delimiters are not affected.
- type Result = Map<string, number>;
+ type Result = Map< string, number >;
JSON
When enabled, Biome inserts spaces inside square brackets when the content fits on a single line. Empty brackets are not affected.
- [1, 2, 3]
+ [ 1, 2, 3 ]
CSS
When enabled, Biome inserts spaces inside parentheses and square brackets when the content fits on a single line. Empty delimiters are not affected.
- rgba(0, 0, 0, 1)
+ rgba( 0, 0, 0, 1 )
- [data-attr]
+ [ data-attr ]
#104616bac1c3 Thanks @TXWSLYF! - Implements #9445. Added the allowImplicit option to useIterableCallbackReturn. When enabled, callbacks can use return; to implicitly return undefined, matching ESLint's array-callback-return rule.
#95715a8eb75 Thanks @dyc3! - Added configurable options to the useNumericSeparators rule. Users can now customize the minimum number of digits required before adding separators and the group length for each type of numeric literal (binary, octal, decimal, hexadecimal).
#9974ff635a9 Thanks @pkallos! - Added ignoreMixedLogicalExpressions to useNullishCoalescing, partially addressing #9232. When enabled, Biome ignores || and ||= mixed with && in the same expression tree.
#10503c656679 Thanks @Mokto! - Added the new nursery rule useSvelteRequireEachKey, a Svelte lint rule that reports {#each} blocks with item bindings that are missing a key.
#105160f29b83 Thanks @Dotify71! - Added useIncludes to the nursery group. This rule flags comparisons of String.prototype.indexOf() or Array.prototype.indexOf() against -1 and suggests replacing them with the clearer includes() / !includes() form.
#104870c03ee3 Thanks @Mokto! - Fixed a Svelte parser error that incorrectly required a binding variable after {:then} and {:catch}. Biome now correctly accepts {:then} and {:catch} without a binding, as well as the {#await expr then} and {#await expr catch} shorthand forms.
#105916e8557b Thanks @xsourabhsharma! - Fixed #10563: Biome now parses comma-separated CSS Modules composes values, such as composes: classA from "./a.css", classB from "./b.css";.
#10603174b21b Thanks @denbezrukov! - Fixed CSS formatting for grid-template-areas declarations with comments before multiline values. Biome now keeps grid area rows aligned instead of adding an extra declaration-boundary indent.
#10542c3f07f7 Thanks @dyc3! - Fixed #10513: Biome no longer rejects literal \u sequences in quoted HTML attribute values.
#1010824e51d6 Thanks @IxxyDev! - Fixed #6611: noUnnecessaryConditions now uses type information to detect more redundant conditions, including ?., ??, ||, &&, comparisons against null/undefined on non-nullish operands, and case clauses that can never match the switch value.
#10568eb1ed0e Thanks @harsha-cpp! - Fixed #10564: useAriaPropsForRole no longer reports false positives for Vue v-bind shorthand bindings (:aria-checked, :aria-level, etc.).
#10520b55d10f Thanks @dyc3! - Fixed #10519: Vue v-on event handlers with multiple inline statements are now parsed consistently with Vue.
#10204ebbf0bd Thanks @ematipico! - Improved the performance of the Biome linter. The improvements are more visible in bigger projects that have more than ~1k files. Early tests showed that in a code base with ~2k files, Biome took less than 26% of time to finish the command.
#80122be0264 Thanks @denbezrukov! - Improved the performance of the formatter in some cases. The formatter is now up to ~20% faster at formatting files.
#104679a5855e Thanks @Netail! - Added a new nursery rule noRestrictedDependencies, which flags imports and package.json dependency entries that have better alternatives in e18e's module replacement data.
For example, the package globby is reported because there's a better alternative:
#105321da3c75 Thanks @denbezrukov! - CSS declarations with comments before : or after !important now preserve spaces before : and ;.
.selector {
- padding/* name */: 1px;
- color: red !important /* note */;
+ padding/* name */ : 1px;
+ color: red !important /* note */ ;
}
#10491a1b5834 Thanks @Mokto! - Fixed the Svelte parser rejecting {#each} blocks where the binding uses object destructuring with property renaming, e.g. {#each items as { id, component: Filter }}. Biome now correctly parses and formats these rename bindings.
#1049099bc7df Thanks @Mokto! - Fixed the CSS parser rejecting comma-separated selector lists inside :global() and :local() pseudo-class functions. Biome now correctly parses :global(.foo, .bar).
#10543c394fae Thanks @mangod12! - Fixed #10477: The RDJSON reporter now emits code replacement text for fix suggestions instead of the human-readable fix description.
#10530e8e1e6a Thanks @Conaclos! - Fixed #10493: useImportType now correctly separates types from a default named import when all imports are types and the style option is set to separatedType.
noRedundantAlt no longer emits false positives when the alt text contains an interpolation, e.g. alt="image of {person}".
useButtonType no longer emits false positives for dynamic button types written as type="{dynamicType}".
noScriptUrl no longer emits false positives for dynamic hrefs such as href="{url}".
#1048996ef9a4 Thanks @Mokto! - Fixed Svelte {#each} parser incorrectly rejecting TypeScript as const type assertions in the iterable expression. Biome now correctly parses {#each arr as const as item}.
#10539935c59a Thanks @dyc3! - Improved how diagnostics print long lines of code, for example minified files where the entire source code is printed in one line.
#10329ef764d5 Thanks @Conaclos! - Fixed an issue where diagnostics showed an incorrect location in Astro files.
#1036350aa415 Thanks @dyc3! - Fixed HTML formatting for a case where comments could cause the formatter to split up a closing tag, which would cause the resulting HTML to be syntactically invalid.
#1035805c2617 Thanks @dyc3! - Fixed #10356: biome rage --linter now displays rules enabled through linter domains in the enabled rules list.
#10300950247c Thanks @dyc3! - Fixed #10265: Svelte function bindings such as bind:value={get, set} are now parsed more precisely, so noCommaOperator won't emit false positives for that syntax anymore.
#9786e71f584 Thanks @MeGaNeKoS! - Fixed #8480: useDestructuring now provides variableDeclarator and assignmentExpression options to control which contexts enforce destructuring, matching ESLint's prefer-destructuring configuration. Both default to {array: true, object: true}. The diagnostic for object destructuring in assignment expressions now instructs users to wrap the assignment in parentheses.
#104251948b72 Thanks @sjh9714! - Fixed #10244: The useOptionalChain rule now detects negated guard inequality chains like !foo || foo.bar !== "x".
#10442001f94f Thanks @ematipico! - Fixed #10411: noMisusedPromises no longer causes a stack overflow when a nested function returns an object with shorthand properties that shadow destructured variables from an outer scope.
#103189b1577f Thanks @dyc3! - Added support for formatter.trailingCommas in overrides. This option was previously available in the top-level formatter configuration but missing from formatter overrides.
#103192e37709 Thanks @dyc3! - Fixed Vue and Svelte formatting for standalone interpolations in inline elements. Biome now preserves existing newlines in cases like:
- <span> {{ value }} </span>
+ <span>
+ {{ value }}
+ </span>
#10439df6b867 Thanks @denbezrukov! - Fixed CSS and SCSS formatting for comments around declaration colons so comments between property names, colons, and values stay at the same boundary as Prettier.
24b2797: Update oxfmt to 0.67.0 and re-target the markdown ::: fence patch to the new dist chunk. The release changes no options; it fixes CSS/SCSS/Less comment preservation and a few JSDoc-cast edge cases in member chains.
24b2797: Update oxlint to 1.82.0. The release adds and removes no rules, so the presets are unchanged apart from one new option: no-unmodified-loop-condition now runs with checkConditionalExpressions: true in the oxlint and ESLint core presets, so each branch of a ternary in a loop condition must be modified inside the loop rather than only the expression as a whole.
24b2797: Update the ESLint family: @angular-eslint/eslint-plugin 22.5, @typescript-eslint/* 8.70, eslint-plugin-solid 0.18, eslint-plugin-vue 10.11, eslint-plugin-jsdoc 64.3.8, eslint-plugin-cypress 7.0.2, @darraghor/eslint-plugin-nestjs-typed 7.5.2 and prettier-plugin-astro 1.0. The dynamic presets pick up the seven new rules automatically: @typescript-eslint/no-generated-empty-object-type, @angular-eslint/reactive-context-must-read-signal, vue/no-shadow-native-events, and Solid's no-boolean-enumerated-attribute, no-store-mutation-outside-setter, no-unused-signal and no-write-in-pure-computation. Note that prettier-plugin-astro 1.0 is a rewrite on the Astro 7 Rust compiler (Node 22.12+); expect whitespace diffs on first run and mirror any custom compressHTML via its new astroCompressHTML option.
24b2797: Refresh the stylelint lock to 17.15.0 and enable its new selector-no-unmatchable rule, which flags selectors that can never match (for example label:checked, ::before:first-child or :is(::before)).
a71dda4: Stop sorting object keys across the whole TanStack presets, not just route files. TanStack Query mutation options are order-sensitive too: TypeScript infers the onMutate context from context-sensitive callbacks in source order, so moving onError/onSettled above onMutate turns the context into {} and ultracite fix broke type-correct code (TS2339: Property '...' does not exist on type '{}'). Mutation and query options live anywhere (hooks, components, colocated files), so the route-file exemption could not cover them. ultracite/oxlint/tanstack now sets sort-keys to off and ultracite/biome/tanstack now sets useSortedKeys to off for all files.
a9db61c: Disable github/filenames-match-regex for file-based route directories (**/routes/**) in the oxlint js-plugins preset, matching the existing unicorn/filename-case exemption in the TanStack preset. TanStack Router filenames such as __root.tsx, $.tsx, and posts.$postId.tsx no longer fail the GitHub filename rule. Resolves #799.
d5d241f: Add ultracite upgrade, and make version drift between Ultracite and its linter visible instead of a crash. Bumping ultracite without bumping the linter fails on the next check/fix with Biome's Found an unknown key error (and the equivalent for ESLint and Oxlint), because each release enables rules from a specific linter version.
ultracite upgrade installs the latest ultracite, prints a release-notes link for the versions you crossed, then hands off to the freshly installed CLI to reinstall your toolchain at the versions that release was verified with: Biome; ESLint, Prettier, Stylelint and the plugins the preset imports; or Oxlint and Oxfmt. Optional extras already in your package.json (framework plugins, Oxlint JS plugins, oxlint-tsgolint) are bumped as well. Config files are never rewritten, and the run ends with the same diagnostics as doctor.
ultracite doctor now checks the installed Biome, ESLint, Prettier, Stylelint, Oxlint and Oxfmt versions against the range this release supports. Too old fails the check and points at ultracite upgrade; newer than the verified range only warns.
The supported ranges are declared as optional peer dependencies so package managers warn when they drift: @biomejs/biome ^2.5.0, eslint ^10.0.0, prettier ^3.0.0, stylelint ^17.0.0, oxlint ^1.79.0, oxfmt >=0.40.0. ultracite init now installs Prettier and Stylelint from those ranges instead of latest.
d322691: Default ultracite init to Oxlint + Oxfmt when --linter is omitted in quiet or non-interactive mode
c677cf5: Recommend Oxlint + Oxfmt in the ultracite init linter prompt and list it first
c5be848: Disable no-use-before-define in TanStack Router route files for the oxlint tanstack preset. File routes are mutually recursive (Route references the component, and the component calls Route.useParams()), so no declaration order could satisfy the rule.
2a43fdd: Turn off unicorn/prefer-reflect-apply in the ultracite/oxlint/anti-slop preset. When extended after ultracite/oxlint/core, the core rule recommended rewriting Function#apply() to Reflect.apply(), which anti-slop's no-reflect-apply then rejected, leaving no way to satisfy both. Direct-call guidance for .apply() still comes from eslint/prefer-spread and eslint/no-useless-call.
03196df: Update @biomejs/biome to 2.5.12. Releases 2.5.10 through 2.5.12 only add nursery rules, which the Biome presets exclude, so the presets are unchanged. The releases also carry linter and formatter fixes, including fewer noUnusedVariables false positives on merged interfaces, namespaces, and overload type parameters, an unsafe-by-default fix for noThisInStatic, and a large batch of Astro expression parsing fixes.
031b867: Update oxfmt to 0.66.0. The 0.65 and 0.66 releases are formatter fixes only, mainly around comment placement between a statement head and its body, suppressed statements (decorators, typecast parens, semicolons), custom side-effect groups in sortImports, CommonMark list interruption in JSDoc, and trailing whitespace in YAML block scalars. The ::: container-directive fence patch is re-targeted to the new markdown bundle; the patched code itself is unchanged.
54affee: Update oxlint to 1.81.0. The 1.80 and 1.81 releases add no rules and remove none, so the presets are unchanged and the peer range stays at ^1.79.0. Notable fixes carried in: no-use-before-define now runs on JS and JSX files, object-shorthand preserves __proto__ semantics, unicorn/prefer-math-min-max no longer applies an unsafe autofix, and JS plugin diagnostics with invalid or reversed locations are clamped instead of crashing.
0b058d1: Fix ultracite fix --codex failing on recent Codex CLI releases. The Codex adapter invoked codex exec --full-auto, a flag Codex has since removed, so every attempt failed at argument parsing. It now runs codex exec --sandbox workspace-write, the equivalent non-interactive, workspace-scoped mode, which is also accepted by older Codex versions. Resolves #794.
e2346bb: Update the ESLint family to latest: eslint 10.9.1, typescript-eslint 8.69.0, eslint-plugin-unicorn 74, eslint-plugin-solid 0.17, eslint-plugin-jsdoc 64.3.5, eslint-plugin-react-doctor and oxlint-plugin-react-doctor 0.9.13, globals 17.12, and the angular, nestjs-typed, next, tanstack-query, cypress, html, jest and storybook plugins. The dynamic presets pick up the new rules automatically: the solid preset gains the eleven rules added in eslint-plugin-solid 0.16 and 0.17 (removed-api, no-single-arg-create-effect, no-accessor-as-prop, valid-use-server, require-async-server-function, no-invalid-server-capture, no-browser-globals-in-server-function, no-module-scope-reactive-primitive, no-restated-default-options, prefer-onSettled-for-side-effects, prefer-structured-class), which only report Solid 2.0 issues when settings.solid.version is set to 2 and stay silent on Solid 1.x code; the nestjs preset gains forward-ref-injection-should-use-wrapper-type, swagger-file-upload-should-be-documented and uploaded-file-should-be-validated. The curated jsdoc and react-doctor lists are unchanged. No enabled rule was removed or deprecated, and the ESLint/oxlint parity check still passes.
7b0456e: ultracite fix now runs lint fixes before the formatter: oxlint before oxfmt, and ESLint then Stylelint before Prettier. A fixer can insert unformatted code, such as the braces curly adds, the imports consistent-type-specifier-style splits, or the font names Stylelint requotes, and running the formatter first left that code unformatted until the next run. Fixer-inserted code is now formatted in the same run. The --claude and --codex agent passes follow the same order.
unicorn/no-nested-ternary is now off in the oxlint and ESLint presets: its fixer adds parentheses that oxfmt and Prettier remove, so the two tools rewrote the file on every run. The core no-nested-ternary rule still reports nested ternaries.
8ddc078: Enable three rules added in Stylelint 17 in the Stylelint preset: selector-no-deprecated and selector-no-invalid report selectors that CSS has dropped or that cannot parse, and relative-selector-nesting-notation is set to explicit, so nested relative selectors are written & > b rather than > b. The property-layout-mappings, unit-layout-mappings and value-keyword-layout-mappings rules are deliberately left off, since they reject every physical property, unit and keyword and can only autofix with a per-project languageOptions.directionality setting. The repo's own Stylelint lock is refreshed from 16.26.1 to 17.14.1, which the config packages already required; ultracite init already installs stylelint@latest so users are unaffected by the lock change.
4609d79: Update the vendored anti-slop Oxlint plugin to upstream v0.1.2 (commit e8c4880). The rule set is unchanged; this picks up a round of correctness fixes: no-known-value-widening now also reports known values passed into local unknown-typed type predicates, no-object-parameters, no-unknown-parameters, no-unknown-returns and no-unknown-type-aliases resolve scoped and transparent generic aliases (including block-scoped aliases and forward references), no-unknown-returns covers PromiseLike<unknown>, no-unsafe-dictionary-type allows generic constraints such as T extends Record<string, unknown>, no-runtime-typeof always allows existence probes against "undefined", no-shape-in-symbol-names allows static member reads such as Zod's schema.shape, and require-safety-comment-for-type-assertion rejects empty justifications and gains a markers option (default ["SAFETY"]). Upstream also added a separate opt-in anti-slop-effect plugin for Effect projects, which is not vendored.
15f7ae0: Add support for the Aube package manager: ultracite init --pm aube is now accepted and projects with an aube-lock.yaml lockfile are detected automatically
1afc8fe: Re-declare selected Oxlint JS plugins on the root config so dependency analyzers see them. ultracite init --linter oxlint --js-plugins ... now generates const jsPlugins = selectJsPlugins([...]) and adds jsPlugins: jsPlugins.jsPlugins to the root config (also when the full ultracite/oxlint/js-plugins preset is extended). Knip only resolves jsPlugins from the root Oxlint config and never walks extends, so eslint-plugin-github, eslint-plugin-sonarjs, and oxlint-plugin-react-doctor were reported as unused devDependencies. Oxlint dedupes the plugin between the root and the extended preset, so linting is unchanged.
Also fix ultracite update dropping the js-plugins preset from extends when the config used the documented import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins" form: the import parser only matched bare default imports. The regenerated full-preset config keeps settings: jsPluginSettings on the root as well.
20b06bf: Ignore .alchemy across all linters and formatters. Alchemy (alchemy.run) writes local state and generated bindings to a .alchemy directory. It is now part of the shared ignore patterns synced into Biome's files.includes and imported by oxlint, oxfmt, and ESLint, and the Stylelint preset ignores it via ignoreFiles. Prettier needs no change: it already respects .gitignore/.prettierignore.
6e9286c: Run lefthook install during ultracite init through the same spawn adapter as every other tool invocation instead of execSync, so it no longer goes through a shell and gets the same Windows command resolution as husky, the linters, and editor extension installs.
8b24f34: Add support for the Nub package manager: ultracite init --pm nub is now accepted and projects with a nub.lock lockfile are detected automatically (requires nypm ^0.6.9)
240cb6b: Install into the workspace root correctly for Nub and Aube monorepos: nypm emits no root selector for them, so nub add ran without -w and was refused. Ultracite now hands nypm pnpm's flag set for these pnpm-compatible CLIs, producing nub add --workspace-root --save-dev ultracite
44ecbba: Add Vitest type-test files (**/*.{test-d,spec-d}.{ts,tsx,js,jsx}) to the test-file globs so the shared test relaxations and the Vitest rule overrides apply to them, and enable the Vitest plugin's typecheck setting in the ESLint preset so expectTypeOf/assertType count as assertions.
7ba6bb8: Package the reusable Ultracite agent skill with the npm distribution.
972b946: Update the oxlint presets for oxlint 1.79: replace the removed react/react-compiler rule with the 22 new React Compiler rules in the react preset, add jsdoc/no-blank-blocks and one-var to the core preset (mirrored in the ESLint presets), and require oxlint ^1.79.0
2d5bbdb: Declare the jsPluginSettings named export in the ultracite/oxlint/js-plugins type declarations, so the documented (and ultracite init-generated) import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins" type-checks (#773)
56aef65: Refresh the toolchain versions that ultracite init installs into projects: @biomejs/biome 2.5.9, the ESLint plugin family (including eslint-plugin-cypress 7, eslint-plugin-jsdoc 64, eslint-plugin-solid 0.15, and eslint-plugin-unicorn 73 — the dynamic presets adopt their new rules automatically), and prettier-plugin-svelte 4.1.1 / prettier-plugin-tailwindcss 0.8.1
8df6ad0: Offer the vendored anti-slop Oxlint preset during ultracite init — it now appears in the JS-plugins prompt when you pick Oxlint, and non-interactive setup accepts it via --js-plugins anti-slop. Selecting it adds ultracite/oxlint/anti-slop to the generated config's extends; since the preset is vendored inside Ultracite, nothing extra is installed.
cd229e9: Bump the oxlint-plugin-react-doctor pin from ^0.7.1 to ^0.9.12, so ultracite init installs the current plugin. All react-doctor rules enabled by the js-plugins presets still exist in 0.9.12, and the ported rules run in curated mode via the settings shipped alongside this release (#771).
e1ac886: Pin React Doctor's ported rules to their framework-aware "curated" mode (#771). react-doctor 0.9.x rewrote its ported oxc/react-refresh rules — notably only-export-components — with a stripped-down default mode: no framework detection, no route-file skipping, and allowConstantExport off, so Next.js route-segment exports like export const dynamic = "force-static" or metadata were flagged as non-component exports in every route file. The ESLint react preset now sets settings["react-doctor"].portedRuleMode: "curated", and generated oxlint configs apply a new jsPluginSettings export from ultracite/oxlint/js-plugins on the root config (oxlint does not merge settings from extended configs, so the setting cannot ride along inside the preset). If you extend the js-plugins preset manually, add settings: jsPluginSettings to your root oxlint config.
c27fe36: Generate oxlint configs that enable a subset of the JS plugins via a new selectJsPlugins export from ultracite/oxlint/js-plugins, instead of inlining the filtering logic into the generated file. The inlined block contained a typeof check that user-side lint presets flagged (anti-slop/no-runtime-typeof, #770); the generated config is now a one-line extend, is emitted already formatted (including the previously missing blank line after imports), and re-running ultracite init migrates existing configs with the old inlined block automatically.
0616523: Update the vendored anti-slop Oxlint plugin to upstream commit 446268e, picking up fixes to no-object-parameters and no-unknown-returns (respect lexical type binders in alias resolution) and a new allowInTypeGuards option on no-runtime-typeof. The ultracite/oxlint/anti-slop preset enables allowInTypeGuards, so typeof checks inside type predicate functions ((x): x is T) no longer need disable comments — predicates are the named-boundary pattern the rule pushes toward (dmmulroy/anti-slop#10).
417a85a: Add an opt-in ultracite/oxlint/anti-slop preset that ships a vendored, self-contained build of the anti-slop Oxlint plugin — fifteen rules that reject low-evidence TypeScript and JavaScript patterns (unjustified type assertions, unknown leaking through signatures, Reflect-based access, module mocking, and more). Extend it alongside ultracite/oxlint/core; nothing extra to install. The preset also turns off two core rules that conflict with anti-slop's widening checks (typescript/consistent-indexed-object-style and unicorn/no-immediate-mutation) when extended after core.
4d3fab8: Move suspicious/useArraySortCompare from the Biome core config to the opt-in type-aware config. The rule is in Biome's types domain — it type-infers the receiver of every method call before checking the method name, which made ultracite check up to ~260x slower on projects with expensive library types (zod, better-auth, Prisma). It now only runs when type-aware linting is explicitly enabled, alongside the other type/project-domain rules. Fixes #768.
a1fa9c4: Replace the hand-rolled package exports map matching in the config-resolution doctor check with the resolve.exports library, which implements Node's full PACKAGE_TARGET_RESOLVE algorithm (wildcard patterns, key-order precedence, conditional exports, and array fallbacks). The manual node_modules walk is kept intentionally — it exists to avoid Bun's auto-install cache resolving specifiers the project's own node_modules can't.
414ea80: Replace the hand-rolled monorepo workspace scan in framework detection with the find-workspaces library. Workspace declarations from package.json (array and yarn-classic object form) and pnpm-workspace.yaml — including negated globs — are now resolved by the library instead of manual pattern collection and globbing, and lerna/bolt monorepos are picked up as well.
a9a1989: Replace the hand-rolled upward directory walks in findNearestFile and detectLinter with the empathic library's find.any, which checks candidate names in order within each directory before moving to the parent — the same per-directory precedence the previous implementation enforced manually.
27b2707: Use magicast to update ESM lint-staged config files during ultracite init. The config is now edited as an AST instead of being imported and re-serialized, so comments and function-valued entries elsewhere in the config survive the update, and the user's config code is no longer executed. If the Ultracite glob pattern is already owned by a non-array value, or the config isn't a mergeable object literal (e.g. defineConfig(...)), init warns and leaves the file untouched instead of rewriting it. CommonJS configs keep the previous behavior.
f2529b8: Rewrite the agent-fix progress renderer on top of log-update, cli-truncate, and string-width. log-update now owns the in-place block rewriting that was previously done with manual cursor-up/clear-line escape sequences, and line truncation is measured by display width instead of code units — so lint messages containing emoji or CJK text can no longer overflow the terminal row and corrupt the animated block.
277b9d6: Replace the hand-rolled child-process handling in the agent fix runner with execa. The timeout → SIGTERM → grace period → SIGKILL escalation, stderr capture, and spawn-failure handling now use execa's timeout and forceKillAfterDelay options, which are battle-tested across platforms (including Windows kill semantics the manual implementation didn't cover). Behavior is unchanged: agent runs still time out after 5 minutes, escalate to SIGKILL after a 10-second grace period, and report a capped stderr tail.
1614a80: Drop the direct cross-spawn dependency: all synchronous process spawning (linter runs, tool version checks, editor extension installs, skill installs) now goes through a small adapter over execa's sync API, which owns the Windows spawn semantics cross-spawn provided. The adapter preserves the spawnSync result shape (status/signal/error/stdout), always disables shell interpretation, and always decodes output as UTF-8. execa was already a dependency for the agent fix runner, so this consolidates on one process-spawning library.
ac114b4: Replace the glob dependency with fast-glob for the tsconfig.json scan during init. fast-glob was already in the dependency tree via find-workspaces, so this drops glob's transitive dependencies (minipass, path-scurry, etc.) from the install without changing behavior.
1c48c68: Enable Tailwind CSS class sorting (sortTailwindcss) in the Oxfmt preset. Classes in class/className attributes and in clsx, cva, tw, twMerge, cn, twJoin, and tv calls are now sorted using the same algorithm as prettier-plugin-tailwindcss, matching the behavior of the Prettier preset (which always loads the Tailwind plugin) and the Biome preset's useSortedClasses rule. Projects without Tailwind installed are unaffected beyond class strings being sorted against the default theme, and oxfmt versions older than 0.35.0 ignore the option.
dc78be4: Stop sorting TanStack route option keys in route files. TanStack Router's route option types are order-sensitive (head/component infer loaderData from properties declared before them), so the Biome useSortedKeys source action rewrote createFileRoute literals into an order that breaks type inference (loaderData becomes never). The Biome TanStack preset now disables useSortedKeys for route files, and the oxlint TanStack preset disables sort-keys there so route files aren't caught between it and react-doctor/tanstack-start-route-property-order.
d018b7f: Fix several agent fix mode (fix --claude/--codex) issues: runs no longer abort with ENOBUFS when linter JSON output exceeds 1MB, user-supplied format/reporter flags can no longer override the JSON reporter and break parsing, a stuck agent process is force-killed 10 seconds after the timeout instead of hanging forever, and the progress renderer no longer garbles TTY output when file paths and rule names exceed the terminal width.
d018b7f: Fix Biome config migration leaving the legacy bare "extends": ["ultracite"] form in place, which breaks Biome's module resolution since the package has no root export. It's now mapped to ultracite/biome/core.
d018b7f: Fix ultracite doctor reporting spurious failures: config checks now walk up parent directories (matching check/fix and the linters themselves) so monorepo packages inheriting a root config pass, .oxlintrc.json is accepted as a valid oxlint config (with a migration suggestion), and Prettier/Stylelint configs declared via package.json keys are recognized.
d018b7f: Fix ultracite init corrupting existing Prettier/Stylelint/ESLint configs by writing an ESM module into JSON/YAML/TOML/CJS config files (e.g. .prettierrc, eslint.config.cjs). Updates now write the default .mjs config instead and remove the incompatible file so it can't shadow the new one.
d018b7f: Fix ultracite check/fix misrouting space-separated flag values (e.g. --max-warnings 10) into the file list, which scrambled the underlying linter invocation and made formatters fail on bogus targets. Positional files listed before a -- separator are also kept as lint targets instead of being reclassified as passthrough, which could silently widen formatter runs to the whole project.
d018b7f: Fix Lefthook and pre-commit YAML updates silently doing nothing on common config shapes: the Lefthook job is now inserted correctly when jobs: isn't the first key under pre-commit: (and no longer matches a jobs: key in a different hook), repos: [] in .pre-commit-config.yaml is handled, and shapes that can't be safely edited produce a warning instead of writing the file back unchanged.
d018b7f: Fix the Husky integration overwriting an existing .husky/pre-commit hook: ultracite init ran husky init, which unconditionally replaces the hook with npm test. It now runs plain husky to set up the hooks infrastructure without touching the hook file.
d018b7f: Fix ultracite init destroying user files it couldn't parse or merge: unparseable tsconfig.json files are no longer replaced with a minimal config, unparseable .vscode/.zed settings are no longer overwritten wholesale, and lint-staged configs with function-valued entries are left untouched — all now warn and skip instead.
d018b7f: Fix re-running ultracite init on an oxlint setup silently enabling the full js-plugins preset — the previously selected JS plugins are now preserved when no new selection is made. Init also no longer flips an explicit "type": "commonjs" in package.json to "module"; it warns instead.
d018b7f: Fix switching linters removing storybook from the project's dependencies. It was swept into the removal set as a peer of eslint-plugin-storybook, but it's a user-facing tool a project may use independently of linting.
d018b7f: Fix Stylelint target generation dropping directories with a dot in their name (e.g. app.web) and producing non-matching globs from Windows-style backslash paths. Framework detection also handles negated workspace patterns (!packages/legacy) again.
d018b7f: Fix the CLI becoming a silent no-op (exiting 0 without linting anything) when a generic TEST environment variable is set, as is common in CI matrices. The internal test guard now uses ULTRACITE_TEST.
36c7b80: Move @typescript-eslint/utils from dependencies to devDependencies. It was accidentally shipped as a runtime dependency in 7.9.0, pulling eslint and the typescript-eslint packages into every consumer's install (including oxlint-only setups) via npm's automatic peer dependency installation. Nothing in the published package imports it — it only exists to support the workspace-internal rule-parity script.
cd0a36c: Add --claude and --codex flags to ultracite fix. After the normal autofix pass, remaining diagnostics are handed to the Claude Code or Codex CLI non-interactively, one agent run per affected file, with a live per-issue spinner that flips to ✓/✗ once the fix is verified by a re-lint. Fixes that don't survive verification are retried (up to 3 attempts per file) with the fresh diagnostics and feedback that the previous approach failed. Works with all three linter modes (Oxlint, Biome, ESLint); exits non-zero if any issues remain, matching the plain fix contract.
The ultracite/oxlint/js-plugins preset no longer enables React Doctor's nextjs-* and TanStack (query-*, tanstack-start-*) rules for every consumer. Rules like nextjs-no-img-element and tanstack-start-no-anchor-element fire on plain <img>/<a> JSX and recommend framework replacements, which falsely errored in Vite + React and other non-Next/non-TanStack projects.
Those rules now live in two new add-on presets:
ultracite/oxlint/next/js-plugins
ultracite/oxlint/tanstack/js-plugins
ultracite init wires the matching add-on automatically when you select the framework together with oxlint-plugin-react-doctor. If you manage oxlint.config.ts by hand and use Next.js or TanStack, add the matching add-on preset to extends alongside js-plugins to keep those rules — or re-run npx ultracite init.
Also fixes re-running init on a config that already extends js-plugins producing a duplicate import jsPlugins declaration.
Patch Changes
3320cd8: Update Biome to 2.5.6. No stable (non-nursery) rules were added, removed, or promoted between 2.5.3 and 2.5.6, so the preset configs are unchanged.
477cd6e: Update ESLint to 10.8.0 and all ESLint plugins to their latest versions. Highlights:
eslint-plugin-react-doctor 0.9.3: the react preset expands from 149 to 417 rules, adopting the upstream recommended set (react-router, three.js/r3f, ink, motion, remotion, zustand/valtio/mobx, and more) while excluding rules that duplicate already-enabled react, react-hooks, and jsx-a11y rules. The next preset gains nextjs-async-dynamic-api-not-awaited and nextjs-metadata-url-consistency; the tanstack preset gains tanstack-start-missing-scripts, query-floating-mutate-async, and query-no-mutation-in-effect-as-read.
eslint-plugin-unicorn 72: adds no-missing-local-resource, no-multiple-promise-resolver-calls, no-shorthand-property-overrides, no-transition-all, no-unnecessary-string-trim, no-useless-re-export, prefer-then-catch, and require-frontmatter-fields. CSS-only rules are excluded from the preset since they fail config validation for JS files.
eslint-plugin-sonarjs 4.2: adds 11 rules including no-fixed-wait-in-tests, parameterized-tests, assertions-in-test-cases, prefer-native-lodash-alternative, and explicit-test-skip.
typescript-eslint 8.65: @typescript-eslint/no-loop-func and @typescript-eslint/no-restricted-imports were deprecated upstream in favor of the base rules, which now apply to TypeScript files.
eslint-plugin-astro 3: removes astro/no-omitted-end-tags and astro/valid-compile.
eslint-plugin-svelte 3.22: adds no-bind-value-on-checkable-inputs and no-conflicting-module-names; no-restricted-html-elements is now off because its schema requires a user-supplied element list.
@angular-eslint/eslint-plugin 22.1: adds inject-at-top and prefer-service-decorator.
b81578b: Fix the useSortedPackageJson action not being executed by turning on assist actions for package.json-like files.
9ec454a: Update oxlint to 1.76.0 and oxfmt to 0.61.0. New stable rules added to the presets: oxc/bad-match-all-arg, id-denylist, node/exports-style (core), react/function-component-definition with arrow-function components (react), and vitest/padding-around-test-blocks (vitest). node/no-top-level-await is off — top-level await is idiomatic in ESM, Astro frontmatter, and build scripts — and the ESLint preset's n/no-top-level-await is now off to match. No rules were removed or promoted out of nursery.
ba61c02: Fix generated oxlint.config.ts accessing plugin.name on ExternalPluginEntry without narrowing the string form, which caused a TypeScript error in projects that type-check the config (#753)
f480c12: Upgrade Biome to 2.5.3 to fix the LSP scanner deadlock (#10845) where editors get stuck on "Biome is scanning the project".
1d70c40: Fail fast with an actionable message when Biome can't resolve ultracite/biome/core. Biome resolves that config out of the project's node_modules, so it errors with an opaque "module not found" whenever Ultracite isn't installed there — a state npx ultracite check / bunx ultracite check hide, because they run the CLI from a temp cache regardless. check and fix now detect it before invoking Biome and say what's actually wrong, and doctor verifies that Ultracite resolves rather than just appearing in package.json (#750).
38d10bc: Move Biome's noUnknownAttribute rule out of the core preset and into the react preset. The rule only recognises React's JSX attribute names, so projects using Solid, Svelte, Vue, or Qwik were incorrectly flagged for framework-standard attributes such as class.
cf723bd: Add interactive and non-interactive selection for optional Oxlint JS plugins during init.
dc6d760: Disable the n/no-unpublished-import rule in the ESLint core config. This rule flags imports of packages that aren't listed as published dependencies, but it produces a lot of false positives in practice, so it's now turned off.
15ecfba: Fix ultracite init --linter eslint installing an unusable toolchain. The generated ESLint config imports eslint-plugin-storybook unconditionally (which requires the storybook peer) and the generated Stylelint config extends stylelint-config-standard / stylelint-config-idiomatic-order / stylelint-prettier, but none of those packages were installed — so a fresh ESLint setup failed to load with "Cannot find package 'storybook'" or "Could not find stylelint-config-standard". These four packages are now installed with the ESLint linter.
2f73a41: Upgrade to oxlint 1.73.0 and oxfmt 0.58.0, and enable the new lint rules they introduce: no-unreachable-loop, unicorn/explicit-timer-delay, and unicorn/no-confusing-array-with.
83b2783: Add an [astro] formatter mapping (astro-build.astro-vscode) to the oxlint VS Code editor settings generated by ultracite init, since oxfmt doesn't format .astro files.
d186c53: Move every JS-plugin-based rule set out of the Oxlint core and framework presets and into a single opt-in ultracite/oxlint/js-plugins preset. This covers eslint-plugin-github and eslint-plugin-sonarjs (previously in core) as well as oxlint-plugin-react-doctor (previously bundled into the react, next, and tanstack presets). The core, react, next, and tanstack presets now run entirely on Oxlint's native Rust rules, so new setups no longer install those dependencies and no longer pay the slower JS-plugin lint pass. To keep the extra ESLint-parity and React Doctor rules, install eslint-plugin-github, eslint-plugin-sonarjs, and oxlint-plugin-react-doctor and extend ultracite/oxlint/js-plugins alongside core (and your framework preset).
057753e: Add performance benchmarks for ultracite check / ultracite fix across all three providers (oxlint, biome, eslint). A new CI job builds the PR and its base branch on the same runner, benchmarks them interleaved, and fails on a statistically significant regression (median ratio > 1.25x with Mann-Whitney U p < 0.05) so config changes can't silently slow the linters down again.
c335a1f: Add **/node_modules and **/.git to the shared ignore patterns. oxlint only skips node_modules when a .gitignore lists it, so in projects without one, ultracite fix would lint and autofix files inside node_modules — corrupting installed packages (e.g. rewriting var enum wrappers in typescript/lib/typescript.js to self-referencing const, causing "Cannot access 'Comparison' before initialization" when oxlint loads eslint-plugin-sonarjs). Fixes #737.
ecd10cc: Disable sonarjs/no-implicit-dependencies and github/no-implicit-buggy-globals in the oxlint and ESLint presets. Both produce false positives through oxlint's JS plugin bridge: no-implicit-dependencies has no dependency-manifest resolution so it flags builtin (bun:test) and workspace imports as missing dependencies, and no-implicit-buggy-globals misreads module-scoped declarations such as Astro frontmatter as implicit globals.
c76f59d: Disable sonarjs/file-name-differ-from-class in the oxlint and ESLint presets. It fires on any file whose name differs from an exported class, which is noise for the many config and module files that export objects rather than classes.
29e30ce: Fold the github and sonarjs rules into the oxlint core preset. The standalone ultracite/oxlint/github and ultracite/oxlint/sonarjs presets are removed — ultracite ships framework presets, not individual plugins. Their rules now live in ultracite/oxlint/core, so every oxlint setup gets eslint-plugin-github and eslint-plugin-sonarjs through oxlint's JS plugin bridge, matching how the ESLint preset already bundles them into core.
This is a breaking change to generated configs: ultracite/oxlint/github and ultracite/oxlint/sonarjs no longer exist. Re-run ultracite init to regenerate oxlint.config.ts.
Also fixed: nine sonarjs rules (async-test-assertions, hooks-before-test-cases, no-duplicate-test-title, no-empty-test-title, no-floating-point-equality, no-forced-browser-interaction, no-trivial-assertions, prefer-specific-assertions, super-linear-regex) that exist in eslint-plugin-sonarjs but that oxlint's JS plugin bridge does not register. Naming them made oxlint hard-fail config parsing, which broke ultracite fix/check for oxlint projects using the sonarjs preset. They are omitted from oxlint core (still enabled in the ESLint preset), and a test now runs oxlint against core to catch this class of regression.
The React Doctor, github, and sonarjs plugins are installed into your project's devDependencies at init (as the ESLint plugins already were), rather than bundled as dependencies of ultracite — oxlint resolves JS plugin specifiers from the project root, so they must be installed there directly.
8a4291f: Upgrade to Oxlint 1.72.0 and Oxfmt 0.57.0. Oxfmt 0.57 adds native CSS and GraphQL formatters. The five new non-nursery Oxlint rules from the 1.71/1.72 releases are already covered by the presets (node/no-sync, node/no-mixed-requires, unicorn/prefer-number-coercion, unicorn/max-nested-calls, vue/no-async-in-computed-properties). The markdown ::: container-directive fence patch (which keeps proseWrap: "never" from folding fences into prose) was regenerated against the 0.57 bundle.
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 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.
c863d09: Fix automatic editor extension installation during ultracite init.
The whole command line (e.g. code --install-extension) was passed to spawnSync as the executable name, which always failed with ENOENT and
silently fell back to the "install manually" message. The command is now split
into the binary and its arguments, so the linter extension actually installs
for VS Code-based editors.
6888129: Enable the eslint/no-await-in-loop rule as an error in the core Oxlint
preset.
Awaiting inside a loop forces each iteration to run sequentially, which can
lead to serious performance issues when the asynchronous operations could
otherwise run concurrently. Promoting this rule to an error encourages
collecting promises and resolving them together (e.g. with Promise.all)
instead of blocking on each one in turn.
62a9b5c: Fix the generated Husky pre-commit hook's error handling and section
replacement.
The standalone hook script set set -e and then tried to capture the
formatter's exit code, re-stage files, and print a failure message — but a
non-zero formatter exit terminated the script immediately, so none of that
ever ran. The script now captures the exit code with || FORMAT_EXIT_CODE=$?
so files are re-staged and failures are reported with the right exit code.
Re-running ultracite init also deleted everything from the # ultracite
marker to the end of the hook, including commands the user added after the
ultracite section. The section is now terminated with an explicit # ultracite end marker and updates replace only the section between the
markers (legacy sections without an end marker are detected by their closing
echo line).
6608ceb: Make the lint-staged integration idempotent and respect dedicated config
files.
package.json was always treated as the lint-staged config because the file
exists in every project, so ultracite init wrote the lint-staged config into package.json even when a dedicated .lintstagedrc.* or lint-staged.config.* file was present — leaving two conflicting configs. package.json now only counts when it actually has a lint-staged key;
otherwise the dedicated config file is updated (or .lintstagedrc.json is
created).
Re-running ultracite init also appended another npx ultracite fix entry on
every run because the merge concatenates arrays. Updates are now skipped when
the existing config already references ultracite.
4e847f7: Insert -- before script arguments in npm hook commands.
The post-edit hook command generated for npm projects was npm run fix --skip=correctness/noUnusedImports, where npm consumes the --skip flag itself instead of forwarding it to the script — so agent hooks
ran a plain ultracite fix, including the unused-import removal the flag
exists to prevent mid-edit. The generated command is now npm run fix -- --skip=correctness/noUnusedImports, matching the documented
form.
ecb0d5b: Scope the Stylelint step of ultracite check and ultracite fix (ESLint mode)
to style files.
Stylelint was previously given the same targets as ESLint and Prettier (or .
when no files were passed), so it tried to parse .ts/.json files as CSS and
failed with CssSyntaxError. Style files now pass through unchanged, directory
targets become **/*.{css,scss,sass,less} globs, other files are dropped, and
the step is skipped entirely when no style targets remain. --allow-empty-input is passed so projects without CSS still succeed.
61ea0a1: Fix the project-path write guard's error message and ordering.
The "Refusing to write through directory outside project" error interpolated
the node:path module instead of the offending file path, printing [object Object]. It now reports the actual path.
writeProjectFile also created directories (mkdir -p) before running the
path-escape check, so directories could be created outside the project before
the guard threw. Validation now happens first; the parent-directory check
resolves the nearest existing ancestor so writes into not-yet-created nested
directories still work.
30971a8: Enable newly available Oxlint and Stylelint rules in the shared configs.
For Oxlint, the core preset now enables eslint/prefer-named-capture-group, jsdoc/require-yields-description, node/callback-return, typescript/method-signature-style, and unicorn/import-style.
The Vue preset now enables vue/component-definition-name-casing, vue/no-computed-properties-in-data, vue/no-deprecated-props-default-this, vue/no-expose-after-await, vue/no-reserved-component-names, vue/no-shared-component-data, vue/no-watch-after-await, vue/require-prop-type-constructor, vue/require-render-return, vue/require-slots-as-functions, vue/return-in-emits-validator, vue/valid-define-options, and vue/valid-next-tick.
The Stylelint preset now enables display-notation with the short option.
8335be7: Build the CLI with bun build and a tsgo type-check gate instead of tsup.
f747449: Fix the Oxlint TanStack preset so route files under routes/ and app/routes/ are exempt from unicorn/filename-case, matching the documented 7.8.0 behavior.
092597e: Fix generated oxlint.config.ts to be pre-formatted according to oxfmt rules, so ultracite check passes immediately after ultracite init without requiring a separate format step.
81da6e8: Generate agent and editor hook commands through nypm's package-manager script helper.
81da6e8: Keep hyphen-prefixed file operands from being forwarded to linters as options.
The executables in our macOS and Windows release archives and uv and uv_build wheels are now code-signed. macOS executables are signed with an Apple Developer ID certificate and notarized by Apple. Windows executables have timestamped Authenticode signatures from Azure Artifact Signing. This enables verification of the release publisher and binary integrity, supports publisher-based allowlisting, and should reduce security warnings and antivirus false positives.
Bug fixes
Exclude distributions uploaded after the exclude-newer cutoff from lockfiles and generated requirement hashes (#21539)
Generate missing artifact hashes when exporting pylock.toml files to ensure they conform to PEP 751 (#20146)
Warn when pylock.toml artifact hash tables are empty, which will be rejected in a future uv release (#21462)
Performance
Speed up installs that overwrite existing files by eliminating per-file temporary directories for atomic hard-link, symlink, and reflink replacements (#21478)
Speed up installs that merge copied wheels into existing environments by replacing per-file temporary directories with adjacent temporary files (#21468)
Speed up local wheel installs by replacing the shared ZIP cursor lock with positioned reads (#21500)
Speed up local wheel installs by reusing ZIP readers and buffers across extracted files (#21499)
Avoid transitive dependency checks and unnecessary resolution when uv pip install --no-deps finds the requested packages already installed (#21523)
Bug fixes
Verify source archives against hashes recorded in uv.lock before reading their metadata or running their build backends (#21223)
Verify supplied hashes for registry requirements pinned with === under both --verify-hashes and --require-hashes (#21543)
Apply hashes from public-version pins to matching local versions when no exact local-version hash is provided (#21544)
Support PowerShell virtual environment activation from UNC paths, including WSL paths (#19159)
Trim surrounding whitespace from entries in .python-version and .python-versions files (#21529)
Suppress VIRTUAL_ENV mismatch warnings for uv add --no-sync, uv remove --no-sync, and uv add --frozen (#21496)
Warn and continue when uv python list cannot query an interpreter (#21498)
Documentation
Restore TOML syntax highlighting for exclude-newer examples (#21534)
Attempt to revoke short-lived PyPI trusted-publishing tokens after uv publish completes, including when publishing fails (#21423)
Preview features
Omit exclude-newer-package settings for packages outside the resolution from uv.lock with the missing-exclude-newer-package-lock preview feature (#21455)
Show terminal dependency cycles in uv tree --invert output (#21404)
Performance
Speed up locking large workspaces with conflicts by excluding unrelated extras and dependency groups from conflict simplification (#21399)
Speed up uv publish by hashing each artifact in a single blocking task and reusing the buffer across reads (#21389)
Bug fixes
Prevent --locked from failing when exclude-newer-package settings differ only for packages outside the resolution (#21454)
Allow uv lock --check to reuse a lockfile when an absolute exclude-newer cutoff is moved later (#19571)
Allow uv lock --check to reuse a lockfile when a package-specific exclude-newer cutoff is disabled (#21450)
Require an explicit --name when uv init would infer a project name reserved for a Python interpreter (#21395)
Write package-specific exclude-newer cutoffs to uv.lock in a deterministic order (#21453)
Warn about invalid tool directories and continue upgrading valid tools with uv tool upgrade --all (#21368)
Preview features
Deduplicate identical files within and across cached wheels with the content-addressed-cache preview feature (#21327)
Reduce allocations while extracting content-addressed wheels by reusing the hashing buffer across files (#21340)
Speed up content-addressed cache cleanup on macOS by reading hard-link counts in bulk (#21344)
Performance
Prevent concurrent uv processes from downloading and extracting the same remote wheel more than once (#21379)
Speed up dependency graph construction from large lockfiles by indexing packages during traversal (#21373)
Extend indexed lockfile traversal to exports, dependency trees, audits, and freshness checks (#21377)
Speed up warm resolutions by reducing repeated marker interner work (#21300)
Bug fixes
Do not trust hashes from direct URLs discovered only in wheel metadata when installing with --require-hashes (#21348)
Use a compatible Azure Storage API version for anonymous and authenticated requests, allowing credential retries when public access is disabled (#21366)
This release fixes a regression in 0.12.14 that lead to rejecting valid installation commands such as using uv pip install --system in python:* docker images or when using uv pip install --target .. (#21699)
Performance
Speed up cold-cache resolution and HTTP cache revalidation by batching cache writes (#21675)
Since we released uv 0.11.0 in March, we've accumulated changes that improve correctness, safety, and compatibility with specifications, but could break some workflows. This release contains those changes; many have been marked as breaking out of an abundance of caution.
We expect most users to be able to upgrade without making changes.
There are no breaking changes to the configuration of the uv build backend. If your [build-system] table includes an upper bound on uv_build, update it to allow uv_build 0.12, e.g., uv_build>=0.11.32,<0.13.
Breaking changes
Define build systems by default with uv init (#19197)
Projects created with uv init now declare a build system and are packaged by default. This was the default project layout all the way back in v0.3, but we found that the use of the hatchling build system was confusing to newcomers and consequently dropped use of a build system by default in v0.4. Since then, we've created our own build system (uv_build) with tight integration with uv and are excited to restore the default to a best-practice project layout.
Previously, uv init example created an unpackaged layout containing main.py and a pyproject.toml without a build system. The project could declare dependencies but was not itself installed into its virtual environment.
Now, uv init example defines a [build-system] using uv_build, places application source code in src/example, and includes a [project.scripts] entry named example. Defining a build system allows the project to be imported from tests or other code, installed as a dependency, and run as a command:
$ uv init example
$cd example
$ uv run example
Hello from example!
Existing projects are unaffected. Use uv init --no-package example to create the previous unpackaged layout without a build system.
This stabilizes the packaged-init preview feature.
Reject unsupported source distribution and wheel archive formats (#18927)
PEP 625 requires source distributions to use .tar.gz archives. Previously, uv also accepted legacy formats such as .tar.bz2 and .tar.xz. Those formats are now rejected, including when referenced by an existing lockfile. Legacy .zip source distributions remain supported for backwards compatibility.
Wheels and other ZIP archives can no longer contain entries compressed with bzip2, LZMA, or XZ. Entries must use the stored, DEFLATE, or zstd compression methods.
Removing support for uncommon compression methods reduces uv's compression dependencies and the attack surface exposed when processing untrusted packages.
You cannot opt out of this behavior. If you depend on a legacy source distribution that uses an unsupported format, we recommend rebuilding it as a .tar.gz archive and regenerating any lockfile containing references to the legacy archive.
Reject wheel files that could replace the Python interpreter (#20748, #20749)
uv already rejected wheel entry points named python, but case variants such as Python were still accepted. On case-insensitive filesystems, including common macOS and Windows setups, these entry points could overwrite the virtual environment's interpreter.
Wheels could also place interpreter files in their .data/scripts directory or in paths such as .data/data/bin/python, bypassing the entry-point check and replacing the interpreter during installation.
uv now rejects case-insensitive variants of reserved interpreter names and wheel data files that would be installed over an interpreter. This includes names such as Python, python.py, and Python.exe, along with other reserved interpreter names and their versioned variants.
You cannot opt out of these checks. Rename conflicting entry points or wheel data files and rebuild the affected wheel.
Prefer stable releases before falling back to pre-releases (#19993)
A dependency can introduce a pre-release requirement after resolution starts. uv previously required each package's pre-release eligibility to be known before resolution began: the default if-necessary-or-explicit mode allowed them for direct requirements that explicitly requested a pre-release, or for packages that only published pre-releases.
This meant that a pre-release requirement discovered in a dependency's metadata, e.g., example>=2.0.0b1, would fail to resolve even when a compatible pre-release existed. To resolve it, you had to add that dependency as a direct requirement or allow pre-releases across your entire dependency graph.
The default mode is now if-necessary. uv tries stable candidates first and falls back to pre-releases when no stable candidate satisfies the active constraints. Like pip, uv now supports pre-release requirements discovered transitively, but can select different versions than previous uv releases when both stable and pre-release candidates are available.
You can opt out of automatic pre-release selection with --prerelease disallow. Alternatively, --prerelease allow considers pre-releases without first preferring stable releases, and --prerelease explicit only allows them for direct requirements that mention a pre-release.
The old if-necessary-or-explicit mode distinguished between explicitly requested pre-releases and packages with no stable releases. That distinction is unnecessary now that if-necessary handles both cases, including transitive requirements. The old name remains available as an alias but is deprecated and will be removed in a future release.
Respect --require-hashes directives in requirements.txt (#19336)
Previously, uv pip install and uv pip sync warned about --require-hashes inside a requirements.txt file but still installed dependencies without checking their hashes. Now, the directive enables hash-checking mode, just as if --require-hashes had been passed on the command line.
For example, this requirements file is no longer accepted because the requirement is neither pinned nor hashed:
--require-hashes
anyio
You cannot opt out while the directive is present. Pin every requirement with == and provide its hash, or remove --require-hashes if hash checking is not intended.
Reject MD5-only hashes in hash-checking mode (#20758)
Previously, uv pip install --require-hashes and uv pip sync --require-hashes accepted requirements whose only available digest used MD5. MD5 is not collision-resistant, so relying on it undermined installations that require hash verification and differed from pip's behavior.
Hash-checking mode now requires at least one secure digest for every requirement. For example, the following requirement is rejected unless a secure hash, such as SHA-256, is also supplied:
A secure hash can be supplied directly on the requirement or in a matching constraints file. Ordinary hash verification without --require-hashes continues to support MD5.
You cannot opt out while hash checking is required. Regenerate affected hashes with SHA-256 or another supported secure hash.
The packages array must be present. Previously, uv interpreted a missing array as an empty lockfile, so uv pip sync could uninstall an environment instead of rejecting malformed input. An explicitly empty packages = [] array remains valid.
Lockfile filenames must be pylock.toml or a single-name variant such as pylock.dev.toml. Names such as pylock..toml and pylock.foo.bar.toml are rejected.
If a wheel, source distribution, or other artifact declares a size, the downloaded or cached artifact must match. Previously, an incorrect size was accepted when the hash was correct. Sizes reported by package indexes remain advisory.
You cannot opt out of these checks. Regenerate malformed lockfiles, rename invalid filenames, and either correct or remove an incorrect optional size value.
Honor explicit certificate overrides even when no certificates can be loaded (#20741, #20767)
Previously, uv ignored SSL_CERT_FILE or SSL_CERT_DIR values that pointed to missing or inaccessible paths, empty files or directories, or sources without valid certificates. Instead, it fell back to its default trust roots, potentially allowing HTTPS connections that the configured override was intended to reject.
Now, any non-empty SSL_CERT_FILE or SSL_CERT_DIR value replaces uv's default certificate roots, even when no valid certificates can be loaded. In that case, HTTPS requests fail because no certificates are trusted. This applies to package downloads and remote scripts, including GitHub Gists.
Fix or unset the certificate override. Unsetting it restores the default trust store; empty environment-variable values continue to be ignored.
Support pip-compatible --cert handling in uv pip (#20418)
The uv pip interface now accepts --cert <path>, e.g.:
$ uv pip install --cert ./company-ca.pem example
As in pip, the provided PEM bundle replaces all other certificate sources for that invocation, including system certificates and SSL_CERT_FILE or SSL_CERT_DIR. This change has no effect unless you pass --cert. Include the necessary certificate authorities in the bundle.
--cert is only supported by uv pip commands; other uv commands continue to use their existing certificate configuration.
Discover projects relative to the script passed to uv run (#20225)
Previously, uv run project/script.py discovered its project from the current directory, even when the script belonged to another project. uv now starts project and workspace discovery from the script's directory instead.
For example, running uv run other-project/script.py now uses other-project and its dependencies. This fixes scripts that previously failed because their own dependencies were not installed, but can select a different environment than before.
You can opt out of script-relative discovery by selecting a project explicitly, e.g., uv run --project . other-project/script.py.
This stabilizes the target-workspace-discovery preview feature.
Require --force before clearing a directory that is not a virtual environment (#20225)
uv venv --clear previously removed any existing target directory, even if it was not a virtual environment. uv emitted a warning but still deleted the directory and its contents. Now, uv refuses to clear directories that do not contain a virtual environment.
You can opt out of this safety check by explicitly passing --force, e.g., uv venv --clear --force ./not-a-virtualenv.
This stabilizes the venv-safe-clear preview feature.
Reject --project when initializing a project (#20225)
--project selects an existing project, so it is not meaningful when initializing a new one. Previously, uv init --project example warned and initialized example anyway; if a positional path was also provided, --project was ignored.
This usage is now an error. Use uv init example to initialize a project at the requested path, or uv init --directory example to change the working directory first.
This stabilizes the init-project-flag preview feature.
Reject missing or invalid --project paths (#20225)
uv previously warned when --project referred to a missing directory or a file other than pyproject.toml, but then attempted to continue. This could produce confusing errors later or run against an unintended project.
Now, uv run --project missing python fails immediately instead of continuing. You cannot opt out of this behavior. Create the directory first or select an existing project. Passing --project path/to/pyproject.toml remains supported and selects the file's parent directory.
This stabilizes the project-directory-must-exist preview feature.
Skip distributions with non-normalized filenames when publishing (#20225)
Distribution filenames must use normalized package names and versions. For example, a wheel for version 1.01.0 should be named example-1.1.0-py3-none-any.whl, not example-1.01.0-py3-none-any.whl.
Previously, uv publish warned about non-normalized filenames but still attempted to upload them. It now skips the affected wheels and source distributions instead.
You cannot opt out of this behavior. Rebuild distributions with normalized filenames before publishing.
This stabilizes the publish-require-normalized preview feature.
Classify Conda environments named base and root by their paths (#20225)
Conda environments named base or root were previously assumed to be the base Conda environment, even when they were ordinary child environments. uv now recognizes child Conda environments named base or root based on their paths, as it already does for other names.
You can opt out of automatic interpreter selection by requesting an interpreter explicitly with --python /path/to/python.
This stabilizes the special-conda-env-names preview feature.
Reject broken .venv symlinks during environment discovery (#20433)
Previously, uv could ignore a broken .venv symlink and continue searching parent directories for another virtual environment. As a result, commands such as uv pip install could unexpectedly modify an unrelated ancestor environment.
uv now stops at a broken .venv symlink and reports its exact path. Errors encountered while reading virtual environment metadata, including permission failures, are also reported immediately instead of being ignored.
You cannot opt out of this behavior. Repair or remove the broken .venv symlink and correct any permissions that prevent uv from inspecting the environment.
Before Python upgrades were supported, uv python install 3.12 --reinstall doubled as a way to install the latest Python 3.12 patch release. Now that --upgrade is available, --reinstall reinstalls the matching patch releases that are already present.
For example, if Python 3.12.6 and 3.12.7 are installed, uv python install 3.12 --reinstall reinstalls both versions instead of installing the latest available 3.12 release.
You can recover the previous upgrade behavior with uv python install 3.12 --upgrade. Combine --upgrade --reinstall to reinstall only the latest patch.
Require --upgrade-group to name an existing dependency group (#18957)
Previously, uv lock --upgrade-group docs silently succeeded even if no docsdependency group existed. uv now validates the requested group against the project, its workspace members, and workspace-level dependency groups.
You cannot opt out of this behavior. Correct the group name or add it to [dependency-groups]. Legacy tool.uv.dev-dependencies still satisfies --upgrade-group dev.
Resolve relative indexes and find-links against --directory (#20740)
The --directory option changes the directory in which uv operates. Previously, relative index and find-links paths supplied on the command line were still resolved against the original working directory.
uv now resolves --index, --default-index, --index-url, --extra-index-url, and --find-links relative to the directory selected by --directory. For example:
$ uv add --directory project --index ./packages example
This now uses project/packages instead of ./packages in the original working directory. Absolute paths and indexes loaded from configuration files are unaffected.
To preserve the previous target, pass an absolute path or adjust the relative path, e.g., --index ../packages.
Preserve absolute paths provided to uv add (#18402)
uv add previously converted every local dependency into a project-relative path, even when the original request used an absolute path or a literal file:// URL. It now preserves the form of the request in pyproject.toml and uv.lock:
Absolute paths make a project less portable. Use a relative path to avoid recording an absolute path. URLs containing expanded variables retain their existing relative-path behavior.
Remove older PyPy distributions that are only available as bzip2 archives (#20423)
Older PyPy patch releases that are only distributed as .tar.bz2 archives are no longer available through uv python install. These releases require unsupported bzip2 archives.
The latest PyPy release for each supported Python minor version is available as a gzip-compressed archive and remains supported. For example, uv python list 3.10 --all-versions still includes the latest PyPy 3.10 release, but older bzip2-only patch releases are omitted.
You cannot opt out of this behavior. Request a newer PyPy patch release instead.
Omit excluded-package comments when annotations are disabled (#20085)
uv pip compile --no-annotate suppresses comments describing the generated requirements file. Previously, a footer listing packages excluded with --unsafe-package was still included, even though annotations were disabled. That footer is now omitted.
You can recover the footer by removing --no-annotate.
uv_build now writes a TOML 1.0-compatible pyproject.toml when building source distributions, allowing older Python build frontends to consume projects that use newer TOML syntax. The original project file remains available in the archive as pyproject.toml.orig.
This stabilizes the toml-backwards-compatibility preview feature.
Automatic open-file limit adjustment on Unix (#20225)
On Linux and macOS, uv now attempts to raise the soft open-file limit at startup toward the hard limit, capped at 1,048,576 descriptors. The new limit also applies to subprocesses and reduces failures caused by running out of file descriptors. If the limit cannot be raised, uv continues running with the existing limit.
This stabilizes the adjust-ulimit preview feature.
Preview features
Allow uv upgrade to target multiple packages, upgrade all production dependencies, and exclude selected dependencies (#20338)
Bug fixes
Include extras activated by dependency groups when evaluating conflicts (#20237)
Configuration
📅Schedule: (in timezone Europe/Warsaw)
Branch creation
At any time (no schedule defined)
Automerge
At any time (no schedule defined)
🚦Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
👻Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.
If you want to rebase/retry this PR, check this box
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | [`2.4.15` → `2.5.13`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.15/2.5.13) |  |  |
| [ultracite](https://www.ultracite.ai/) ([source](https://github.com/haydenbleasel/ultracite)) | [`7.8.0` → `7.11.1`](https://renovatebot.com/diffs/npm/ultracite/7.8.0/7.11.1) |  |  |
| [uv_build](https://pypi.org/project/uv/) ([source](https://github.com/astral-sh/uv), [changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)) | `>=0.11.14,<0.12.0` → `>=0.12.13,<0.13.0` |  |  |
---
### Release Notes
<details>
<summary>biomejs/biome (@​biomejs/biome)</summary>
### [`v2.5.13`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2513)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.12...@biomejs/biome@2.5.13)
##### Patch Changes
- [#​11379](https://github.com/biomejs/biome/pull/11379) [`07a0073`](https://github.com/biomejs/biome/commit/07a0073c1e1b1de323292968b8988cc6f79ec5c7) Thanks [@​Netail](https://github.com/Netail)! - Added the nursery rule [`useLayeredStyles`](https://biomejs.dev/linter/rules/use-layered-styles/), which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.
```css
/* Invalid */
@import 'foo.css';
.my-style {
color: red;
}
/* Valid */
@import 'foo.css' layer(base);
@layer base {
.my-style {
color: red;
}
}
```
- [#​11667](https://github.com/biomejs/biome/pull/11667) [`e997900`](https://github.com/biomejs/biome/commit/e997900c3eaf9d5efaf1ca12a067a962e1a04d0b) Thanks [@​devtechedge](https://github.com/devtechedge)! - Added the nursery rule [`useBetterDomTraversing`](https://biomejs.dev/linter/rules/use-better-dom-traversing), which prefers `.firstChild`, `.firstElementChild`, `.closest()`, and merged `.querySelector()` calls over positional DOM traversal.
```js
element.childNodes[0];
element.children[0];
element.parentElement.parentElement;
element.querySelector("a").querySelector("b");
```
- [#​11620](https://github.com/biomejs/biome/pull/11620) [`20e513a`](https://github.com/biomejs/biome/commit/20e513af6fb0127854f4eb5cb9edee0f20d1b543) Thanks [@​jakeleventhal](https://github.com/jakeleventhal)! - Fixed [#​11610](https://github.com/biomejs/biome/issues/11610), [#​11611](https://github.com/biomejs/biome/issues/11611), [#​11612](https://github.com/biomejs/biome/issues/11612), [#​11615](https://github.com/biomejs/biome/issues/11615), and [#​11616](https://github.com/biomejs/biome/issues/11616): Biome no longer fully infers an imported generic declaration just to apply its type arguments, restoring type-aware lint performance for large libraries such as Zod. This improves [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing), and [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands).
- [#​11657](https://github.com/biomejs/biome/pull/11657) [`e322040`](https://github.com/biomejs/biome/commit/e32204014687469e6c6f3684d32caf56311cc118) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7495](https://github.com/biomejs/biome/issues/7495): [`noUselessConstructor`](https://biomejs.dev/linter/rules/no-useless-constructor/) now ignores TypeScript constructors that forward at least one argument to `super`, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7076](https://github.com/biomejs/biome/issues/7076): [`useAriaPropsForRole`](https://biomejs.dev/linter/rules/use-aria-props-for-role) and [`useFocusableInteractive`](https://biomejs.dev/linter/rules/use-focusable-interactive) no longer report non-focusable elements with `role="separator"`. A separator with an explicit `tabIndex` or `tabindex` still requires `aria-valuenow`.
- [#​11627](https://github.com/biomejs/biome/pull/11627) [`23aad6d`](https://github.com/biomejs/biome/commit/23aad6df8f71bd9b134633c43d2334771687d10d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6571](https://github.com/biomejs/biome/issues/6571) so Grit plugins can capture and inspect multiple named import specifiers.
- [#​11631](https://github.com/biomejs/biome/pull/11631) [`00dbd3a`](https://github.com/biomejs/biome/commit/00dbd3a30489617d5bb55466006ac9977612a23b) Thanks [@​ematipico](https://github.com/ematipico)! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.
- [#​11628](https://github.com/biomejs/biome/pull/11628) [`a2f8ff7`](https://github.com/biomejs/biome/commit/a2f8ff7a1eb01f5c91e7154937e17f761863e3bc) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noXorAsExponentiation`](https://biomejs.dev/linter/rules/no-xor-as-exponentiation/), which reports the bitwise XOR operator `^` between two decimal integer literals, where the exponentiation operator `**` was likely intended.
```js
const kibibyte = 2 ^ 10; // 8, not 1024
```
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7192](https://github.com/biomejs/biome/issues/7192): [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) now considers compound assignments such as `??=` to read and use private class members.
- [#​11676](https://github.com/biomejs/biome/pull/11676) [`840a52a`](https://github.com/biomejs/biome/commit/840a52ad14b027e21661a9121b316ccac139d736) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11672](https://github.com/biomejs/biome/issues/11672) and [#​11671](https://github.com/biomejs/biome/issues/11671) by disabling the experimental capitalized-call and effect-dependency checks in [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/), matching their exclusion from upstream's recommended lint preset. Valid calls such as `Intl.NumberFormat()` and captures of variables declared inside effects no longer produce these diagnostics.
- [#​11660](https://github.com/biomejs/biome/pull/11660) [`49485ed`](https://github.com/biomejs/biome/commit/49485eda65813e5b7e2be68cdd56ffd90674f713) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11653](https://github.com/biomejs/biome/issues/11653): Astro template suppression comments (`{/* biome-ignore lint: reason */}`) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.
- [#​11664](https://github.com/biomejs/biome/pull/11664) [`9a73b9c`](https://github.com/biomejs/biome/commit/9a73b9cc4bb1000336dc25704546f4d63a9bb326) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/).
- [#​11661](https://github.com/biomejs/biome/pull/11661) [`5341b3f`](https://github.com/biomejs/biome/commit/5341b3fb9c7bae8ce2426d32e6e72aed9637a82f) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7479](https://github.com/biomejs/biome/issues/7479). [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now treats Unicode escapes in identifiers as the same binding as their decoded spelling.
- [#​11630](https://github.com/biomejs/biome/pull/11630) [`62e1fc5`](https://github.com/biomejs/biome/commit/62e1fc59621b6ab5c3988ae36b6591180e07d08f) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.
```diff
<span>
- {head.median - base.median >= 0 ? "+" : "−"}
- {formatMs(Math.abs(head.median - base.median))}
+ {head.median - base.median >= 0 ? "+" : "−"}{formatMs(Math.abs(head.median - base.median))}
</span>
```
- [#​11658](https://github.com/biomejs/biome/pull/11658) [`ed4bfa4`](https://github.com/biomejs/biome/commit/ed4bfa4a1de63241a7c3586ff12d7f990cf84303) Thanks [@​fredrikblau](https://github.com/fredrikblau)! - Fixed [#​11644](https://github.com/biomejs/biome/issues/11644): [`useHeadingContent`](https://biomejs.dev/linter/rules/use-heading-content/) no longer reports headings that render their text with a directive: `set:html` and `set:text` in Astro files, `v-html` and `v-text` in Vue files.
```astro
<h1 set:html={heading} />
<h2 set:text={heading}></h2>
```
```vue
<template>
<h1 v-html="heading"></h1>
<h2 v-text="heading"></h2>
</template>
```
- [#​11613](https://github.com/biomejs/biome/pull/11613) [`47d7383`](https://github.com/biomejs/biome/commit/47d7383d049b36ff8eaba50912176928143dd9e9) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the performance of Biome Formatter up to \~50% in some cases.
- [#​11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6974](https://github.com/biomejs/biome/issues/6974), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported TypeScript private constructor properties read through object destructuring from `this` as unused.
- [#​11618](https://github.com/biomejs/biome/pull/11618) [`21a10cf`](https://github.com/biomejs/biome/commit/21a10cfcac4db8044e8bff6b24d9b1e197c2b343) Thanks [@​siketyan](https://github.com/siketyan)! - Fixed [#​11605](https://github.com/biomejs/biome/issues/11605): Type inference now infers the type of an unannotated callback parameter from the signature of the function the callback is passed to, and honours explicit type arguments on call expressions. This improves type-aware analysis for [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/), [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/), [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/), [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands/), [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/), [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/), [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/), [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/), [`useDisposables`](https://biomejs.dev/linter/rules/use-disposables/), [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/), [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing/), [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/), and [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/). For example, `noFloatingPromises` can now detect Promises reached through such parameters:
```ts
interface Context {
doSomething(): Promise<void>;
}
declare function test(callback: (ctx: Context) => Promise<void>): void;
test(async (ctx) => {
ctx.doSomething(); // now reported as a floating promise
});
```
- [#​11698](https://github.com/biomejs/biome/pull/11698) [`b019982`](https://github.com/biomejs/biome/commit/b019982bfbf8a9db58bd16b1e5e1a241128540d4) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed parsing of unquoted CSS URLs beginning with `@` or `!`, such as `url(@/assets/icon.svg)` and `url(!font.woff2)`. Preserved escaped and non-ASCII whitespace in raw URLs during formatting.
```diff
-background-image: url(image\);
+background-image: url(image\ );
```
- [#​11622](https://github.com/biomejs/biome/pull/11622) [`c23e4c7`](https://github.com/biomejs/biome/commit/c23e4c7e7a33d3f00863d80be663678af8c2a073) Thanks [@​Netail](https://github.com/Netail)! - Added the nursery rule [`noUnsafeIframeSandbox`](https://biomejs.dev/linter/rules/no-unsafe-iframe-sandbox/), which reports `iframe` elements whose `sandbox` attribute combines `allow-scripts` and `allow-same-origin`, since that combination lets the embedded document remove its own sandboxing.
```jsx
<iframe src="https://example.com" sandbox="allow-scripts allow-same-origin" />
```
- [#​11606](https://github.com/biomejs/biome/pull/11606) [`de0528f`](https://github.com/biomejs/biome/commit/de0528f940ea41b798816e1923b2b51ffcd0b473) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended [`noSvelteAtHtmlTags`](https://biomejs.dev/linter/rules/no-svelte-at-html-tags) nursery rule, which reports Svelte `{@html}` tags that render unescaped HTML.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6782](https://github.com/biomejs/biome/issues/6782): GritQL plugins now match captured JSX component names against code snippets such as `React.Fragment`.
- [#​11687](https://github.com/biomejs/biome/pull/11687) [`09d97d9`](https://github.com/biomejs/biome/commit/09d97d973b522c6bd95e6d26006cb4b3a221396d) Thanks [@​hori-design](https://github.com/hori-design)! - Fixed [#​11678](https://github.com/biomejs/biome/issues/11678): [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) no longer panics on files that contain non-ASCII characters. This bumps the React Compiler version.
- [#​11595](https://github.com/biomejs/biome/pull/11595) [`a64d757`](https://github.com/biomejs/biome/commit/a64d7572d5684f3555be5dc02eb1d29a16f290dc) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery Vue-domain rule [`useVueBaseImport`](https://biomejs.dev/linter/rules/use-vue-base-import/) rule, which enforces importing Vue APIs from `vue` instead of internal `@vue/*` packages.
- [#​11675](https://github.com/biomejs/biome/pull/11675) [`353cbae`](https://github.com/biomejs/biome/commit/353cbae47056f8e03b27d1d9b69e165b5b72f122) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) silently producing no diagnostics in WebAssembly builds, including the playground.
- [#​11625](https://github.com/biomejs/biome/pull/11625) [`ea20e5a`](https://github.com/biomejs/biome/commit/ea20e5a4640b4455cd12e0eb6ffaa590803c67a2) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Improved linting performance for large CSS and JSON files.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7527](https://github.com/biomejs/biome/issues/7527): suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressing [`noTsIgnore`](https://biomejs.dev/linter/rules/no-ts-ignore/) now places the `biome-ignore` comment before `@ts-ignore`.
- [#​11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​8629](https://github.com/biomejs/biome/issues/8629), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported used private TypeScript method overload signatures as unused.
- [#​11669](https://github.com/biomejs/biome/pull/11669) [`579f401`](https://github.com/biomejs/biome/commit/579f401b0a97760db99d64b97b2bc29ab20e3f8a) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Improved the performance of [`noExcessiveLinesPerFile`](https://biomejs.dev/linter/rules/no-excessive-lines-per-file/) when `skipBlankLines` is `false`.
### [`v2.5.12`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2512)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.11...@biomejs/biome@2.5.12)
##### Patch Changes
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro attribute expressions rejecting TypeScript and JSX syntax that is accepted in text expressions.
```astro
<Component icon={<Icon />} count={total as number} onSelect={(e: Event) => e} />
```
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro attribute names being split on `:` and `.` inside an expression, such as `{x && <button x-on:keyup.enter={go} client:load.foo />}`.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed a bare `>` in the children of an Astro expression being treated as markup, such as `{x && <div>a > b</div>}`.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed HTML comments inside an Astro expression failing to parse. They are now read as trivia, wherever they appear among the children.
```astro
{x && <div><!-- first -->text<!-- last --></div>}
{cond && <a></a><!-- c --><b></b>}
```
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed `is:raw` children inside an Astro expression being read as JSX, such as `{x && <div is:raw>{not js} < & text</div>}`.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed an apostrophe or quote in the text of a JSX element inside an Astro expression ending the expression early, such as `{items.map((i) => <li>it's {i}</li>)}`.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed the children of a `<script>` or `<style>` inside an Astro expression being read as JSX. Their contents are text, so braces and comparisons no longer have to be escaped.
```astro
{cond && <style>a { color: red }</style>}
{cond && <script>let x = {a: 1};</script>}
```
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Added support for template literal attribute values inside an Astro expression, such as ``{x && <C data-x=`t${x}` />}``.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed unquoted attribute values being rejected inside an Astro expression, such as `{x && <a class=foo maxlength=255 href=/about>go</a>}`.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed a template literal nested inside `${}` breaking the rest of an Astro file, such as ``const href = `/blog${page === 0 ? '' : `/${page + 1}`}`;``.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed a quote inside a regex character class breaking the rest of an Astro file, such as `const unsafe = /[/"]/;`.
- [#​11508](https://github.com/biomejs/biome/pull/11508) [`54f3a2e`](https://github.com/biomejs/biome/commit/54f3a2ea2765c80df11d04e47cd8da0354f5f7ca) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useFlatMathMinMax`](https://biomejs.dev/linter/rules/use-flat-math-min-max/). Because `Math.min()` and `Math.max()` accept any number of arguments, the rule reports unnecessary nested calls to the same method:
```js
Math.max(Math.max(a, b), c);
```
The fix flattens this expression to `Math.max(a, b, c)`.
- [#​11585](https://github.com/biomejs/biome/pull/11585) [`c5c8315`](https://github.com/biomejs/biome/commit/c5c8315cc2174b52834513d4c01edd09341e46cd) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​11475](https://github.com/biomejs/biome/issues/11475): `noUnresolvedImports` no longer reports Bun runtime built-in modules (`bun`, `bun:bundle`, `bun:ffi`, `bun:jsc`, `bun:sqlite`, `bun:test`).
- [#​11368](https://github.com/biomejs/biome/pull/11368) [`52a57b3`](https://github.com/biomejs/biome/commit/52a57b374af947ffcba11f0dd97b3cb9676ce044) Thanks [@​Austin1serb](https://github.com/Austin1serb)! - Fixed [#​6830](https://github.com/biomejs/biome/issues/6830): Biome now reports a diagnostic for excessively deep syntax instead of overflowing the native stack while releasing the parsed tree.
- [#​11596](https://github.com/biomejs/biome/pull/11596) [`1fc42ed`](https://github.com/biomejs/biome/commit/1fc42ed80a00e3ca86d44de8e1f66707061eb862) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noThisOutsideOfClass`](https://biomejs.dev/linter/rules/no-this-outside-of-class/). The rule reports `this` outside class members and TypeScript functions with an explicit `this` parameter.
```js
function Person(name) {
this.name = name;
}
```
- [#​11555](https://github.com/biomejs/biome/pull/11555) [`2516335`](https://github.com/biomejs/biome/commit/25163350c44aee821d3aeac5b20569cd37d1ae31) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11529](https://github.com/biomejs/biome/issues/11529), where [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) missed unhandled Promise chains when the imported function's module belonged to an import cycle. Cyclic modules now preserve types for exports that do not participate in recursive type dependencies.
- [#​11518](https://github.com/biomejs/biome/pull/11518) [`0fee70c`](https://github.com/biomejs/biome/commit/0fee70c6420140d62e9e9507ff3eda735077691b) Thanks [@​HarperZ9](https://github.com/HarperZ9)! - Fixed [#​11500](https://github.com/biomejs/biome/issues/11500): the formatter now prints the `declare` modifier before accessibility modifiers on class properties. `private declare readonly name: string` is now formatted as `declare private readonly name: string`, matching Prettier and TypeScript's canonical modifier order.
- [#​11580](https://github.com/biomejs/biome/pull/11580) [`1277af2`](https://github.com/biomejs/biome/commit/1277af285ff5ab2e7a4deb07b32855c9caa7b770) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​5091](https://github.com/biomejs/biome/issues/5091): Biome no longer moves comments next to the `<` of a generic, which causes invalid TypeScript syntax:
```diff
- Generic<// a comment
+ Generic<
+ // a comment
```
- [#​11577](https://github.com/biomejs/biome/pull/11577) [`42995d2`](https://github.com/biomejs/biome/commit/42995d2d19a937c44e9abbd400901bc6ec0dcaf5) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​4592](https://github.com/biomejs/biome/issues/4592). Biome no longer crashes while parsing malformed `delete` expressions.
- [#​11590](https://github.com/biomejs/biome/pull/11590) [`67963b4`](https://github.com/biomejs/biome/commit/67963b4085558e414bc48bddb82618b7cc6d8fdf) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6427](https://github.com/biomejs/biome/issues/6427) so Grit plugins can use `function = ...` as a node argument.
- [#​11600](https://github.com/biomejs/biome/pull/11600) [`a689cb5`](https://github.com/biomejs/biome/commit/a689cb5405885db94693e8ce39a22a53950cf2bf) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6644](https://github.com/biomejs/biome/issues/6644): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now recognizes all interface declarations in a TypeScript declaration-merging group when the interface is referenced.
The following snippet no longer triggers the rule.
```ts
interface Things {
foo: string;
}
interface Things {
bar: string;
}
export type Key = keyof Things;
interface Things {
baz: string;
}
```
- [#​11591](https://github.com/biomejs/biome/pull/11591) [`d4a0716`](https://github.com/biomejs/biome/commit/d4a07167df43309f424dc906fc5d0dc80b5e208d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6615](https://github.com/biomejs/biome/issues/6615). [`noDuplicateProperties`](https://biomejs.dev/linter/rules/no-duplicate-properties/) no longer reports declarations nested in block at-rules as duplicates of declarations in their parent block.
- [#​11492](https://github.com/biomejs/biome/pull/11492) [`f2a07aa`](https://github.com/biomejs/biome/commit/f2a07aadedd47034dccffd941935c71481b4c354) Thanks [@​santichausis](https://github.com/santichausis)! - Fixed [#​11454](https://github.com/biomejs/biome/issues/11454): [`noMisplacedAssertion`](https://biomejs.dev/linter/rules/no-misplaced-assertion/) now recognises `@fast-check/vitest`'s `test.prop(...)` (and `.concurrent.prop`, `.skip.prop`, etc.) as a test function, the same way it already recognises `test.each`. The JS formatter picks up the same recognition, so a curried `test.prop(...)(...)` call is now formatted with the regular breakable argument layout used for `test.each`/`test.for`, instead of the single-line-hugging layout used for plain `it`/`test` calls.
For example, Biome no longer reports the assertion below as misplaced:
```js
import { fc, test } from "@fast-check/vitest";
test.prop([fc.string()])("round-trips", (s) => {
expect(s).toBe(s);
});
```
- [#​11589](https://github.com/biomejs/biome/pull/11589) [`65742b3`](https://github.com/biomejs/biome/commit/65742b3658ab08aed31be6afdfbb4d8d5a737c47) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​4928](https://github.com/biomejs/biome/issues/4928): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports a value declaration as unused when its merged namespace is referenced.
- [#​11559](https://github.com/biomejs/biome/pull/11559) [`472dbc2`](https://github.com/biomejs/biome/commit/472dbc2c38ed1dbed6066fe26eac7ef97c79b05d) Thanks [@​levrik](https://github.com/levrik)! - Fixed a false positive in [`noVueDuplicateKeys`](https://biomejs.dev/linter/rules/no-vue-duplicate-keys/) where a `<script setup>` variable initialized from `props` was reported as a duplicate of the prop it derives from. Biome now exempts any variable whose initializer references `props`, instead of only recognizing `defineProps()` and `toRefs(props)`.
For example, Biome no longer reports `foo` below as a duplicate key:
```vue
<script setup>
import { toRef } from 'vue';
const props = defineProps(['foo']);
const foo = toRef(props, 'foo');
</script>
```
- [#​11594](https://github.com/biomejs/biome/pull/11594) [`6586ceb`](https://github.com/biomejs/biome/commit/6586cebec6182d37361ce42ca906ab190fd9a15b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6640](https://github.com/biomejs/biome/issues/6640). Biome no longer crashes when linting malformed `for...of` statements.
- [#​11571](https://github.com/biomejs/biome/pull/11571) [`85b197d`](https://github.com/biomejs/biome/commit/85b197da722fc8d07cd10b8fa7e1271652ed5e26) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10838](https://github.com/biomejs/biome/issues/10838): [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) no longer corrupts JSX attributes when nested JSX elements also require sorting.
- [#​11533](https://github.com/biomejs/biome/pull/11533) [`97e76c0`](https://github.com/biomejs/biome/commit/97e76c04cf19de45e63a22a9954c5077f45d4e6c) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11520](https://github.com/biomejs/biome/issues/11520), where the Biome scanner would start analysing dependencies multiple times, leading to long and unresponsive sessions.
- [#​11564](https://github.com/biomejs/biome/pull/11564) [`18a0e1f`](https://github.com/biomejs/biome/commit/18a0e1f058df3c8434d98d700eef5949695cb8f6) Thanks [@​Netail](https://github.com/Netail)! - Fixed the diagnostic range of [`noInferrableTypes`](https://biomejs.dev/linter/rules/no-inferrable-types/) so it now highlights only the type instead of including the leading `:` colon, spaces and comments.
- [#​11540](https://github.com/biomejs/biome/pull/11540) [`124fdaa`](https://github.com/biomejs/biome/commit/124fdaa1dad40a1e5d485da13ca51064b0a40adb) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`#11537`](https://github.com/biomejs/biome/issues/11537): [`noShorthandPropertyOverrides`](https://biomejs.dev/linter/rules/no-shorthand-property-overrides/) now compares declarations only within the same block. The rule no longer reports `@supports` feature queries and correctly checks nested, `@keyframes`, and `@page` blocks.
- [#​11532](https://github.com/biomejs/biome/pull/11532) [`7ceb0ee`](https://github.com/biomejs/biome/commit/7ceb0ee925461abd9afe17b12a09abc9c0b43c28) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11528](https://github.com/biomejs/biome/issues/11528): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports statement-level `await` expressions that handle Promise values, including overloaded calls returning Promise aliases. Awaited values that resolve to arrays of Promises remain reported because their element Promises are not handled by `await`.
- [#​11474](https://github.com/biomejs/biome/pull/11474) [`3c6412e`](https://github.com/biomejs/biome/commit/3c6412e7f44b9aaac750844f9a5f7ff7c3aa0feb) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10241](https://github.com/biomejs/biome/issues/10241). Biome no longer reports unsupported text expression diagnostics for double-curly text in vanilla HTML, and the formatter preserves adjacent curly-brace text.
- [#​11593](https://github.com/biomejs/biome/pull/11593) [`6c7fd27`](https://github.com/biomejs/biome/commit/6c7fd273848765547dba547e550fc319df7455a0) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noVueDeprecatedScopedSlots`](https://biomejs.dev/linter/rules/no-vue-deprecated-scoped-slots/). It reports deprecated `$scopedSlots` references in Vue templates and component objects, and offers an unsafe replacement with `$slots`. For example, Biome now reports `this.$scopedSlots.default` inside a Vue component.
- [#​11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed the formatter crashing on an Astro or Svelte expression spanning several lines in a file with CRLF line endings, such as `<p>{a +\r\n b}</p>`.
- [#​11581](https://github.com/biomejs/biome/pull/11581) [`f4e5ebb`](https://github.com/biomejs/biome/commit/f4e5ebb40e64d4488166bf0f2b7d8d96a6118016) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useModernMathApis`](https://biomejs.dev/linter/rules/use-modern-math-apis/). The rule reports legacy mathematical patterns that have direct modern `Math` equivalents.
```js
Math.sqrt(a * a + b * b);
```
- [#​11597](https://github.com/biomejs/biome/pull/11597) [`a20f44a`](https://github.com/biomejs/biome/commit/a20f44a3eb2086e65a6d8077eb89ab81f4d73130) Thanks [@​Netail](https://github.com/Netail)! - Added the nursery rule [`noBunModules`](https://biomejs.dev/linter/rules/no-bun-modules/), which forbids the use of Bun builtin modules (e.g. `bun:sqlite`, `bun:ffi`).
- [#​11545](https://github.com/biomejs/biome/pull/11545) [`7d54688`](https://github.com/biomejs/biome/commit/7d54688ee89244af3b287402295340d1d35ca96e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11542](https://github.com/biomejs/biome/issues/11542): Biome now reports HTML comments between Svelte tag attributes as parse errors.
- [#​11582](https://github.com/biomejs/biome/pull/11582) [`b6611dd`](https://github.com/biomejs/biome/commit/b6611dd5c1a54b80f181f4c0b5147a2c1c311dc9) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​3862](https://github.com/biomejs/biome/issues/3862). Biome now parses legacy Internet Explorer `filter` and `-ms-filter` values such as `progid:DXImageTransform...` and `alpha(opacity=40)`.
- [#​11575](https://github.com/biomejs/biome/pull/11575) [`65da251`](https://github.com/biomejs/biome/commit/65da251b0f4da0680f7ccb8820ba428344018848) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the Tailwind parser's ability to recover from parsing failures. Whitespace now always allows the parser to recover and start parsing a new class.
- [#​11576](https://github.com/biomejs/biome/pull/11576) [`0f78499`](https://github.com/biomejs/biome/commit/0f784998407970338481a1017279b9f17c43c61f) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​3515](https://github.com/biomejs/biome/issues/3515) and [#​10395](https://github.com/biomejs/biome/issues/10395), where Biome could corrupt Unicode characters while writing source received through standard input to standard output. Characters such as `⚠` and `✔` are now preserved.
- [#​11539](https://github.com/biomejs/biome/pull/11539) [`0fca643`](https://github.com/biomejs/biome/commit/0fca643d22845c28e0e0b7375013155e3f80717f) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11512](https://github.com/biomejs/biome/issues/11512), where [`style/noDescendingSpecificity`](https://biomejs.dev/linter/rules/no-descending-specificity/) missed lower-specificity selectors after a later higher-specificity selector with the same tail selector.
- [#​11544](https://github.com/biomejs/biome/pull/11544) [`040f867`](https://github.com/biomejs/biome/commit/040f86770cb830cd9ddaa827fd5b78fa16e7484c) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11541](https://github.com/biomejs/biome/issues/11541): formatting a Svelte render tag followed by an HTML comment no longer duplicates the comment.
```diff
<div>
{@render children?.()}
<!-- comment -->
- <!-- comment -->
</div>
```
- [#​11565](https://github.com/biomejs/biome/pull/11565) [`ee69e0e`](https://github.com/biomejs/biome/commit/ee69e0e8a90e6231a3b208cda4b3e65ad8b2006a) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11525](https://github.com/biomejs/biome/issues/11525). Now the configuration schema correctly provides auto-completion for linter domains.
- [#​11583](https://github.com/biomejs/biome/pull/11583) [`b19390c`](https://github.com/biomejs/biome/commit/b19390cb6ec276651365542387469c8b4634e0af) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11352](https://github.com/biomejs/biome/issues/11352): [`useExplicitLengthCheck`](https://biomejs.dev/linter/rules/use-explicit-length-check/) no longer reports `length`-like properties used as value-producing `||` fallbacks or optional chains, and it no longer offers fixes for value-producing `&&` checks or unsafe negations.
- [#​11562](https://github.com/biomejs/biome/pull/11562) [`753e955`](https://github.com/biomejs/biome/commit/753e955afe7bcb360506795fed25697828a59772) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where the Biome Language Server would start with logging level set to debug. This would cause logs to grow exponentially in long sessions.
- [#​11217](https://github.com/biomejs/biome/pull/11217) [`7d3ee9c`](https://github.com/biomejs/biome/commit/7d3ee9ccd5cf5df585ab3a17517a9514608a645a) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed handling of `biome-ignore format` suppression comments on TypeScript declared class properties with string literal names.
```ts
class A {
declare /* biome-ignore format: exercise suppression checking */ 'a-b': 0;
}
```
- [#​11497](https://github.com/biomejs/biome/pull/11497) [`f5d7896`](https://github.com/biomejs/biome/commit/f5d7896f7115a2d57962471f6d7abfafddb07918) Thanks [@​dyc3](https://github.com/dyc3)! - Added the [`noInvalidFileInputAccept`](https://biomejs.dev/linter/rules/no-invalid-file-input-accept/) nursery rule. The rule reports invalid literal `accept` values on file inputs in JSX and HTML, and normalizes common mistakes.
```jsx
<input type="file" accept="image/jpg" />
```
- [#​11345](https://github.com/biomejs/biome/pull/11345) [`ac58958`](https://github.com/biomejs/biome/commit/ac58958135d79e790f0edee8ec18aaa16f5d9849) Thanks [@​jakeleventhal](https://github.com/jakeleventhal)! - Improved type inference performance by avoiding resolution of unused members in object arguments.
- [#​11554](https://github.com/biomejs/biome/pull/11554) [`2d55931`](https://github.com/biomejs/biome/commit/2d559316e00764b0843d3d483d4a093fb566de57) Thanks [@​Netail](https://github.com/Netail)! - Added the new nursery rule [`useReactNamingConvention`](https://biomejs.dev/linter/rules/use-react-naming-convention/), which enforces naming conventions for React values assigned from `createContext`, `useId`, and `useRef`. A value from `createContext` must be a PascalCase component name ending with `Context`, a value from `useId` must be named `id` or end with `Id`, and a value from `useRef` must be named `ref` or end with `Ref`.
- [#​11491](https://github.com/biomejs/biome/pull/11491) [`1d6210b`](https://github.com/biomejs/biome/commit/1d6210b8ef6a2d2d83ea16e6fb95c124fd370690) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noUnmodifiedLoopCondition`](https://biomejs.dev/linter/rules/no-unmodified-loop-condition/), which reports variables in loop conditions that are never modified in the loop.
```js
let node = getNode();
while (node) {
process(node);
}
```
### [`v2.5.11`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2511)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.10...@biomejs/biome@2.5.11)
##### Patch Changes
- [#​11499](https://github.com/biomejs/biome/pull/11499) [`9743d0c`](https://github.com/biomejs/biome/commit/9743d0ceae807757300e5b0ec66266125bc664c1) Thanks [@​scs0209](https://github.com/scs0209)! - Fixed [#​11496](https://github.com/biomejs/biome/issues/11496): [`useValidAnchor`](https://biomejs.dev/linter/rules/use-valid-anchor/) now treats Astro JSX shorthand attributes like `<a {href}>` as a valid `href`.
- [#​11437](https://github.com/biomejs/biome/pull/11437) [`88f805e`](https://github.com/biomejs/biome/commit/88f805e19b67ab4c876e4fc4a8b4018bd03df20b) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed [#​9944](https://github.com/biomejs/biome/issues/9944): adjacent elements inside an Astro expression now parse as an implicit fragment instead of raising an error.
```astro
{options.map(() =>
<div />
<div />
)}
```
- [#​11437](https://github.com/biomejs/biome/pull/11437) [`88f805e`](https://github.com/biomejs/biome/commit/88f805e19b67ab4c876e4fc4a8b4018bd03df20b) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro templates rejecting unclosed HTML void elements, such as `{cond && <br>}`.
- [#​11507](https://github.com/biomejs/biome/pull/11507) [`e2fc036`](https://github.com/biomejs/biome/commit/e2fc03669886732ac9c768aa00f3ffae46241848) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11157](https://github.com/biomejs/biome/issues/11157): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports Vue `<script setup>` bindings used by CSS `v-bind()` as unused.
- [#​11398](https://github.com/biomejs/biome/pull/11398) [`afc4615`](https://github.com/biomejs/biome/commit/afc4615079a72e0810f06186f78e5cb177a5638e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11389](https://github.com/biomejs/biome/issues/11389): Files passed through `--stdin-file-path` now use full HTML support for Astro, Svelte, and Vue when it is enabled.
- [#​11526](https://github.com/biomejs/biome/pull/11526) [`372cd68`](https://github.com/biomejs/biome/commit/372cd68ba156efdc497017598a49e21484a3ada9) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`noVueRefAsOperand`](https://biomejs.dev/linter/rules/no-vue-ref-as-operand/) to track Vue refs through declaration aliases and `toRefs()` properties, and to recognize `useTemplateRef()` results. The rule no longer reports false positives such as plain ref transfers, plain `toRefs()` property access, `defineModel()` modifiers, or the supported `.effect` member as operands.
The refactor enabling these fixes also improves the performance of the rule.
- [#​11458](https://github.com/biomejs/biome/pull/11458) [`a7cd286`](https://github.com/biomejs/biome/commit/a7cd2868c3d98fbc75174c5bf69fdcfacbe87304) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11436](https://github.com/biomejs/biome/issues/11436): GritQL snippets such as `export { $specifiers } from $source` now match named re-exports with aliases, inline `type` modifiers, and multiple specifiers.
- [#​11515](https://github.com/biomejs/biome/pull/11515) [`382b15d`](https://github.com/biomejs/biome/commit/382b15d5e0f9e2a75604fec1f15ad342628c99c7) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11390](https://github.com/biomejs/biome/issues/11390), where `noFloatingPromises` performed expensive full type inference for calls to non-Promise methods declared on third-party TypeScript classes. The rule now classifies those calls using targeted type information.
- [#​11516](https://github.com/biomejs/biome/pull/11516) [`6f40e82`](https://github.com/biomejs/biome/commit/6f40e8224afc58737626d997c0ea779e2b37baca) Thanks [@​levrik](https://github.com/levrik)! - Fixed [`noVueRefAsOperand`](https://biomejs.dev/linter/rules/no-vue-ref-as-operand/) so it no longer reports a callback parameter (e.g. from `.find()`, `.map()`) as an unwrapped ref value just because it's nested inside a `ref()`, `computed()`, or similar call.
```js
const result = computed(() => list.find((item) => item.label === "a"));
```
Previously, `item` here was incorrectly treated as a ref value because the rule attributed it to the outer `computed()` call.
- [#​11495](https://github.com/biomejs/biome/pull/11495) [`496268d`](https://github.com/biomejs/biome/commit/496268d1470b6a4cd52bff03d37899c4bb7f77ab) Thanks [@​Netail](https://github.com/Netail)! - Fixed [`useGraphqlNamingConvention`](https://biomejs.dev/linter/rules/use-graphql-naming-convention/) so it no longer reports GraphQL enum value definitions with comments & descriptions and now displays a more accurate diagnostic range.
- [#​11407](https://github.com/biomejs/biome/pull/11407) [`6ef52b0`](https://github.com/biomejs/biome/commit/6ef52b02fc07e23de7ad498d853aaf2c825717fd) Thanks [@​1678092075](https://github.com/1678092075)! - Fixed [#​11214](https://github.com/biomejs/biome/issues/11214): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports type parameters declared by non-default function overload signatures that have an implementation.
- [#​11322](https://github.com/biomejs/biome/pull/11322) [`5c353e6`](https://github.com/biomejs/biome/commit/5c353e6c85a40807e2710684da807f8757ee650c) Thanks [@​jp-knj](https://github.com/jp-knj)! - Added a new nursery rule `noAstroSetHtmlDirective`, which disallows Astro's `set:html` directive because untrusted content can introduce cross-site scripting vulnerabilities.
For example, the following snippet triggers the rule:
```astro
<div set:html={content} />
```
- [#​11462](https://github.com/biomejs/biome/pull/11462) [`18883b7`](https://github.com/biomejs/biome/commit/18883b7dafb8f9581534508fdd5b1e34632f2724) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10776](https://github.com/biomejs/biome/issues/10776): [`useVueHyphenatedAttributes`](https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes/) no longer reports lowercase attribute names containing punctuation, such as `pt:header:data-test-id` and `some_attr`.
- [#​11476](https://github.com/biomejs/biome/pull/11476) [`3270ca4`](https://github.com/biomejs/biome/commit/3270ca4560a28eee92564b9ef64f778972cbf3ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10330](https://github.com/biomejs/biome/issues/10330): Vue interpolation delimiters now stay attached to whitespace-sensitive element boundaries and adjacent inline siblings, wrapping their expression when needed to fit the configured line width. Interpolations followed by text now also converge after one formatting pass.
```diff
-<v-btn v-if="store.state.user" variant="text" to="/my-rooms"
- >{{ $t("nav.my-rooms") }}</v-btn
->
+<v-btn v-if="store.state.user" variant="text" to="/my-rooms">{{
+ $t("nav.my-rooms")
+}}</v-btn>
```
- [#​11191](https://github.com/biomejs/biome/pull/11191) [`3e5367f`](https://github.com/biomejs/biome/commit/3e5367f13de6c8cb80070544774c9935cac7d649) Thanks [@​ematipico](https://github.com/ematipico)! - Added the nursery rule [`noUndeclaredCustomProperties`](https://biomejs.dev/linter/rules/no-undeclared-custom-properties/), which reports references to custom properties that are not defined in available CSS, static HTML-like `style` attributes, or JSX string `style` attributes.
For example, the following snippet triggers the rule:
```css
a { color: var(--undefined-color); }
```
- [#​11435](https://github.com/biomejs/biome/pull/11435) [`7754894`](https://github.com/biomejs/biome/commit/7754894ffaaaa2ab0b281789d5ceae8f333d61a4) Thanks [@​levrik](https://github.com/levrik)! - Fixed: Variables and imports used as custom Vue directives are no longer reported as unused.
For example:
```vue
<script setup>
const vHighlight = {
mounted: (element) => {
element.style.color = "red";
},
};
</script>
<template>
<p v-highlight>Hello</p>
</template>
```
- [#​11501](https://github.com/biomejs/biome/pull/11501) [`e6acded`](https://github.com/biomejs/biome/commit/e6acdedf09c452371670aaaffd0b55206019d1e6) Thanks [@​aminya](https://github.com/aminya)! - Improved the performance of [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/) by skipping type inference for calls to unrelated methods.
- [#​11467](https://github.com/biomejs/biome/pull/11467) [`66b282c`](https://github.com/biomejs/biome/commit/66b282cb70cd61b7606ce1658482b9fe082e37e6) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11464](https://github.com/biomejs/biome/issues/11464): Biome now parses parenthesized object literals returned from arrow functions when they contain a conditional expression and a nested arrow function.
- [#​11456](https://github.com/biomejs/biome/pull/11456) [`db9aa2a`](https://github.com/biomejs/biome/commit/db9aa2a3d936372cbe3ee87687ad25816c9d75ae) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10278](https://github.com/biomejs/biome/issues/10278): Marked the fix for [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) as unsafe by default.
- [#​11502](https://github.com/biomejs/biome/pull/11502) [`652aedb`](https://github.com/biomejs/biome/commit/652aedbdcba8ccb45ccecbce506c90a337f2d64c) Thanks [@​levrik](https://github.com/levrik)! - `noGlobalAssign` no longer reports assignments to a Vue `<script setup>` binding from a template expression, when the binding's name happens to match a built-in global (e.g. `open`, `parent`, `top`).
For example, this no longer triggers a diagnostic:
```vue
<script setup>
const open = defineModel();
</script>
<template>
<button @click="open = !open">Toggle</button>
</template>
```
### [`v2.5.10`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2510)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.9...@biomejs/biome@2.5.10)
##### Patch Changes
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting JavaScript comments between attributes.
```astro
<div /* block comment */ class="something"></div>
<Component /* c */ client:load />
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed a bare `<` in Astro text being treated as the start of a tag, such as `<p>5 < 6 and 7 > 6</p>`. As in HTML, a `<` that cannot open a tag is text and needs no escaping.
- [#​11438](https://github.com/biomejs/biome/pull/11438) [`3133ffa`](https://github.com/biomejs/biome/commit/3133ffa9ae6beaa3c4464edac60de47d5c6f6426) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed [#​8294](https://github.com/biomejs/biome/issues/8294): an Astro expression holding only a comment is no longer reported as a parse error, which also stopped the whole file from being formatted.
```astro
<div>{/* a note */}</div>
<div class={/* a note */}>x</div>
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed [#​9165](https://github.com/biomejs/biome/issues/9165): an empty Astro expression such as `<div>{}</div>` no longer fails to parse. Astro renders `{}` as nothing.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro expressions containing a comment failing to parse.
```astro
<div>{/* block comment */ x}</div>
<div>{/* only a comment */}</div>
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Added support for Astro's fragment shorthand.
```astro
<>
<p>a</p>
</>
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed an Astro frontmatter block being cut short by a closing tag inside a string or comment.
```astro
---
const a = "</script>";
// </script> in a comment
---
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed `---` being read as an Astro frontmatter fence when markup precedes it. Astro only recognizes frontmatter at the very start of a file, so a file opening with a comment now has no frontmatter, and its `---` lines are content.
```astro
<!-- c -->
---
this is text, not frontmatter
---
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed an Astro frontmatter block ending early on a line that merely starts with a dash.
```astro
---
--count;
---
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed the children of an Astro element carrying `is:raw` being parsed as markup instead of raw text. This now also covers `<script>` and `<style>`, whose contents Astro emits verbatim rather than processing, so they are no longer linted as JavaScript or CSS.
```astro
<article is:raw><% awesome %></article>
<script is:raw>{{ mustache }}</script>
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting attribute names that start with a colon, such as `:href`.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed the Astro parser failing to recover from a malformed closing tag such as `<div></{<//`, so that a later mistake is reported where it happens rather than cascading.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed `{` inside an Astro `<math>` element opening an expression. MathML is foreign content where Astro parses no expressions, so LaTeX such as `R^{2x}` now survives as text. `<svg>` is unaffected.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed `{{` at the start of an Astro expression being read as an interpolation. Astro has no `{{ }}` syntax, so `{{ a: 1 }}` and `<Comp a={{ b: 1 }} />` are object literals.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed expressions inside an Astro `<pre>` or `<textarea>` being read as raw text. Astro parses both as ordinary elements, so their markup and interpolations are now parsed, and a variable used only inside one is no longer reported as unused.
```astro
<pre>{value}</pre>
<textarea><div>{value}</div></textarea>
```
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Added support for template literal attribute values in Astro, such as ``<div class=`a ${b} c`>``.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting HTML5 unquoted attribute values that contain `` ` ``, `=`, `'` or `"`, such as `<a href=a=b>` and `<a href=a'b>`.
- [#​11393](https://github.com/biomejs/biome/pull/11393) [`dec5a8f`](https://github.com/biomejs/biome/commit/dec5a8fadcb565867526e51da0895c2be27400bb) Thanks [@​1678092075](https://github.com/1678092075)! - Fixed [#​11207](https://github.com/biomejs/biome/issues/11207): [`useStrictMode`](https://biomejs.dev/linter/rules/use-strict-mode/) no longer reports Vue event handlers such as `@click="count++"`.
- [#​11431](https://github.com/biomejs/biome/pull/11431) [`c065f99`](https://github.com/biomejs/biome/commit/c065f995909d16cbf98c247a280a48c156aeb61f) Thanks [@​levrik](https://github.com/levrik)! - Fixed [#​11429](https://github.com/biomejs/biome/issues/11429): Variables and imports used by Vue same-name bindings such as `:disabled` or `v-bind:disabled` are no longer reported as unused.
- [#​11409](https://github.com/biomejs/biome/pull/11409) [`405dedb`](https://github.com/biomejs/biome/commit/405dedb0ff65dd29927faf587f6542e3c29db248) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a memory leak in the LSP server where memory usage kept growing over long editor sessions.
- [#​11422](https://github.com/biomejs/biome/pull/11422) [`a51eff7`](https://github.com/biomejs/biome/commit/a51eff7f7ca71e8786a2f0db1d560455b83ce21c) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11416](https://github.com/biomejs/biome/issues/11416): Biome no longer crashes when parsing incomplete `{let}` or `{const}` declarations in Svelte files.
- [#​11378](https://github.com/biomejs/biome/pull/11378) [`34b715c`](https://github.com/biomejs/biome/commit/34b715cb417d482bfb4630c05a576b748c8faa8b) Thanks [@​Netail](https://github.com/Netail)! - Added extra rule sources from `@eslint/css`. `biome migrate eslint` detects rules in your eslint configurations more reliably.
- [#​11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Fixed `{#`, `{/`, `{:` and `{@` being read as Svelte block openings in every HTML-like file. They are now Svelte-only, so in HTML, Vue and Angular files a sequence such as `{#if x}` is ordinary text instead of a parse error.
- [#​11443](https://github.com/biomejs/biome/pull/11443) [`8d45229`](https://github.com/biomejs/biome/commit/8d452293d04272c876b0414292540645cfea87e4) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11390](https://github.com/biomejs/biome/issues/11390): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer performs unnecessary type inference on call arguments when checking methods of non-generic class instances created with `new`.
- [#​11425](https://github.com/biomejs/biome/pull/11425) [`9c2667b`](https://github.com/biomejs/biome/commit/9c2667ba2010441054bc0b54a1a810e851207560) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​6426](https://github.com/biomejs/biome/issues/6426): GritQL plugins now match and rewrite metavariables embedded in quoted strings.
- [#​11441](https://github.com/biomejs/biome/pull/11441) [`00317c3`](https://github.com/biomejs/biome/commit/00317c353a65214d8f4cb0f2d930d7c4e1f305dd) Thanks [@​dyc3](https://github.com/dyc3)! - Improved performance of [`useNamedCaptureGroup`](https://biomejs.dev/linter/rules/use-named-capture-group/), [`noMisplacedAssertion`](https://biomejs.dev/linter/rules/no-misplaced-assertion/), [`noSkippedTests`](https://biomejs.dev/linter/rules/no-skipped-tests/), [`noExportsInTest`](https://biomejs.dev/linter/rules/no-exports-in-test/), [`noDuplicateTestHooks`](https://biomejs.dev/linter/rules/no-duplicate-test-hooks/), [`noIdenticalTestTitle`](https://biomejs.dev/linter/rules/no-identical-test-title/), [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order/), and [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top/).
### [`v2.5.9`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#259)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.8...@biomejs/biome@2.5.9)
##### Patch Changes
- [#​11321](https://github.com/biomejs/biome/pull/11321) [`41386f3`](https://github.com/biomejs/biome/commit/41386f38935b299f1a1f759a2c7fdd5c2050bded) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11315](https://github.com/biomejs/biome/issues/11315): The CSS parser now recovers at declaration boundaries after bogus declarations, allowing subsequent valid declarations to be parsed.
- [#​11248](https://github.com/biomejs/biome/pull/11248) [`57b197e`](https://github.com/biomejs/biome/commit/57b197e6d5a2432ff6904afff24125e4d8ec01cd) Thanks [@​yanthomasdev](https://github.com/yanthomasdev)! - Expanded the environment variable metadata used by `biome rage` to include `BIOME_BINARY`, `BIOME_LOG_FILE`, and `RUST_BACKTRACE` as well as reworded explanations for better readability.
- [#​11377](https://github.com/biomejs/biome/pull/11377) [`a8798ea`](https://github.com/biomejs/biome/commit/a8798ea9f2569fab4524704c99a8e2fe45c2ca32) Thanks [@​Netail](https://github.com/Netail)! - Added a new nursery rule [`useNamedLayer`](https://biomejs.dev/linter/rules/use-named-layer) which disallows anonymous cascade layers.
```css
@layer {
a {
color: red;
}
}
```
- [#​11327](https://github.com/biomejs/biome/pull/11327) [`6771cf5`](https://github.com/biomejs/biome/commit/6771cf5bd2e64f256468a33b811adec8e793d933) Thanks [@​dyc3](https://github.com/dyc3)! - The HTML formatter now preserves meaningful blank lines in HTML, including spacing after elements with trailing spaces and blank lines between comment groups.
```diff
<div>
<!-- first group -->
+
<!-- second group -->
</div>
```
- [#​10312](https://github.com/biomejs/biome/pull/10312) [`ba8aa18`](https://github.com/biomejs/biome/commit/ba8aa183371b3080691ed80e5a9f6f0239cf451b) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTailwindShorthandClasses`](https://biomejs.dev/linter/rules/use-tailwind-shorthand-classes/), which suggests shorter Tailwind utility classes. For example, the rule suggests replacing `w-4 h-4` with `size-4`.
- [#​11333](https://github.com/biomejs/biome/pull/11333) [`715e0cd`](https://github.com/biomejs/biome/commit/715e0cd1b3e6c88d153554901a659378c728e408) Thanks [@​kkkhs](https://github.com/kkkhs)! - Fixed [#​11328](https://github.com/biomejs/biome/issues/11328): `lint/nursery/useExpect` now recognizes Vitest Browser Mode `expect.element()` calls as assertions.
- [#​11343](https://github.com/biomejs/biome/pull/11343) [`9b98211`](https://github.com/biomejs/biome/commit/9b982113dba8b37c163662d59611ecba0fc02f5a) Thanks [@​johncarmack1984](https://github.com/johncarmack1984)! - Fixed [#​11311](https://github.com/biomejs/biome/issues/11311): the CSS parser now accepts Tailwind container-query variant names in `@variant`, such as `@xl` and `@max-xl`. These previously produced a parse error and a [`noUnknownAtRules`](https://biomejs.dev/linter/rules/no-unknown-at-rules/) diagnostic.
```css
@variant @xl {
div {
background: red;
}
}
```
- [#​11220](https://github.com/biomejs/biome/pull/11220) [`3e8c488`](https://github.com/biomejs/biome/commit/3e8c4887c4ef87df45f56aafa4fbc5f497dae42f) Thanks [@​santichausis](https://github.com/santichausis)! - Fixed [#​9541](https://github.com/biomejs/biome/issues/9541): [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/), [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/), and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now correctly recognise exported variables and functions declared in one embedded `<script>` block as usable from a sibling `<script>` block, in Svelte's `<script module>`/`<script>` pair and Vue's non-`setup` `<script>` blocks.
For example, Biome no longer reports `greet` as undeclared in the following Svelte component:
```svelte
<script module>
export function greet() {
console.log("Hello!");
}
</script>
<script>
greet();
</script>
```
- [#​11300](https://github.com/biomejs/biome/pull/11300) [`36430eb`](https://github.com/biomejs/biome/commit/36430ebb9679d1ca5d9c231a36b709a4b5eab9b3) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter's whitespace handling for `marquee`, `noscript`, `video`, `audio`, and `object` elements.
```diff
- <marquee behavior="alternate"> This text will bounce </marquee>
+ <marquee behavior="alternate">This text will bounce</marquee>
```
- [#​11299](https://github.com/biomejs/biome/pull/11299) [`6559e6c`](https://github.com/biomejs/biome/commit/6559e6ced6d4ebe8c26e818931df15d02829130d) Thanks [@​jp-knj](https://github.com/jp-knj)! - Added the nursery rule `useAstroClientOnlyDirectiveValue`, which reports Astro `client:only` directives without an initializer.
For example, `<Component client:only />` triggers the rule.
- [#​11365](https://github.com/biomejs/biome/pull/11365) [`7529811`](https://github.com/biomejs/biome/commit/7529811358079edb5a2a9d4a5f67a9f639a63f3a) Thanks [@​MHJahanbakhsh](https://github.com/MHJahanbakhsh)! - Fixed [#​11229](https://github.com/biomejs/biome/issues/11229): The [`useGenericFontNames`](https://biomejs.dev/linter/rules/use-generic-font-names/) rule now treats `math` as a valid generic font family.
- [#​11346](https://github.com/biomejs/biome/pull/11346) [`674f5f4`](https://github.com/biomejs/biome/commit/674f5f4b4e6923b6c7fd12d76e366f82ffe6405b) Thanks [@​Jayllyz](https://github.com/Jayllyz)! - Fixed [#​11335](https://github.com/biomejs/biome/issues/11335): [`noComponentHookFactories`](https://biomejs.dev/linter/rules/no-component-hook-factories/) now reports a `use`-prefixed variable only when a function is assigned to it directly.
```js
function factory() {
const useColors = true; // no longer reported
const useStore = createStore({ count: 0 }); // no longer reported
const useData = () => useState(null); // still reported
return useColors;
}
```
- [#​11334](https://github.com/biomejs/biome/pull/11334) [`c87c46a`](https://github.com/biomejs/biome/commit/c87c46ab350a40fd38b2288887e2d6e930a2d62d) Thanks [@​zkasuran](https://github.com/zkasuran)! - Fixed [#​11317](https://github.com/biomejs/biome/issues/11317): [`noSvgWithoutTitle`](https://biomejs.dev/linter/rules/no-svg-without-title/) no longer reports an `svg` that uses the boolean shorthand `aria-hidden` (equivalent to `aria-hidden={true}` in React).
- [#​11364](https://github.com/biomejs/biome/pull/11364) [`13853b1`](https://github.com/biomejs/biome/commit/13853b16685d96bfb9158de7d5f4c101d114ba32) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a bug where [`useJsxKeyInIterable`](https://biomejs.dev/linter/rules/use-jsx-key-in-iterable/) incorrectly flagged Astro files.
- [#​11321](https://github.com/biomejs/biome/pull/11321) [`41386f3`](https://github.com/biomejs/biome/commit/41386f38935b299f1a1f759a2c7fdd5c2050bded) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11315](https://github.com/biomejs/biome/issues/11315): Invalid CSS declarations in HTML `style` attributes now produce parser diagnostics instead of causing a panic.
- [#​11325](https://github.com/biomejs/biome/pull/11325) [`67c3bf0`](https://github.com/biomejs/biome/commit/67c3bf01131c0c079fa058eef96dc28d52c2c59f) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed HTML text wrapping to account for the width of an adjacent closing tag, avoiding lines that exceed the configured width when the final word and tag must move together.
```diff
<a-long-long-long-element
- >foo bar foo bar foo bar foo bar foo bar foo bar foo bar</a-long-long-long-element
+ >foo bar foo bar foo bar foo bar foo bar foo
+ bar</a-long-long-long-element
>
```
- [#​11367](https://github.com/biomejs/biome/pull/11367) [`fe5b5d4`](https://github.com/biomejs/biome/commit/fe5b5d41c863d5e2f3b58570e15f483c189d2825) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed TypeScript `compilerOptions.paths` resolution when mapping targets omit `./`. Biome now resolves these targets relative to their configured path base.
- [#​11316](https://github.com/biomejs/biome/pull/11316) [`17e48d6`](https://github.com/biomejs/biome/commit/17e48d6088f23ec30a1e17e315b52369f1e4836c) Thanks [@​wanxiankai](https://github.com/wanxiankai)! - Fixed [#​11289](https://github.com/biomejs/biome/issues/11289): the safe fix for [`noExtraBooleanCast`](https://biomejs.dev/linter/rules/no-extra-boolean-cast/) now preserves parentheses around nested conditional expressions.
- [#​11254](https://github.com/biomejs/biome/pull/11254) [`d25d113`](https://github.com/biomejs/biome/commit/d25d113aed23ca9b5ee9b7cdedb208d8a0b2cd00) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11242](https://github.com/biomejs/biome/issues/11242): Biome no longer crashes with an access violation when analysing files on Windows ARM64.
- [#​11221](https://github.com/biomejs/biome/pull/11221) [`85aac73`](https://github.com/biomejs/biome/commit/85aac73d32a5f4a0db7bab3ebd195e35b32d513d) Thanks [@​freeatnet](https://github.com/freeatnet)! - Added the nursery rule [`noUnsafeTypeAssertion`](https://biomejs.dev/linter/rules/no-unsafe-type-assertion/), which disallows TypeScript type assertions while allowing const assertions.
```ts
const value = input as SomeType;
```
- [#​11314](https://github.com/biomejs/biome/pull/11314) [`7ffb677`](https://github.com/biomejs/biome/commit/7ffb677159c96f072a508e58bfad26ca9c301ac4) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11310](https://github.com/biomejs/biome/issues/11310): Restored the performance of [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) and [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) when analyzed expressions share deep imported type paths.
- [#​11356](https://github.com/biomejs/biome/pull/11356) [`6cd3263`](https://github.com/biomejs/biome/commit/6cd32636f463551b8dfe46aeefb1191d437b4694) Thanks [@​johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands modifiers on bare utilities (`@container/sidebar`, `shadow/50`).
- [#​11318](https://github.com/biomejs/biome/pull/11318) [`76059e9`](https://github.com/biomejs/biome/commit/76059e9f03f5962a18f3569714f8f207ef7c1d91) Thanks [@​johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands container-query variants (`@sm:`, `@max-lg:`, `@min-[400px]:`) and child and descendant variants (`*:`, `**:`).
- [#​11357](https://github.com/biomejs/biome/pull/11357) [`faa2074`](https://github.com/biomejs/biome/commit/faa2074472bc0f4a11f4e80cb4d2b0e55883226a) Thanks [@​johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now accepts the legacy leading `!` important marker (`!flex`, `hover:!p-4`).
- [#​11344](https://github.com/biomejs/biome/pull/11344) [`f34e15c`](https://github.com/biomejs/biome/commit/f34e15c946511d998c01b6c6e410f0c220c2943e) Thanks [@​johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands combinator selectors in arbitrary variants (`has-[>svg]:`, `has-[+p]:`), modifiers on variants (`group-hover/menu:`, `@sm/main:`), and arbitrary container-query sizes (`@[400px]:`).
- [#​11324](https://github.com/biomejs/biome/pull/11324) [`2f5d452`](https://github.com/biomejs/biome/commit/2f5d452015ee80a02d4e50c4bb2ba930092048a2) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed HTML formatting that inserted rendered whitespace between an element and touching text when the line wrapped.
```diff
<div>
- before<meter value=".5"></meter>
- after
+ before<meter value=".5"></meter
+ >after
</div>
```
- [#​11312](https://github.com/biomejs/biome/pull/11312) [`e65f07e`](https://github.com/biomejs/biome/commit/e65f07e06342c7d8d74b98ff219d72c7e081b4f2) Thanks [@​xosnos](https://github.com/xosnos)! - Added a new nursery rule [`useControlLabel`](https://biomejs.dev/linter/rules/use-control-label/) for both HTML and JSX, which reports interactive control elements (`button`, `menuitem`) without an accessible label.
```jsx
<button />
```
- [#​11364](https://github.com/biomejs/biome/pull/11364) [`13853b1`](https://github.com/biomejs/biome/commit/13853b16685d96bfb9158de7d5f4c101d114ba32) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed SVG parsing for files with an XML declaration followed by a `PUBLIC` doctype, such as `<?xml version="1.0"?><!DOCTYPE svg PUBLIC "a" "b">`.
- [#​11301](https://github.com/biomejs/biome/pull/11301) [`610ee28`](https://github.com/biomejs/biome/commit/610ee282989ac73908e0f8bd6e49bc40cccfef77) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed parent tag wrapping when an HTML element starts or ends with a block-like or hidden child such as `source`, `track`, or `param`.
```diff
- <video src="brave.webm"><track kind="subtitles" src="brave.en.vtt"></video>
+ <video src="brave.webm">
+ <track kind="subtitles" src="brave.en.vtt">
+ </video>
```
### [`v2.5.8`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#258)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.7...@biomejs/biome@2.5.8)
##### Patch Changes
- [#​10710](https://github.com/biomejs/biome/pull/10710) [`0a0fbc1`](https://github.com/biomejs/biome/commit/0a0fbc15d67c410c80dfae398903f845544fcd65) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/), which reports diagnostics from React Compiler lint mode.
- [#​11251](https://github.com/biomejs/biome/pull/11251) [`ea9dd8a`](https://github.com/biomejs/biome/commit/ea9dd8a93e65f849840415e8e26cd668aa1af913) Thanks [@​dyc3](https://github.com/dyc3)! - Improved performance of [`noImportCycles`](https://biomejs.dev/linter/rules/no-import-cycles/).
- [#​11247](https://github.com/biomejs/biome/pull/11247) [`52b44d6`](https://github.com/biomejs/biome/commit/52b44d6795741d051bf703bd69c6cb447af8fd1d) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noSvelteLegacyConst`](https://biomejs.dev/linter/rules/no-svelte-legacy-const/), which disallows legacy Svelte `{@const}` tags and recommends declaration tags with `$derived()`.
Invalid:
```svelte
{#each boxes as box}
{@const area = box.width * box.height}
<p>{area}</p>
{/each}
```
Valid:
```svelte
{#each boxes as box}
{const area = $derived(box.width * box.height)}
<p>{area}</p>
{/each}
```
- [#​11252](https://github.com/biomejs/biome/pull/11252) [`d5f5704`](https://github.com/biomejs/biome/commit/d5f570414fdcdddf62372e35c05f6dababad9287) Thanks [@​Turtle-Hwan](https://github.com/Turtle-Hwan)! - Fixed [#​11250](https://github.com/biomejs/biome/issues/11250): [`useAwait`](https://biomejs.dev/linter/rules/use-await/) no longer reports async functions that contain an `await using` declaration.
- [#​11143](https://github.com/biomejs/biome/pull/11143) [`6be7be1`](https://github.com/biomejs/biome/commit/6be7be1b147d7b4352ff5625a78bd54a48958950) Thanks [@​vznh](https://github.com/vznh)! - Fixed [#​11017](https://github.com/biomejs/biome/issues/11017): [`noUselessUndefined`](https://biomejs.dev/linter/rules/no-useless-undefined/) no longer reports `return undefined` when the enclosing function has a return type annotation other than `undefined` or `void`.
- [#​11234](https://github.com/biomejs/biome/pull/11234) [`caefe39`](https://github.com/biomejs/biome/commit/caefe393c66340914c481f7ccfc82979cf76b61b) Thanks [@​subotac](https://github.com/subotac)! - Fixed [#​11228](https://github.com/biomejs/biome/issues/11228): CSS block comments between a declaration colon and value now preserve their source indentation.
```diff
:root {
--font-stack:
-/* comment */
+ /* comment */
system-ui;
}
```
- [#​11285](https://github.com/biomejs/biome/pull/11285) [`bca1f73`](https://github.com/biomejs/biome/commit/bca1f73d939423056337bfd0a42cbdcb66bb1e3f) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed [#​11280](https://github.com/biomejs/biome/issues/11280): CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name.
```diff
-:/* comment */ where(div) {}
+:where(/* comment */ div) {}
```
- [#​11080](https://github.com/biomejs/biome/pull/11080) [`af16a0b`](https://github.com/biomejs/biome/commit/af16a0bf884c48bad2caab70e7930096e81e1c99) Thanks [@​dyc3](https://github.com/dyc3)! - HTML `style` attribute values are now parsed as CSS. All Biome CSS lint rules are applied to the `style` attributes.
- [#​11195](https://github.com/biomejs/biome/pull/11195) [`6a85588`](https://github.com/biomejs/biome/commit/6a85588578725195625281984a47c9a8563bf103) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed Svelte files failing to parse when an expression begins with an object literal.
Now the following snippet is correctly parsed:
```svelte
<p>{{ a: true }}</p>
<div class={{ active: isActive }}></div>
```
- [#​11173](https://github.com/biomejs/biome/pull/11173) [`481d008`](https://github.com/biomejs/biome/commit/481d008f6e8872a78749496fbbf1f9c761d9a770) Thanks [@​Austin1serb](https://github.com/Austin1serb)! - Fixed [#​10242](https://github.com/biomejs/biome/issues/10242): JavaScript GritQL patterns with multiple metavariables now match snippets consistently in WebAssembly.
- [#​11187](https://github.com/biomejs/biome/pull/11187) [`23c0369`](https://github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8) Thanks [@​ematipico](https://github.com/ematipico)! - Added the nursery rule [`noInvalidPropertyInitValue`](https://biomejs.dev/linter/rules/no-invalid-property-init-value/), which reports an `@property` whose `initial-value` does not match its `syntax` descriptor. For example, the following declaration triggers the rule because `red` is not a `<length>`:
```css
@property --size {
syntax: "<length>";
inherits: false;
initial-value: red;
}
```
- [#​11272](https://github.com/biomejs/biome/pull/11272) [`73896e6`](https://github.com/biomejs/biome/commit/73896e6712ba4c398ba21141829f8361ace45eb2) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the diagnostic emitted by [`noRootType`](https://biomejs.dev/linter/rules/no-root-type).
- [#​11240](https://github.com/biomejs/biome/pull/11240) [`bd0b68d`](https://github.com/biomejs/biome/commit/bd0b68d418890059930074b46273aa616fbb735a) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11223](https://github.com/biomejs/biome/issues/11223): Improved the
performance of [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/)
when analyzing async class methods that call other methods through `this`.
- [#​11172](https://github.com/biomejs/biome/pull/11172) [`4a0bc5c`](https://github.com/biomejs/biome/commit/4a0bc5c46e6dbbefd17fa133ea426aa41f0a23f8) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Fixed [#​10806](https://github.com/biomejs/biome/issues/10806): [`noUselessFragments`](https://biomejs.dev/linter/rules/no-useless-fragments/) no longer causes Biome to panic when its unsafe fix removes a fragment used as a JSX attribute value.
- [#​11227](https://github.com/biomejs/biome/pull/11227) [`4d603b0`](https://github.com/biomejs/biome/commit/4d603b072fae45a69bd291ab92f3379232cd34df) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Fixed [#​11178](https://github.com/biomejs/biome/issues/11178): [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) no longer reports Vue's built-in instance properties, such as `$slots` and `$attrs`, in template expressions or `$event` in inline event-handler expressions. The instance properties are still reported inside `<script setup>`, where they are not defined.
- [#​11187](https://github.com/biomejs/biome/pull/11187) [`23c0369`](https://github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the `syntax` descriptor of `@property` rules.
### [`v2.5.7`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#257)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.6...@biomejs/biome@2.5.7)
##### Patch Changes
- [#​10822](https://github.com/biomejs/biome/pull/10822) [`c171b3b`](https://github.com/biomejs/biome/commit/c171b3bd513d49c35b66cdc74a5de0ca0766b6ef) Thanks [@​pkallos](https://github.com/pkallos)! - Added the option `ignoreIfStatements` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). Biome now flags `if` statements that only assign to a nullish variable (such as `if (!a) { a = b }`) and can rewrite them to `??=`. When enabled, Biome ignores those `if` statements.
- [#​11136](https://github.com/biomejs/biome/pull/11136) [`e63354c`](https://github.com/biomejs/biome/commit/e63354cf280783fa6380951342bdacc3fd55e681) Thanks [@​AkashNaickar](https://github.com/AkashNaickar)! - Added a new nursery rule [`noExtendNative`](https://biomejs.dev/linter/rules/no-extend-native/), which reports extending the prototype of a built-in object.
- [#​10094](https://github.com/biomejs/biome/pull/10094) [`e007143`](https://github.com/biomejs/biome/commit/e00714360807115210e549caca0f235431ca9a8a) Thanks [@​THEjacob1000](https://github.com/THEjacob1000)! - Added the nursery rule [`noTailwindArbitraryValue`](https://biomejs.dev/linter/rules/no-tailwind-arbitrary-value/). Biome now reports Tailwind CSS arbitrary values such as `w-[400px]`, including in HTML/JSX class attributes, configured utility functions, and tagged templates.
- [#​11184](https://github.com/biomejs/biome/pull/11184) [`135f476`](https://github.com/biomejs/biome/commit/135f476de8b853f9dc2ff2679ea3525432e66e8e) Thanks [@​subotac](https://github.com/subotac)! - Fixed [#​11176](https://github.com/biomejs/biome/issues/11176): `noUnknownPseudoClass` now recognizes Vue's `:deep()` pseudo-class inside `.vue` style blocks.
- [#​8239](https://github.com/biomejs/biome/pull/8239) [`a519f9d`](https://github.com/biomejs/biome/commit/a519f9d19e56015ec906efac4629fbb15708f5e2) Thanks [@​cormacrelf](https://github.com/cormacrelf)! - Fixed [#​8233](https://github.com/biomejs/biome/issues/8233), where Biome CLI in
stdin mode didn't work correctly when handling files in projects with nested
configurations. For example, with the following structure,
`--stdin-file-path=subdirectory/...` would not use the nested configuration in
`subdirectory/biome.json`:
```
├── biome.json
└── subdirectory
├── biome.json
└── lib.js
```
```shell
biome format --write --stdin-file-path=subdirectory/lib.js < subdirectory/lib.js
```
Now, the nested configuration is correctly picked up and applied.
In addition, Biome now shows a warning if `--stdin-file-path` is provided but
that path is ignored and therefore not formatted or fixed.
- [#​11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/): Biome now chooses the same function overload as TypeScript when an argument is a callback, so conditions that were previously missed are reported.
The following code is now invalid, because a parameter typed `() => void` accepts an `async` callback and `schedule` therefore returns `string`:
```ts
declare function schedule(handler: () => void): string;
declare function schedule(handler: () => Promise<void>): string | undefined;
schedule(async () => {}) ?? "fallback";
```
The following code is also now invalid, because `map(() => 42)` returns `42`:
```ts
type Mapper<T> = () => T;
declare function map<T>(mapper: Mapper<T>): T;
map(() => 42) || flag;
```
- [#​11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11087](https://github.com/biomejs/biome/issues/11087): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports optional chains and nullish coalescing whose receiver can be nullish.
For example, the optional chain and fallback in the following code are no longer reported:
```ts
declare const usage: { range: { startDate: string } } | null;
const startDate = usage?.range.startDate ?? "N/A";
```
- [#​11118](https://github.com/biomejs/biome/pull/11118) [`9c16840`](https://github.com/biomejs/biome/commit/9c16840801a806ba34fbba7da28b9724d250207a) Thanks [@​subotac](https://github.com/subotac)! - Fixed [#​11098](https://github.com/biomejs/biome/issues/11098): The HTML formatter now preserves the configured trailing newline when a file ends with a comment.
```diff
-<!-- trailing comment -->
\ No newline at end of file
+<!-- trailing comment -->
```
- [#​11201](https://github.com/biomejs/biome/pull/11201) [`0e80610`](https://github.com/biomejs/biome/commit/0e8061069915651a6f7cbba918a0bde0dbc1491f) Thanks [@​Bishwas-py](https://github.com/Bishwas-py)! - Fixed [#​11182](https://github.com/biomejs/biome/issues/11182): suppression comments for [`noPositiveTabindex`](https://biomejs.dev/linter/rules/no-positive-tabindex/) now suppress the rule in HTML files when the attributes of the element span multiple lines.
- [#​11079](https://github.com/biomejs/biome/pull/11079) [`607afd2`](https://github.com/biomejs/biome/commit/607afd2488efb30cff5ea4b27de4d98eca728e0f) Thanks [@​dyc3](https://github.com/dyc3)! - The HTML formatter now lays out the `srcset` attribute of `<img>` and `<source>` as the list of candidates it is. Runs of whitespace between candidates collapse, and once the list no longer fits on one line each candidate goes on its own line with the descriptors aligned:
```diff
- <img srcset="/visual@0.5.png 400w, /visual.png 805w, /visual@2x.png 1610w, /visual@3x.png 2415w" />
+ <img
+ srcset="
+ /visual@0.5.png 400w,
+ /visual.png 805w,
+ /visual@2x.png 1610w,
+ /visual@3x.png 2415w
+ "
+ />
```
- [#​11156](https://github.com/biomejs/biome/pull/11156) [`fed72c7`](https://github.com/biomejs/biome/commit/fed72c7e8a2bff2942d5970f182262d18e049914) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Fixed [#​11129](https://github.com/biomejs/biome/issues/11129): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports Vue bindings as unused when they are assigned through automatically unwrapped template refs.
- [#​11124](https://github.com/biomejs/biome/pull/11124) [`d890b39`](https://github.com/biomejs/biome/commit/d890b39c3ef21040bded453d9af91e1b301a0d67) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting of line comments between a declaration colon and value to preserve their source indentation.
```diff
.test {
background:
- /////// foo
- // bar
+ /////// foo
+ // bar
radial-gradient(circle, #​000, transparent);
}
```
- [#​11113](https://github.com/biomejs/biome/pull/11113) [`3d8ab73`](https://github.com/biomejs/biome/commit/3d8ab73619f1c62a2d544d41ffee16eab9307d51) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting of long block comments between comma-separated property values:
```diff
.foo {
box-shadow:
- 1000px /* long long long long long long long long long long long long comment */ 1000px /* long long long long long long long long long comment */ 2px color(srgb 0.555555555 0.555555555 0.555555555),
+ 1000px
+ /* long long long long long long long long long long long long comment */
+ 1000px /* long long long long long long long long long comment */ 2px
+ color(srgb 0.555555555 0.555555555 0.555555555),
1px 1px black;
}
```
- [#​11127](https://github.com/biomejs/biome/pull/11127) [`da5c1a5`](https://github.com/biomejs/biome/commit/da5c1a539bac009eb1bc275b9bd8194f9ca7d5fa) Thanks [@​dyc3](https://github.com/dyc3)! - The HTML formatter now picks the quote character for an attribute by counting the quotes in the value rather than looking only for a double quote. `'` and `"` count as the characters they stand for, and only the character that ends up as the delimiter stays escaped:
```diff
- <div title='123 '" 456'></div>
+ <div title="123 '" 456"></div>
```
Entities that are not quotes, such as `&` or `&[#​39](https://github.com/biomejs/biome/issues/39);`, are left exactly as written.
- [#​11193](https://github.com/biomejs/biome/pull/11193) [`77035bb`](https://github.com/biomejs/biome/commit/77035bb3777805c682eefa4cbed5464c94baccba) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter collapsing the blank line between an element and the text that follows it. A blank line before text is now kept, the way one before another element already was:
```diff
<div>foo</div>
-
text
```
- [#​11106](https://github.com/biomejs/biome/pull/11106) [`ad80f57`](https://github.com/biomejs/biome/commit/ad80f572c922fc2a80c90b8e26a66300dfb82d24) Thanks [@​dyc3](https://github.com/dyc3)! - The HTML formatter now writes the HTML5 doctype in lowercase, matching Prettier:
```diff
- <!DOCTYPE html>
+ <!doctype html>
```
This only applies to a plain `.html` file whose doctype stands alone. A doctype that names a DTD keeps the case it was written with, since the rest of the declaration is not lowercased either:
```html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
```
A `.vue`, `.svelte`, or `.astro` file keeps whatever the author wrote.
- [#​11188](https://github.com/biomejs/biome/pull/11188) [`60679db`](https://github.com/biomejs/biome/commit/60679dbe6d53c9b78571042b0b8c906bd345e52d) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter printing a comment twice when it ended the line of the last element in a document:
```diff
- text<!-- a --><!-- a -->
+ text<!-- a -->
```
- [#​11077](https://github.com/biomejs/biome/pull/11077) [`4dcd0d9`](https://github.com/biomejs/biome/commit/4dcd0d99579650191696dc5fb8b16dd69d65c4ee) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed a bug where the HTML formatter collapsed the whitespace inside `<textarea>`, `<xmp>` and `<plaintext>`, changing what the page renders.
```diff
- <textarea>
- line one
- line two </textarea>
+ <textarea>line one line two</textarea>
```
Biome now prints the content of these elements exactly as it appears in the source, matching the existing behavior for `<pre>`.
- [#​11194](https://github.com/biomejs/biome/pull/11194) [`abfbb11`](https://github.com/biomejs/biome/commit/abfbb11da260852f0b4aa15f36207314ccfae436) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter refusing to format a Svelte file containing an array pattern that skips a position:
```svelte
{#each animals as [, value]}
<p>{value}</p>
{/each}
```
- [#​10094](https://github.com/biomejs/biome/pull/10094) [`e007143`](https://github.com/biomejs/biome/commit/e00714360807115210e549caca0f235431ca9a8a) Thanks [@​THEjacob1000](https://github.com/THEjacob1000)! - Fixed [`useSortedClasses`](https://biomejs.dev/linter/rules/use-sorted-classes/) to correctly detect unsorted classes in static member expression tagged templates (e.g. `tw.div\`...\`\`). Previously, these were silently skipped due to surrounding whitespace trivia not being stripped from the tag name.
- [#​11078](https://github.com/biomejs/biome/pull/11078) [`10da30e`](https://github.com/biomejs/biome/commit/10da30e0013c35fe2f4d3e335b88a539ae6eb87a) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed Vue single-file components failing to parse when they contain a custom block such as `<i18n>` or `<docs>`, or a `<template>` written in another language. Their content is no longer read as HTML, so a block may hold whatever its own tooling expects:
```vue
<docs>
This block is prose, and it may mention a `<my-component>` without closing it.
</docs>
<template lang="pug">
.test
#foo
</template>
```
Previously both blocks produced a parse error and the whole file was left unformatted. Biome now prints their content unchanged while still formatting the opening tag.
- [#​11231](https://github.com/biomejs/biome/pull/11231) [`4afd901`](https://github.com/biomejs/biome/commit/4afd901edd5d921d63a259a049c6a774269c7b82) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the performance of the following lint rules:
- [`noArguments`](https://biomejs.dev/linter/rules/no-arguments/).
- [`noGlobalAssign`](https://biomejs.dev/linter/rules/no-global-assign/).
- [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/).
- [`noRestrictedGlobals`](https://biomejs.dev/linter/rules/no-restricted-globals/).
- [`noInvalidUseBeforeDeclaration`](https://biomejs.dev/linter/rules/no-invalid-use-before-declaration/).
- [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/).
- [`noRedeclare`](https://biomejs.dev/linter/rules/no-redeclare/).
- [#​11134](https://github.com/biomejs/biome/pull/11134) [`2fa0a62`](https://github.com/biomejs/biome/commit/2fa0a62224af7a13869a28ef80aefa5ea75ebfd2) Thanks [@​yanthomasdev](https://github.com/yanthomasdev)! - Clarified the warning emitted when using the experimental `json` and `json-pretty` reporters.
- [#​11198](https://github.com/biomejs/biome/pull/11198) [`ed88b13`](https://github.com/biomejs/biome/commit/ed88b13a6d95fe564aaee6c731651e7dec8266db) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Fixed [#​11171](https://github.com/biomejs/biome/issues/11171): variables referenced only inside a Svelte attachment (`{@attach ...}`) are no longer reported as unused by [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) and [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/).
- [#​11155](https://github.com/biomejs/biome/pull/11155) [`6ee17ea`](https://github.com/biomejs/biome/commit/6ee17ea2df979a67df5d1263734f28f77c6512a6) Thanks [@​dyc3](https://github.com/dyc3)! - Improved performance when printing diagnostics to the console.
- [#​11160](https://github.com/biomejs/biome/pull/11160) [`217f8ad`](https://github.com/biomejs/biome/commit/217f8adbc2f700ab4c92cb227434c2afba9f9611) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) by skipping type inference for assignment statements, which are always considered handled.
- [#​11159](https://github.com/biomejs/biome/pull/11159) [`26c23d9`](https://github.com/biomejs/biome/commit/26c23d96ced1a6eca496955fbe93279da2747346) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Fixed [#​11144](https://github.com/biomejs/biome/issues/11144): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports already-awaited optional Promise values.
- [#​11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11121](https://github.com/biomejs/biome/issues/11121): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports conditions based on an inapplicable function overload.
For example, the condition in the following code is no longer reported because `query({})` selects the overload that returns `boolean`:
```ts
declare function query(options: { initial: string }): { isPending: false };
declare function query(options: { initial?: string }): { isPending: boolean };
const { isPending } = query({});
isPending || fallback;
```
- [#​11152](https://github.com/biomejs/biome/pull/11152) [`c4fc6a9`](https://github.com/biomejs/biome/commit/c4fc6a90777358905cf99b3261a479de73d7d383) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of collecting rule timings with `--profile-rules` in heavily multithreaded environments.
- [#​11128](https://github.com/biomejs/biome/pull/11128) [`4d3ff76`](https://github.com/biomejs/biome/commit/4d3ff7689c36af5149142d9a4a23165154359655) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7635](https://github.com/biomejs/biome/issues/7635): [`noDeprecatedImports`](https://biomejs.dev/linter/rules/no-deprecated-imports/) now detects deprecated ambient declarations that are exported separately.
- [#​11117](https://github.com/biomejs/biome/pull/11117) [`01f7ef5`](https://github.com/biomejs/biome/commit/01f7ef58d4c19a587b01754c96b577a2a5a47418) Thanks [@​subotac](https://github.com/subotac)! - Fixed [#​11014](https://github.com/biomejs/biome/issues/11014): [`noDelete`](https://biomejs.dev/linter/rules/no-delete/) no longer reports `process.env["FOO"]` style property deletions.
- [#​11168](https://github.com/biomejs/biome/pull/11168) [`9847e68`](https://github.com/biomejs/biome/commit/9847e680ff8bb891a6c910e881af98a4fffa33c2) Thanks [@​saberoueslati](https://github.com/saberoueslati)! - Added the nursery rule [`noNonScalableViewport`](https://biomejs.dev/linter/rules/no-non-scalable-viewport), which reports viewport metadata that disables user scaling with `user-scalable=no`.
For example:
```html
<meta name="viewport" content="width=device-width, user-scalable=no" />
```
- [#​11154](https://github.com/biomejs/biome/pull/11154) [`a1d6b1f`](https://github.com/biomejs/biome/commit/a1d6b1fc544c6c6cc1dd38f87898d34738fbe97b) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of [`noImportCycles`](https://biomejs.dev/linter/rules/no-import-cycles/) by skipping graph traversals for imports that cannot be part of a cycle.
- [#​11175](https://github.com/biomejs/biome/pull/11175) [`d96d6dd`](https://github.com/biomejs/biome/commit/d96d6dd07702828f7e7a5ce59f8fc00006f6ee46) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the `syntax` descriptor of `@property` rules.
### [`v2.5.6`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#256)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.5...@biomejs/biome@2.5.6)
##### Patch Changes
- [#​11035](https://github.com/biomejs/biome/pull/11035) [`0e4b03b`](https://github.com/biomejs/biome/commit/0e4b03be71b32120c6326e58e046260bcf5d3231) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a performance regression in [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) that caused type inference to run repeatedly while linting a file.
- [#​11043](https://github.com/biomejs/biome/pull/11043) [`22ec076`](https://github.com/biomejs/biome/commit/22ec076462d4590ea7c95f7693b69040c32a38aa) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting for multiline function arguments preceded by comments:
```diff
.example {
value: outer(
1,
/* comment */
nested(
- first,
- second
- )
+ first,
+ second
+ )
);
}
```
- [#​11007](https://github.com/biomejs/biome/pull/11007) [`c9acb25`](https://github.com/biomejs/biome/commit/c9acb25acbce7a6f632b5041ec546a604aea4343) Thanks [@​BTF-Kabir-2020](https://github.com/BTF-Kabir-2020)! - Fixed [#​9195](https://github.com/biomejs/biome/issues/9195): [`useHookAtTopLevel`](https://biomejs.dev/linter/rules/use-hook-at-top-level/) no longer reports hooks in named `forwardRef` components that receive a `ref` parameter.
- [#​10152](https://github.com/biomejs/biome/pull/10152) [`50a9bd8`](https://github.com/biomejs/biome/commit/50a9bd84df852de305e94a91fb57f6b3b1378187) Thanks [@​Zelys-DFKH](https://github.com/Zelys-DFKH)! - Fixed [#​10131](https://github.com/biomejs/biome/issues/10131): Biome now correctly parses curried arrow functions in ternary consequents when the inner arrow's parameters use a destructuring pattern, e.g. `cond ? (x) => ({ a, b }) => body : alt`.
- [#​11105](https://github.com/biomejs/biome/pull/11105) [`8ffe2b9`](https://github.com/biomejs/biome/commit/8ffe2b9f2f9224921a0bad4a772e6611006351e5) Thanks [@​dadavidtseng](https://github.com/dadavidtseng)! - Fixed [#​11092](https://github.com/biomejs/biome/issues/11092): The [`noUselessTernary`](https://biomejs.dev/linter/rules/no-useless-ternary/) quick fix now preserves operator spacing when simplifying or inverting boolean ternary expressions.
- [#​10533](https://github.com/biomejs/biome/pull/10533) [`5809875`](https://github.com/biomejs/biome/commit/580987506a32cdde2f5498e0f712e3493ef9adde) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed [#​10515](https://github.com/biomejs/biome/issues/10515): `biome check --write` was not idempotent on Svelte files — multi-line template literals in `<script>` blocks and block comments in `<style>` blocks gained an extra indent level on every run.
- [#​11040](https://github.com/biomejs/biome/pull/11040) [`0abb620`](https://github.com/biomejs/biome/commit/0abb620b2f0bd748bf272a2bc56aa02f5a6d0fee) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed an issue where the HTML formatter would duplicate a comment placed directly before a Svelte `{@const ...}` or `{@debug ...}` block. The duplication compounded on every subsequent `--write`, causing the file to grow exponentially.
- [#​10858](https://github.com/biomejs/biome/pull/10858) [`6d18204`](https://github.com/biomejs/biome/commit/6d182043b1de76f8668464bfa5c295161135ee0e) Thanks [@​ruidosujeira](https://github.com/ruidosujeira)! - Fixed [#​10839](https://github.com/biomejs/biome/issues/10839): Svelte `{#each}` array destructuring no longer includes spaces inside square brackets, and multiline bind function expressions now indent their getter, setter, and function body correctly.
- [#​11009](https://github.com/biomejs/biome/pull/11009) [`2c36626`](https://github.com/biomejs/biome/commit/2c36626bed58e63e49ecca8a40c717adae4c91ac) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the accuracy of type-aware lint rules by resolving more inferred types. For example, [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) now detects floating Promises returned by aliased callbacks and arrays of Promises created by async mapping callbacks.
The following statements are now reported:
```ts
type AsyncCallback = () => Promise<void>;
declare const callback: AsyncCallback;
callback();
[1, 2, 3].map(async (value) => value);
```
- [#​10973](https://github.com/biomejs/biome/pull/10973) [`9cb044c`](https://github.com/biomejs/biome/commit/9cb044cf2c8971642942c302a6d2b0000964c2f0) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed false positives in [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) when generic-constraint, normalization, substitution, or structural return-type comparison cannot complete. The rule now suppresses diagnostics rather than suggesting a return type derived from partial information. For example, this unresolved return type is no longer reported:
```ts
function unresolvedReturnType(): MissingType {
return "value" as const;
}
```
- [#​11071](https://github.com/biomejs/biome/pull/11071) [`15047a2`](https://github.com/biomejs/biome/commit/15047a2fff2aa2a5c0c096257b4718b0141431be) Thanks [@​dyc3](https://github.com/dyc3)! - The HTML parser now accepts mixed-case `doctype` declarations.
- [#​11030](https://github.com/biomejs/biome/pull/11030) [`cc90e65`](https://github.com/biomejs/biome/commit/cc90e65a6b14388a5fab1d893f782055fac34f91) Thanks [@​marschattha](https://github.com/marschattha)! - The `rdjson` reporter now populates the [severity](https://github.com/reviewdog/reviewdog/blob/master/proto/rdf/reviewdog.proto) field of each diagnostic (`ERROR`, `WARNING`, or `INFO`), so tools consuming Reviewdog Diagnostic Format output no longer need to assume a default severity.
- [#​11009](https://github.com/biomejs/biome/pull/11009) [`2c36626`](https://github.com/biomejs/biome/commit/2c36626bed58e63e49ecca8a40c717adae4c91ac) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a performance regression in type-aware JavaScript lint rules by inferring only requested types and memoizing export resolution.
- [#​11056](https://github.com/biomejs/biome/pull/11056) [`903b177`](https://github.com/biomejs/biome/commit/903b1770528040484b5f8b71f652130a8e6bd960) Thanks [@​dyc3](https://github.com/dyc3)! - Added support for Svelte declaration tags using `let` and `const`. Biome can now parse, format, and lint bindings declared in these tags.
- [#​11045](https://github.com/biomejs/biome/pull/11045) [`89c27c6`](https://github.com/biomejs/biome/commit/89c27c62541d2b628247563441e48f2303e53f4b) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the performance of Biome formatter up to \~7% across the board.
- [#​9806](https://github.com/biomejs/biome/pull/9806) [`781d68d`](https://github.com/biomejs/biome/commit/781d68dae5df6ad188efc8afb0972112654614fe) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noJsRestrictedProperties`](https://biomejs.dev/linter/rules/no-js-restricted-properties/), which ports ESLint's `no-restricted-properties` rule. Biome now flags restricted member access and object destructuring, and `biome migrate eslint` preserves the rule's options.
### [`v2.5.5`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#255)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.4...@biomejs/biome@2.5.5)
##### Patch Changes
- [#​10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) for unions of bigint literals. The rule now reports missing bigint cases and compares bigint literals by value, including binary, octal, hexadecimal, and separator-containing spellings. For example, this switch now reports the missing `2n` case:
```ts
declare const value: 1n | 2n;
switch (value) {
case 1n:
break;
}
```
- [#​10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed false positives in [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/) and [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing/) when member, stringification, or nullish inference cannot complete. These rules now suppress diagnostics instead of reporting from partial type information. For example, neither expression is reported when a recursive type cannot be fully resolved:
```ts
type Recursive = Recursive;
declare const value: Recursive;
String(value);
value || "fallback";
```
- [#​10977](https://github.com/biomejs/biome/pull/10977) [`0bf7486`](https://github.com/biomejs/biome/commit/0bf748653e488d0b959d39847641438cdb28188b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10922](https://github.com/biomejs/biome/issues/10922): the action [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) no longer triggers for HTML instructions.
- [#​10957](https://github.com/biomejs/biome/pull/10957) [`cf263c4`](https://github.com/biomejs/biome/commit/cf263c4700e9f24115e541d1f142934a9b2d878f) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`noThenProperty`](https://biomejs.dev/linter/rules/no-then-property/) failing to detect `Object.fromEntries`, `Object.defineProperty`, and `Reflect.defineProperty` calls with comments between their tokens.
- [#​10983](https://github.com/biomejs/biome/pull/10983) [`edc0ed7`](https://github.com/biomejs/biome/commit/edc0ed738ab8da3d512d527196684bd668090854) Thanks [@​ayaangazali](https://github.com/ayaangazali)! - Fixed [#​10980](https://github.com/biomejs/biome/issues/10980): [`useAriaPropsSupportedByRole`](https://biomejs.dev/linter/rules/use-aria-props-supported-by-role/) no longer reports false positives when the attribute that determines an element's implicit ARIA role is written as a shorthand attribute, such as `<a {href} aria-label="...">` in Astro and Svelte files.
Shorthand attributes are now taken into account when computing the implicit role, so the anchor above correctly resolves to the `link` role instead of `generic`.
- [#​10889](https://github.com/biomejs/biome/pull/10889) [`89526e3`](https://github.com/biomejs/biome/commit/89526e3858c437408ec9ff192c35a866ad991d1b) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatter casing for syntax-owned names while preserving author-defined names, including scoped keyframes and container scroll-state queries.
```diff
- A:HOVER { COLOR: INITIAL; }
+ A:hover { color: initial; }
- @KEYFRAMES :GLOBAL KeepFrames { FROM { COLOR: RED; } }
+ @keyframes :GLOBAL KeepFrames { from { color: RED; } }
- @CONTAINER scroll-state((SCROLLED: TOP) AND (STUCK)) { A:HOVER { COLOR: RED; } }
+ @container scroll-state((SCROLLED: TOP) AND (STUCK)) { A:hover { color: RED; } }
```
- [#​10964](https://github.com/biomejs/biome/pull/10964) [`794ccd0`](https://github.com/biomejs/biome/commit/794ccd0528345c4eaa87af1d86f02475277a0a22) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting for comments between declaration values and `!important`.
```diff
-a { color: /* before */ /* after */ red !important; }
+a { color: /* before */ red /* after */ !important; }
```
- [#​10993](https://github.com/biomejs/biome/pull/10993) [`b7a9694`](https://github.com/biomejs/biome/commit/b7a969425d4292fc7c50440da7aea41ce5c9a9c2) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed the CSS formatter to preserve comments on the correct side of selector combinators and before declaration blocks.
```diff
-.before > /* comment */ .after {}
+.before /* comment */ > .after {}
```
It now also keeps selectors with escaped newlines in attribute values inline when they fit.
```diff
-div
- span[foo="bar\
+div span[foo="bar\
value"] {}
```
- [#​10978](https://github.com/biomejs/biome/pull/10978) [`8ebafe1`](https://github.com/biomejs/biome/commit/8ebafe1c7489f1f7af379b8e52b8ad063c82d28a) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10870](https://github.com/biomejs/biome/issues/10870): [`noUnresolvedImports`](https://biomejs.dev/linter/rules/no-unresolved-imports/) no longer reports false positives such as `import type { NextRequest } from "next/server"`.
- [#​10901](https://github.com/biomejs/biome/pull/10901) [`68c10e6`](https://github.com/biomejs/biome/commit/68c10e672fc886b31423b18be01e873d3bf77f43) Thanks [@​Socialpranker](https://github.com/Socialpranker)! - Fixed [#​10622](https://github.com/biomejs/biome/issues/10622): the HTML/Vue parser no longer panics on the argument-less `v-bind` shorthand (`:="props"`).
This syntax is valid Vue and equivalent to `v-bind="props"`, so the parser now accepts it (along with the longhand `v-bind:="props"`) instead of crashing while building a diagnostic for a missing argument.
- [#​10936](https://github.com/biomejs/biome/pull/10936) [`7df46f5`](https://github.com/biomejs/biome/commit/7df46f5be0880a02cb37453f01b83c1ba59b1e44) Thanks [@​ematipico](https://github.com/ematipico)! - Improved generic tuple inference for [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/). The rule now recognizes specialised tuple element types returned through generic aliases.
- [#​10941](https://github.com/biomejs/biome/pull/10941) [`f787725`](https://github.com/biomejs/biome/commit/f7877258271e20523d5c673e62912fce1d85cd56) Thanks [@​siketyan](https://github.com/siketyan)! - Fixed [`#10855`](https://github.com/biomejs/biome/issues/10855): Biome now supports parsing and formatting CSS custom media queries declared with [`@custom-media`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@custom-media).
- [#​10969](https://github.com/biomejs/biome/pull/10969) [`72d309b`](https://github.com/biomejs/biome/commit/72d309b655cee70473e20b061f5a45112139688c) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where Biome logs became too verbose, dumping information not relevant to user's operations.
- [`e62f6b6`](https://github.com/biomejs/biome/commit/e62f6b61461227bbfd57fdf1b50b2dc8c01ea5a0) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10963](https://github.com/biomejs/biome/issues/10963): Biome no longer panics when a type-aware rule such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) checks a call to a function with multiple call signatures imported from another module.
- [#​10931](https://github.com/biomejs/biome/pull/10931) [`899c60d`](https://github.com/biomejs/biome/commit/899c60d506115b3f62030236cbd0901bf294e6ab) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed `check --write` command. Now the command reports code frame of the formatted code, if the formatter is enabled.
- [#​10904](https://github.com/biomejs/biome/pull/10904) [`ceee4f4`](https://github.com/biomejs/biome/commit/ceee4f43dabf88d86b87c9a4ce6051b6738869c2) Thanks [@​qzwxsaedc](https://github.com/qzwxsaedc)! - Fixed [#​10892](https://github.com/biomejs/biome/issues/10892): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports a false positive when checking a member of a discriminated union that is accessed through a default type-only namespace import. The following code is no longer flagged:
```ts
import type Types from "./types";
declare function parse(): Types.Result<string>;
const result = parse();
if (!result.success) {
}
```
- [#​10962](https://github.com/biomejs/biome/pull/10962) [`f0a67f2`](https://github.com/biomejs/biome/commit/f0a67f2e56c0785595c5cf14a93dba5bb32acf2d) Thanks [@​ematipico](https://github.com/ematipico)! - Biome no longer removes embedded styles and scripts in HTML files.
- [#​11000](https://github.com/biomejs/biome/pull/11000) [`5039a1e`](https://github.com/biomejs/biome/commit/5039a1ee35771d0193de65a6326781313ab77afb) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a bug where closing one editor stopped a shared Biome daemon used by other editors. LSP proxy processes now exit when either the editor or daemon disconnects.
- [#​10957](https://github.com/biomejs/biome/pull/10957) [`cf263c4`](https://github.com/biomejs/biome/commit/cf263c4700e9f24115e541d1f142934a9b2d878f) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of the [`noThenProperty`](https://biomejs.dev/linter/rules/no-then-property/) lint rule by about 50%.
- [#​10992](https://github.com/biomejs/biome/pull/10992) [`4bf9b21`](https://github.com/biomejs/biome/commit/4bf9b21319df240e2c5ef2e5a9cb2e9582a0e1d1) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/): The rule now reports Promise-returning callbacks where a synchronous callback is expected when calls use tuple spreads or tuple rest parameters, including generic and deeply nested tuples, and when constructor signatures come from interface or object types. Recursive or excessively nested tuple spreads use a conservative fallback so analysis terminates.
For example, the following callback is now reported.
```ts
declare function consume(...args: [number, () => void]): void;
const prefix: [number] = [1];
consume(...prefix, async () => {});
```
- [#​10915](https://github.com/biomejs/biome/pull/10915) [`b3b12b3`](https://github.com/biomejs/biome/commit/b3b12b3fe390feabbd9ba097922d6c7e56823406) Thanks [@​Functionhx](https://github.com/Functionhx)! - Added the rule [`noNegationInEqualityCheck`](https://biomejs.dev/linter/rules/no-negation-in-equality-check/). The rule flags negated expressions on the left side of strict equality checks like `!foo === bar` — due to operator precedence this evaluates as `(!foo) === bar` which is almost always a mistake for `foo !== bar`.
The rule provides an unsafe fix that flips the operator.
```js
// Invalid
!foo === bar;
!foo !== bar;
// Valid
foo !== bar;
foo === bar;
```
- [#​10970](https://github.com/biomejs/biome/pull/10970) [`bd1038b`](https://github.com/biomejs/biome/commit/bd1038be1ad110aae60bcdbe9a154c6a2fc85c14) Thanks [@​ematipico](https://github.com/ematipico)! - Improved overload selection for [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/). Biome now handles overloaded calls, overloaded constructors, rest parameters, union arguments, and generic constraints without selecting an incompatible signature. For example, `noMisusedPromises` now reports the async callback passed to the synchronous overload:
```ts
declare function consume(kind: "async", callback: () => Promise<void>): void;
declare function consume(kind: "sync", callback: () => void): void;
consume("sync", async () => {});
```
- [#​10933](https://github.com/biomejs/biome/pull/10933) [`48a4abb`](https://github.com/biomejs/biome/commit/48a4abb99d41b1241b2a5812a12247b671d0dfed) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/) to recognize bigint zero indexes.
- [#​10931](https://github.com/biomejs/biome/pull/10931) [`899c60d`](https://github.com/biomejs/biome/commit/899c60d506115b3f62030236cbd0901bf294e6ab) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an orchestration issue that could lead to deadlocks when type-aware rules are enabled.
- [#​10969](https://github.com/biomejs/biome/pull/10969) [`72d309b`](https://github.com/biomejs/biome/commit/72d309b655cee70473e20b061f5a45112139688c) Thanks [@​ematipico](https://github.com/ematipico)! - Hardened the Biome Language Server by improving its synchronisation logic.
- [#​10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed false positives in [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) and [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/) when Promise or thenable inference cannot complete. These rules now suppress diagnostics instead of treating incomplete type information as a definite result. For example, `useAwaitThenable` no longer reports `await value` when the value's thenability is unknown:
```ts
declare const value: unknown;
async function consume() {
await value;
}
```
### [`v2.5.4`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#254)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.3...@biomejs/biome@2.5.4)
##### Patch Changes
- [#​10665](https://github.com/biomejs/biome/pull/10665) [`55ff995`](https://github.com/biomejs/biome/commit/55ff995098148446b7e7fdfc19053902bb987122) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of the HTML parser slightly in our synthetic benchmarks.
- [#​10894](https://github.com/biomejs/biome/pull/10894) [`f4fb10e`](https://github.com/biomejs/biome/commit/f4fb10e176e537e8ce2cac0c3fd4c38a77f91886) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6392](https://github.com/biomejs/biome/issues/6392): On-type formatting no longer moves comments before an `if` statement into its body.
- [#​10939](https://github.com/biomejs/biome/pull/10939) [`f2799db`](https://github.com/biomejs/biome/commit/f2799db38e3d8a644207d9b8f957abea6cb3d9fa) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10930](https://github.com/biomejs/biome/issues/10930): [`noLabelWithoutControl`](https://biomejs.dev/linter/rules/no-label-without-control/) now correctly detects text interpolation in Astro, Svelte & Vue as valid accessible content.
- [#​10945](https://github.com/biomejs/biome/pull/10945) [`ae15d98`](https://github.com/biomejs/biome/commit/ae15d98bbf2222fbb34e3e31832cba9676a6d01c) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10942](https://github.com/biomejs/biome/issues/10942): Svelte directives don't throw an accidental debug log anymore.
- [#​10842](https://github.com/biomejs/biome/pull/10842) [`5e1abfe`](https://github.com/biomejs/biome/commit/5e1abfee59155b5fdca8813314371ed54c06acfb) Thanks [@​JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#​9196](https://github.com/biomejs/biome/issues/9196): `biome check --write --unsafe` no longer hangs forever when applying the [`noCommentText`](https://biomejs.dev/linter/rules/no-comment-text/) code fix.
The rule's fix now wraps the comment in a real JSX expression container (`{/* comment */}`) instead of re-inserting the braces as plain JSX text, so the fixed code is no longer reported again by the same rule.
- [#​10891](https://github.com/biomejs/biome/pull/10891) [`ecca79e`](https://github.com/biomejs/biome/commit/ecca79e8ff10f40aa676212c0db0a970c6091615) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [`#10885`](https://github.com/biomejs/biome/issues/10885): prevented a module-inference regression introduced by a housekeeping change.
- [#​10886](https://github.com/biomejs/biome/pull/10886) [`60c8043`](https://github.com/biomejs/biome/commit/60c8043527f7ccc7b505471e1042f2a4324e4d31) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10727](https://github.com/biomejs/biome/issues/10727): Biome now breaks the arguments of curried `test.each`, `it.each`, `describe.each`, and `test.for` calls when they exceed the configured line width.
```diff
- test.each([[1, 2]])("a description that is long enough to push the hugged opening line beyond the print width", (a, b) => {
- expect(a).toBe(b);
- });
+ test.each([[1, 2]])(
+ "a description that is long enough to push the hugged opening line beyond the print width",
+ (a, b) => {
+ expect(a).toBe(b);
+ },
+ );
```
- [#​10895](https://github.com/biomejs/biome/pull/10895) [`01a85f0`](https://github.com/biomejs/biome/commit/01a85f04b09f0af05b16a15c137421e312ceada5) Thanks [@​ematipico](https://github.com/ematipico)! - Biome will now remove stale Unix daemon sockets from older Biome versions when starting a newer daemon.
### [`v2.5.3`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#253)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.2...@biomejs/biome@2.5.3)
##### Patch Changes
- [#​10815](https://github.com/biomejs/biome/pull/10815) [`86613d5`](https://github.com/biomejs/biome/commit/86613d5b01eb965b460ccefbf27f168d87774aaf) Thanks [@​WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed a parser panic reported in [#​10708](https://github.com/biomejs/biome/issues/10708): Biome now recovers when unsupported CSS Modules `@value` rules or scoped `@keyframes` names end at EOF.
- [#​10534](https://github.com/biomejs/biome/pull/10534) [`da9b403`](https://github.com/biomejs/biome/commit/da9b403b6bbacc8d75d56e327a46f4ed0285913e) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) false positives in Svelte files: Svelte store subscriptions (`$store` references in templates now keep the underlying `store` binding from being flagged), and `$bindable()` props that are only written to in the script block (write-only is intentional for bindable props) are no longer reported as unused.
- [#​10827](https://github.com/biomejs/biome/pull/10827) [`098ba41`](https://github.com/biomejs/biome/commit/098ba41c99e6efaac8eb182eec258a567bb00123) Thanks [@​Aqu1bp](https://github.com/Aqu1bp)! - Fixed [#​10698](https://github.com/biomejs/biome/issues/10698): The [`noUnsafeOptionalChaining`](https://biomejs.dev/linter/rules/no-unsafe-optional-chaining/) rule now reports unsafe optional chains wrapped in TypeScript `as`, `satisfies`, type assertion, and instantiation expressions, such as `new (value?.constructor as Constructor)()`.
- [#​10773](https://github.com/biomejs/biome/pull/10773) [`3c6513d`](https://github.com/biomejs/biome/commit/3c6513d4e9a82a195785144caa9d96093c3861ff) Thanks [@​otkrickey](https://github.com/otkrickey)! - Fixed [#​10772](https://github.com/biomejs/biome/issues/10772): [`useVueValidVOn`](https://biomejs.dev/linter/rules/use-vue-valid-v-on/) no longer reports a missing handler for v-on directives using a verb modifier (`.stop` / `.prevent`) without an expression, e.g. `<div @click.stop></div>`. The rule also accepts the arg-less object syntax `<div v-on="$listeners"></div>` instead of reporting a missing event name.
- [#​10721](https://github.com/biomejs/biome/pull/10721) [`d83c66b`](https://github.com/biomejs/biome/commit/d83c66b39a820703d94100f8a6502cc6dbad26a1) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved type-aware lint rule inference for built-in globals and indexed function calls. Biome now resolves `Error(...)`, `new Error(...)`, optional `Error#stack`, and calls through indexed function values such as `handlers[0]()` more accurately.
- [#​10865](https://github.com/biomejs/biome/pull/10865) [`6450276`](https://github.com/biomejs/biome/commit/6450276764ee4794a0fcb46c139f95b68d892427) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10845](https://github.com/biomejs/biome/issues/10845). Biome Language Server no longer goes in deadlock when the scanner is enabled.
- [#​10853](https://github.com/biomejs/biome/pull/10853) [`93d8e53`](https://github.com/biomejs/biome/commit/93d8e5352454bccfbd179db03b3155776599c52c) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10840](https://github.com/biomejs/biome/issues/10840): Astro shorthand attribute syntax is now correctly being parsed from embedded nodes.
- [#​10820](https://github.com/biomejs/biome/pull/10820) [`bba3092`](https://github.com/biomejs/biome/commit/bba30920715920142e933939f6270feedca933a5) Thanks [@​JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#​10619](https://github.com/biomejs/biome/issues/10619): [`noProcessEnv`](https://biomejs.dev/linter/rules/no-process-env/) now also reports computed (bracket) member access. Previously only dot access was checked, so `process["env"]` and `env["NODE_ENV"]` (where `env` is imported from `node:process`) were missed. Both static and computed accesses are now reported.
- [#​10835](https://github.com/biomejs/biome/pull/10835) [`3447b2f`](https://github.com/biomejs/biome/commit/3447b2f5a3c430efc8e917514260af5341c5509d) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10824](https://github.com/biomejs/biome/issues/10824): [`useDomQuerySelector`](https://biomejs.dev/linter/rules/use-dom-query-selector/) now supports an `ignore` option for receiver identifiers that should not be reported.
- [#​10875](https://github.com/biomejs/biome/pull/10875) [`b12e486`](https://github.com/biomejs/biome/commit/b12e486d0f0b80d02d2208e239190f8756d39d48) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10795](https://github.com/biomejs/biome/issues/10795): `--profile-rules` now reports timings for each plugin separately as `plugin/<pluginName>`, matching the naming used by plugin suppressions, instead of aggregating all plugins under a single `plugin/plugin` entry.
- [#​10877](https://github.com/biomejs/biome/pull/10877) [`d6bc447`](https://github.com/biomejs/biome/commit/d6bc4473a210758ee49f6cad41bc69587a7cf125) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [biome-zed#164](https://github.com/biomejs/biome-zed/issues/164): Biome no longer inserts stray whitespace when format-on-type runs after closing delimiters such as `)`, `]`, and `}`.
- [#​10867](https://github.com/biomejs/biome/pull/10867) [`a21463e`](https://github.com/biomejs/biome/commit/a21463e5f616a2db5035b470cd206ac9da4d9423) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10864](https://github.com/biomejs/biome/issues/10864): Biome no longer crashes when checking or linting HTML files with unquoted attribute values such as `<textarea rows=4></textarea>`.
### [`v2.5.2`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#252)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.1...@biomejs/biome@2.5.2)
##### Patch Changes
- [#​10595](https://github.com/biomejs/biome/pull/10595) [`f458028`](https://github.com/biomejs/biome/commit/f4580289094a8fe5c85252adc3399c060bab811e) Thanks [@​pkallos](https://github.com/pkallos)! - Added the option `ignoreBooleanCoercion` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||` and `||=` used inside a `Boolean()` call, where coalescing on falsy values is intentional.
- [#​10798](https://github.com/biomejs/biome/pull/10798) [`4a32b63`](https://github.com/biomejs/biome/commit/4a32b63eb41f144dc8faf6b5cdb05e1de5dbcb63) Thanks [@​pkallos](https://github.com/pkallos)! - Added the option `ignorePrimitives` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||`, `||=`, and ternary expressions whose non-nullish operands are all primitives the option opts out of. Use `true` to ignore all primitives, or an object selecting `string`, `number`, `boolean`, or `bigint`.
- [#​10545](https://github.com/biomejs/biome/pull/10545) [`f3d4c00`](https://github.com/biomejs/biome/commit/f3d4c0082676c5188e9a6aa516318c7e3d59bda6) Thanks [@​Mokto](https://github.com/Mokto)! - Added the new nursery rule [`noSvelteUnnecessaryStateWrap`](https://biomejs.dev/linter/rules/no-svelte-unnecessary-state-wrap/), which reports unnecessary `$state()` wrapping of classes from `svelte/reactivity` that are already reactive.
```svelte
<script>
import { SvelteMap } from "svelte/reactivity";
const map = $state(new SvelteMap()); // redundant
</script>
```
- [#​10752](https://github.com/biomejs/biome/pull/10752) [`f62fb8b`](https://github.com/biomejs/biome/commit/f62fb8b53092fe85e16f9d4ea0e584fee7031ab5) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10739](https://github.com/biomejs/biome/issues/10739). Now the rule [`useValidAutocomplete`](https://biomejs.dev/linter/rules/use-valid-autocomplete/) correctly flags the `autoComplete` attribute.
- [#​10796](https://github.com/biomejs/biome/pull/10796) [`f1b3ab2`](https://github.com/biomejs/biome/commit/f1b3ab2c09522a52c93f669ce679675237b96813) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10768](https://github.com/biomejs/biome/issues/10768). Improved the performance of the Biome Language Server by cancelling certain in-flight operations when there are fast updates.
- [#​10719](https://github.com/biomejs/biome/pull/10719) [`aa649b5`](https://github.com/biomejs/biome/commit/aa649b586a2221bf058af7ce80af6faa11faf846) Thanks [@​minseong0324](https://github.com/minseong0324)! - Fixed [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) false positive on returns that use a widening type assertion: `"a" as string` is no longer reported as misleading. The rule now also reports a literal-pinning assertion such as `false as false`, matching the existing `as const` behavior.
```ts
// No longer flagged (returns are `string`):
function getValue(b: boolean): string {
if (b) return "a" as string;
return "b" as string;
}
// Now also reported, like `as const` (returns `false`):
function isReady(): boolean {
return false as false;
}
```
- [#​10678](https://github.com/biomejs/biome/pull/10678) [`8f073a7`](https://github.com/biomejs/biome/commit/8f073a7cd72b4cf46c2ebf2bc08f4068fc4b5e34) Thanks [@​PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#​7718](https://github.com/biomejs/biome/issues/7718): Biome now correctly parses CSS nesting selectors when `&` appears as a trailing sub-selector after a type selector, e.g. `h1& { color: red; }`.
- [#​10756](https://github.com/biomejs/biome/pull/10756) [`5ec965a`](https://github.com/biomejs/biome/commit/5ec965a2620dec7cb40aa4946ba1d41408b11fd9) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatter output for selector lists with `allowWrongLineComments` and `//` comments after a selector comma. Biome now keeps the selector before the line comment inline instead of breaking it across descendant combinators.
```diff
-.powerPathNavigator
- .helm
- button.pressedButton, // pressed
+.powerPathNavigator .helm button.pressedButton, // pressed
.powerPathNavigator .helm button:active:not(.disabledButton) {
}
```
- [#​10757](https://github.com/biomejs/biome/pull/10757) [`6232fcd`](https://github.com/biomejs/biome/commit/6232fcdef77471e6a6a74bcc33ff7b2b2a9f85a2) Thanks [@​PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#​8269](https://github.com/biomejs/biome/issues/8269): the CSS parser now accepts Tailwind `@variant` and `@utility` names that start with a digit, such as the `2xl` breakpoint.
```css
@utility container {
@variant 2xl {
max-width: 1400px;
}
}
```
- [#​10777](https://github.com/biomejs/biome/pull/10777) [`575ced6`](https://github.com/biomejs/biome/commit/575ced6fd7fe3597fdec36e572763e4a5d590244) Thanks [@​WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#​10708](https://github.com/biomejs/biome/issues/10708): the GitLab reporter now handles `--verbose` diagnostics filtering correctly.
- [#​10281](https://github.com/biomejs/biome/pull/10281) [`0efe244`](https://github.com/biomejs/biome/commit/0efe2442e9b81d83f7332fd792ad6096678f8b2c) Thanks [@​Zelys-DFKH](https://github.com/Zelys-DFKH)! - Fixed a bug where GritQL patterns rejected positional (unkeyed) arguments.
- [#​10758](https://github.com/biomejs/biome/pull/10758) [`e36fd8a`](https://github.com/biomejs/biome/commit/e36fd8a9f1314744276df515a1137f21802d3aa5) Thanks [@​henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#​10697](https://github.com/biomejs/biome/issues/10697): The formatter no longer removes the parentheses around an `await` or `yield` expression used as the target of a TypeScript instantiation expression. For example, `(await makeFactory)<Value>` is no longer reformatted to `await makeFactory<Value>`, which would change the meaning of the code.
- [#​10586](https://github.com/biomejs/biome/pull/10586) [`3617094`](https://github.com/biomejs/biome/commit/3617094f00e90f7167ff20baf3c12b5014188b35) Thanks [@​IxxyDev](https://github.com/IxxyDev)! - Fixed [#​9568](https://github.com/biomejs/biome/issues/9568): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports a false positive when calling an overloaded function and the selected overload does not return a promise.
```ts
function bestEffort(cb: () => Promise<number>): Promise<number>;
function bestEffort(cb: () => number): number;
function bestEffort(
cb: () => number | Promise<number>,
): Promise<number> | number {
return cb() as Promise<number> | number;
}
// This resolves to the second overload, which returns `number`, so it is no
// longer flagged as a floating promise.
bestEffort(() => 42);
```
- [#​10766](https://github.com/biomejs/biome/pull/10766) [`7aff4c1`](https://github.com/biomejs/biome/commit/7aff4c11900579a62dc27ef4e02a4c4760fbbff4) Thanks [@​JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#​2862](https://github.com/biomejs/biome/issues/2862): [`noInteractiveElementToNoninteractiveRole`](https://biomejs.dev/linter/rules/no-interactive-element-to-noninteractive-role/) no longer reports custom elements (a tag name containing a dash, e.g. `<my-button role="img" />`). Per the [W3C HTML-ARIA specification](https://www.w3.org/TR/html-aria/#el-autonomous-custom-element), a custom element may be given any role or none.
- [#​10680](https://github.com/biomejs/biome/pull/10680) [`771daa4`](https://github.com/biomejs/biome/commit/771daa4f7d229a8754f47923f03b899dc0fc5630) Thanks [@​WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed [#​10635](https://github.com/biomejs/biome/issues/10635): Biome now recognizes chained
table tests such as `test.concurrent.each()` and `it.concurrent.each()` as test calls, fixing
`noMisplacedAssertion` false positives and improving formatting for those test declarations.
- [#​10759](https://github.com/biomejs/biome/pull/10759) [`34570b5`](https://github.com/biomejs/biome/commit/34570b5b793c44e978b12589dafcfda22dba7df1) Thanks [@​henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#​10636](https://github.com/biomejs/biome/issues/10636): [noStaticElementInteractions](https://biomejs.dev/linter/rules/no-static-element-interactions/) no longer reports a false positive for event handlers on Svelte special elements such as `<svelte:window>`, `<svelte:document>`, and `<svelte:body>`. These are not real DOM elements, so they are now ignored by the rule.
- [#​10741](https://github.com/biomejs/biome/pull/10741) [`bd2364e`](https://github.com/biomejs/biome/commit/bd2364e3d077e3a77addcab6dbe127db38654e4a) Thanks [@​JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#​6686](https://github.com/biomejs/biome/issues/6686): the `rage` command now respects the `--config-path` option and the `BIOME_CONFIG_PATH` environment variable when loading the Biome configuration. Previously it always used the default configuration resolution and reported the configuration as `Not set` when no `biome.json` existed in the working directory.
- [#​10763](https://github.com/biomejs/biome/pull/10763) [`2c3e82d`](https://github.com/biomejs/biome/commit/2c3e82d0235ad2f8331744aefc708d1b71f7177c) Thanks [@​Aqu1bp](https://github.com/Aqu1bp)! - Fixed [#​10742](https://github.com/biomejs/biome/issues/10742): [`noSolidDestructuredProps`](https://biomejs.dev/linter/rules/no-solid-destructured-props) now reports destructured props in Solid function components and JSX children.
- [#​10606](https://github.com/biomejs/biome/pull/10606) [`a4cc4ab`](https://github.com/biomejs/biome/commit/a4cc4ab0b01a8ef1731d37cb44bccc5522876f2e) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed false positives in `noUnusedImports`, `noUnusedVariables`, and `useImportType` for Svelte components that use both a `<script module>` and a `<script>` block. The two blocks compile to a single module and share a top-level scope, so a binding (import, function, or variable) declared in one block and used only in the other is no longer reported as unused.
- [#​10767](https://github.com/biomejs/biome/pull/10767) [`36d5aa7`](https://github.com/biomejs/biome/commit/36d5aa77d751bf33485cd2c92d89e4c5764e1e50) Thanks [@​otkrickey](https://github.com/otkrickey)! - Fixed [#​10754](https://github.com/biomejs/biome/issues/10754): [`useVueValidVBind`](https://biomejs.dev/linter/rules/use-vue-valid-v-bind/) no longer reports the Vue 3.4+ same-name shorthand as missing a value. `:foo` and `v-bind:foo` are now accepted as equivalent to `:foo="foo"`, while `v-bind`, `v-bind:[dynamicArg]`, and `:[dynamicArg]` without a value continue to be reported.
- [#​10775](https://github.com/biomejs/biome/pull/10775) [`a918af0`](https://github.com/biomejs/biome/commit/a918af0ba827a7fd60a12c96b58daebc8af61db2) Thanks [@​WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#​10708](https://github.com/biomejs/biome/issues/10708): `biome rage` didn't detect running Biome daemon pipes on Windows.
- [#​10730](https://github.com/biomejs/biome/pull/10730) [`5a2e65b`](https://github.com/biomejs/biome/commit/5a2e65b9929ef0f2294c20e028fd396d760d2b26) Thanks [@​dinocosta](https://github.com/dinocosta)! - Fixed an issue where Biome was resolving [the well-known Zed settings file](https://biomejs.dev/guides/configure-biome/#well-known-files) from the wrong location on macOS and Windows.
- [#​10807](https://github.com/biomejs/biome/pull/10807) [`d97fffe`](https://github.com/biomejs/biome/commit/d97fffe0aba04cddec66943d6bff3e99d440b451) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where `.scss` files were incorrectly analyzed when running `biome check`.
- [#​10672](https://github.com/biomejs/biome/pull/10672) [`53c6efc`](https://github.com/biomejs/biome/commit/53c6efcd3e5e2769bf8edbe14b8c06ee9fda52d2) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed a bug where Biome incorrectly formatted snippets that have parsing errors.
- [#​10719](https://github.com/biomejs/biome/pull/10719) [`aa649b5`](https://github.com/biomejs/biome/commit/aa649b586a2221bf058af7ce80af6faa11faf846) Thanks [@​minseong0324](https://github.com/minseong0324)! - Fixed [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/) false positive when awaiting a custom thenable that is not the global `Promise`. A value with a callable `then` member is now recognized as awaitable.
```ts
interface Thenable<T> {
then(onfulfilled: (value: T) => void): void;
}
declare const t: Thenable<number>;
async function f() {
await t;
}
```
- [#​10734](https://github.com/biomejs/biome/pull/10734) [`4396496`](https://github.com/biomejs/biome/commit/43964961c88ca0f93ee83d10621844fa2dc7515c) Thanks [@​BangDori](https://github.com/BangDori)! - Fixed [#​10708](https://github.com/biomejs/biome/issues/10708): `biome migrate` now preserves trivia when migrating the deprecated `recommended` option to `preset`.
- [#​10683](https://github.com/biomejs/biome/pull/10683) [`ae31a00`](https://github.com/biomejs/biome/commit/ae31a004a20ed33d6aa35d5ec8bb4c433273a517) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10657](https://github.com/biomejs/biome/issues/10657) [#​10671](https://github.com/biomejs/biome/issues/10671) [#​10661](https://github.com/biomejs/biome/issues/10661) [#​10637](https://github.com/biomejs/biome/issues/10637) [#​10718](https://github.com/biomejs/biome/issues/10718): HTML rules now correctly handle dynamic attributes.
- [#​10746](https://github.com/biomejs/biome/pull/10746) [`54e8239`](https://github.com/biomejs/biome/commit/54e8239bba3f598d7923ac1e446d658714ea7832) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't correctly detect styles defined inside the Astro directive `is:global`.
- [#​10770](https://github.com/biomejs/biome/pull/10770) [`dd1429c`](https://github.com/biomejs/biome/commit/dd1429c604f58b89524a3f5329e2920d198e8d9f) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the Biome Language Server DX by orchestrating certain operations, so that they won't block the editor during typing. This improvement is more visible in large documents.
- [#​10473](https://github.com/biomejs/biome/pull/10473) [`d9b5133`](https://github.com/biomejs/biome/commit/d9b5133de7e211b22f4531fe220070690a18c8d1) Thanks [@​Mokto](https://github.com/Mokto)! - Improved [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/), [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/), [`noUnusedFunctionParameters`](https://biomejs.dev/linter/rules/no-unused-function-parameters/), and [`useImportType`](https://biomejs.dev/linter/rules/use-import-type/) for Svelte, Vue, and Astro files (with `html.experimentalFullSupportEnabled`). Bindings used only in the template — including component tags, attribute interpolations, directives, `bind:` shorthand, and snippet parameters — are no longer reported as unused, while genuinely unused ones still are.
- [#​10796](https://github.com/biomejs/biome/pull/10796) [`f1b3ab2`](https://github.com/biomejs/biome/commit/f1b3ab2c09522a52c93f669ce679675237b96813) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where the Biome Language Server didn't enable project or type-aware lint rules, even when they were explicitly enabled.
- [#​10746](https://github.com/biomejs/biome/pull/10746) [`54e8239`](https://github.com/biomejs/biome/commit/54e8239bba3f598d7923ac1e446d658714ea7832) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't detect styles declared inside HTML documents.
- [#​10774](https://github.com/biomejs/biome/pull/10774) [`bde945b`](https://github.com/biomejs/biome/commit/bde945bee29cb566086828ad788153d9111a125a) Thanks [@​pattrickrice](https://github.com/pattrickrice)! - Fixed [#​10268](https://github.com/biomejs/biome/issues/10268) where a race condition resulted in internal errors such as: `The file biome.json does not exist in the workspace`.
### [`v2.5.1`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2513)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.0...@biomejs/biome@2.5.1)
##### Patch Changes
- [#​11379](https://github.com/biomejs/biome/pull/11379) [`07a0073`](https://github.com/biomejs/biome/commit/07a0073c1e1b1de323292968b8988cc6f79ec5c7) Thanks [@​Netail](https://github.com/Netail)! - Added the nursery rule [`useLayeredStyles`](https://biomejs.dev/linter/rules/use-layered-styles/), which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.
```css
/* Invalid */
@import 'foo.css';
.my-style {
color: red;
}
/* Valid */
@import 'foo.css' layer(base);
@layer base {
.my-style {
color: red;
}
}
```
- [#​11667](https://github.com/biomejs/biome/pull/11667) [`e997900`](https://github.com/biomejs/biome/commit/e997900c3eaf9d5efaf1ca12a067a962e1a04d0b) Thanks [@​devtechedge](https://github.com/devtechedge)! - Added the nursery rule [`useBetterDomTraversing`](https://biomejs.dev/linter/rules/use-better-dom-traversing), which prefers `.firstChild`, `.firstElementChild`, `.closest()`, and merged `.querySelector()` calls over positional DOM traversal.
```js
element.childNodes[0];
element.children[0];
element.parentElement.parentElement;
element.querySelector("a").querySelector("b");
```
- [#​11620](https://github.com/biomejs/biome/pull/11620) [`20e513a`](https://github.com/biomejs/biome/commit/20e513af6fb0127854f4eb5cb9edee0f20d1b543) Thanks [@​jakeleventhal](https://github.com/jakeleventhal)! - Fixed [#​11610](https://github.com/biomejs/biome/issues/11610), [#​11611](https://github.com/biomejs/biome/issues/11611), [#​11612](https://github.com/biomejs/biome/issues/11612), [#​11615](https://github.com/biomejs/biome/issues/11615), and [#​11616](https://github.com/biomejs/biome/issues/11616): Biome no longer fully infers an imported generic declaration just to apply its type arguments, restoring type-aware lint performance for large libraries such as Zod. This improves [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing), and [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands).
- [#​11657](https://github.com/biomejs/biome/pull/11657) [`e322040`](https://github.com/biomejs/biome/commit/e32204014687469e6c6f3684d32caf56311cc118) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7495](https://github.com/biomejs/biome/issues/7495): [`noUselessConstructor`](https://biomejs.dev/linter/rules/no-useless-constructor/) now ignores TypeScript constructors that forward at least one argument to `super`, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7076](https://github.com/biomejs/biome/issues/7076): [`useAriaPropsForRole`](https://biomejs.dev/linter/rules/use-aria-props-for-role) and [`useFocusableInteractive`](https://biomejs.dev/linter/rules/use-focusable-interactive) no longer report non-focusable elements with `role="separator"`. A separator with an explicit `tabIndex` or `tabindex` still requires `aria-valuenow`.
- [#​11627](https://github.com/biomejs/biome/pull/11627) [`23aad6d`](https://github.com/biomejs/biome/commit/23aad6df8f71bd9b134633c43d2334771687d10d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6571](https://github.com/biomejs/biome/issues/6571) so Grit plugins can capture and inspect multiple named import specifiers.
- [#​11631](https://github.com/biomejs/biome/pull/11631) [`00dbd3a`](https://github.com/biomejs/biome/commit/00dbd3a30489617d5bb55466006ac9977612a23b) Thanks [@​ematipico](https://github.com/ematipico)! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.
- [#​11628](https://github.com/biomejs/biome/pull/11628) [`a2f8ff7`](https://github.com/biomejs/biome/commit/a2f8ff7a1eb01f5c91e7154937e17f761863e3bc) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noXorAsExponentiation`](https://biomejs.dev/linter/rules/no-xor-as-exponentiation/), which reports the bitwise XOR operator `^` between two decimal integer literals, where the exponentiation operator `**` was likely intended.
```js
const kibibyte = 2 ^ 10; // 8, not 1024
```
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7192](https://github.com/biomejs/biome/issues/7192): [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) now considers compound assignments such as `??=` to read and use private class members.
- [#​11676](https://github.com/biomejs/biome/pull/11676) [`840a52a`](https://github.com/biomejs/biome/commit/840a52ad14b027e21661a9121b316ccac139d736) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​11672](https://github.com/biomejs/biome/issues/11672) and [#​11671](https://github.com/biomejs/biome/issues/11671) by disabling the experimental capitalized-call and effect-dependency checks in [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/), matching their exclusion from upstream's recommended lint preset. Valid calls such as `Intl.NumberFormat()` and captures of variables declared inside effects no longer produce these diagnostics.
- [#​11660](https://github.com/biomejs/biome/pull/11660) [`49485ed`](https://github.com/biomejs/biome/commit/49485eda65813e5b7e2be68cdd56ffd90674f713) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​11653](https://github.com/biomejs/biome/issues/11653): Astro template suppression comments (`{/* biome-ignore lint: reason */}`) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.
- [#​11664](https://github.com/biomejs/biome/pull/11664) [`9a73b9c`](https://github.com/biomejs/biome/commit/9a73b9cc4bb1000336dc25704546f4d63a9bb326) Thanks [@​dyc3](https://github.com/dyc3)! - Improved the performance of [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/).
- [#​11661](https://github.com/biomejs/biome/pull/11661) [`5341b3f`](https://github.com/biomejs/biome/commit/5341b3fb9c7bae8ce2426d32e6e72aed9637a82f) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7479](https://github.com/biomejs/biome/issues/7479). [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now treats Unicode escapes in identifiers as the same binding as their decoded spelling.
- [#​11630](https://github.com/biomejs/biome/pull/11630) [`62e1fc5`](https://github.com/biomejs/biome/commit/62e1fc59621b6ab5c3988ae36b6591180e07d08f) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.
```diff
<span>
- {head.median - base.median >= 0 ? "+" : "−"}
- {formatMs(Math.abs(head.median - base.median))}
+ {head.median - base.median >= 0 ? "+" : "−"}{formatMs(Math.abs(head.median - base.median))}
</span>
```
- [#​11658](https://github.com/biomejs/biome/pull/11658) [`ed4bfa4`](https://github.com/biomejs/biome/commit/ed4bfa4a1de63241a7c3586ff12d7f990cf84303) Thanks [@​fredrikblau](https://github.com/fredrikblau)! - Fixed [#​11644](https://github.com/biomejs/biome/issues/11644): [`useHeadingContent`](https://biomejs.dev/linter/rules/use-heading-content/) no longer reports headings that render their text with a directive: `set:html` and `set:text` in Astro files, `v-html` and `v-text` in Vue files.
```astro
<h1 set:html={heading} />
<h2 set:text={heading}></h2>
```
```vue
<template>
<h1 v-html="heading"></h1>
<h2 v-text="heading"></h2>
</template>
```
- [#​11613](https://github.com/biomejs/biome/pull/11613) [`47d7383`](https://github.com/biomejs/biome/commit/47d7383d049b36ff8eaba50912176928143dd9e9) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the performance of Biome Formatter up to \~50% in some cases.
- [#​11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6974](https://github.com/biomejs/biome/issues/6974), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported TypeScript private constructor properties read through object destructuring from `this` as unused.
- [#​11618](https://github.com/biomejs/biome/pull/11618) [`21a10cf`](https://github.com/biomejs/biome/commit/21a10cfcac4db8044e8bff6b24d9b1e197c2b343) Thanks [@​siketyan](https://github.com/siketyan)! - Fixed [#​11605](https://github.com/biomejs/biome/issues/11605): Type inference now infers the type of an unannotated callback parameter from the signature of the function the callback is passed to, and honours explicit type arguments on call expressions. This improves type-aware analysis for [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/), [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/), [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/), [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands/), [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/), [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/), [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/), [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/), [`useDisposables`](https://biomejs.dev/linter/rules/use-disposables/), [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/), [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing/), [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/), and [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/). For example, `noFloatingPromises` can now detect Promises reached through such parameters:
```ts
interface Context {
doSomething(): Promise<void>;
}
declare function test(callback: (ctx: Context) => Promise<void>): void;
test(async (ctx) => {
ctx.doSomething(); // now reported as a floating promise
});
```
- [#​11698](https://github.com/biomejs/biome/pull/11698) [`b019982`](https://github.com/biomejs/biome/commit/b019982bfbf8a9db58bd16b1e5e1a241128540d4) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed parsing of unquoted CSS URLs beginning with `@` or `!`, such as `url(@/assets/icon.svg)` and `url(!font.woff2)`. Preserved escaped and non-ASCII whitespace in raw URLs during formatting.
```diff
-background-image: url(image\);
+background-image: url(image\ );
```
- [#​11622](https://github.com/biomejs/biome/pull/11622) [`c23e4c7`](https://github.com/biomejs/biome/commit/c23e4c7e7a33d3f00863d80be663678af8c2a073) Thanks [@​Netail](https://github.com/Netail)! - Added the nursery rule [`noUnsafeIframeSandbox`](https://biomejs.dev/linter/rules/no-unsafe-iframe-sandbox/), which reports `iframe` elements whose `sandbox` attribute combines `allow-scripts` and `allow-same-origin`, since that combination lets the embedded document remove its own sandboxing.
```jsx
<iframe src="https://example.com" sandbox="allow-scripts allow-same-origin" />
```
- [#​11606](https://github.com/biomejs/biome/pull/11606) [`de0528f`](https://github.com/biomejs/biome/commit/de0528f940ea41b798816e1923b2b51ffcd0b473) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended [`noSvelteAtHtmlTags`](https://biomejs.dev/linter/rules/no-svelte-at-html-tags) nursery rule, which reports Svelte `{@html}` tags that render unescaped HTML.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​6782](https://github.com/biomejs/biome/issues/6782): GritQL plugins now match captured JSX component names against code snippets such as `React.Fragment`.
- [#​11687](https://github.com/biomejs/biome/pull/11687) [`09d97d9`](https://github.com/biomejs/biome/commit/09d97d973b522c6bd95e6d26006cb4b3a221396d) Thanks [@​hori-design](https://github.com/hori-design)! - Fixed [#​11678](https://github.com/biomejs/biome/issues/11678): [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) no longer panics on files that contain non-ASCII characters. This bumps the React Compiler version.
- [#​11595](https://github.com/biomejs/biome/pull/11595) [`a64d757`](https://github.com/biomejs/biome/commit/a64d7572d5684f3555be5dc02eb1d29a16f290dc) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery Vue-domain rule [`useVueBaseImport`](https://biomejs.dev/linter/rules/use-vue-base-import/) rule, which enforces importing Vue APIs from `vue` instead of internal `@vue/*` packages.
- [#​11675](https://github.com/biomejs/biome/pull/11675) [`353cbae`](https://github.com/biomejs/biome/commit/353cbae47056f8e03b27d1d9b69e165b5b72f122) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) silently producing no diagnostics in WebAssembly builds, including the playground.
- [#​11625](https://github.com/biomejs/biome/pull/11625) [`ea20e5a`](https://github.com/biomejs/biome/commit/ea20e5a4640b4455cd12e0eb6ffaa590803c67a2) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Improved linting performance for large CSS and JSON files.
- [#​11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​7527](https://github.com/biomejs/biome/issues/7527): suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressing [`noTsIgnore`](https://biomejs.dev/linter/rules/no-ts-ignore/) now places the `biome-ignore` comment before `@ts-ignore`.
- [#​11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​8629](https://github.com/biomejs/biome/issues/8629), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported used private TypeScript method overload signatures as unused.
- [#​11669](https://github.com/biomejs/biome/pull/11669) [`579f401`](https://github.com/biomejs/biome/commit/579f401b0a97760db99d64b97b2bc29ab20e3f8a) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Improved the performance of [`noExcessiveLinesPerFile`](https://biomejs.dev/linter/rules/no-excessive-lines-per-file/) when `skipBlankLines` is `false`.
### [`v2.5.0`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#250)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.16...@biomejs/biome@2.5.0)
##### Minor Changes
- [#​9539](https://github.com/biomejs/biome/pull/9539) [`f0615fd`](https://github.com/biomejs/biome/commit/f0615fdae80fa7257fc1d0448d2027cb1acff46e) Thanks [@​ematipico](https://github.com/ematipico)! - Added a new reporter called `concise`. When `--reporter=concise` is passed the commands `format`, `lint`, `check` and `ci`, the diagnostics are printed in a compact manner:
```
! index.ts:2:10: lint/correctness/noUnusedImports: Several of these imports are unused.
! main.ts:9:7: lint/correctness/noUnusedVariables: This variable f is unused.
× index.ts:8:5: lint/suspicious/noImplicitAnyLet: This variable implicitly has the any type.
× main.ts:2:10: lint/suspicious/noRedeclare: Shouldn't redeclare 'z'. Consider to delete it or rename it.
```
- [#​9495](https://github.com/biomejs/biome/pull/9495) [`2056b23`](https://github.com/biomejs/biome/commit/2056b23812a17f9c9a9015e5b725faecb04647b5) Thanks [@​aviraldua93](https://github.com/aviraldua93)! - Added the [`useKeyWithClickEvents`](https://biomejs.dev/linter/rules/use-key-with-click-events/) a11y lint rule for HTML files (`.html`, `.vue`, `.svelte`, `.astro`). This is a port of the existing JSX rule. The rule enforces that elements with an `onclick` handler also have at least one keyboard event handler (`onkeydown`, `onkeyup`, or `onkeypress`) to ensure keyboard accessibility.
Inherently keyboard-accessible elements (`<a>`, `<button>`, `<input>`, `<select>`, `<textarea>`, `<option>`) are excluded, as are elements hidden from assistive technologies (`aria-hidden`) or with `role="presentation"` / `role="none"`.
```html
<!-- Invalid: no keyboard handler -->
<div onclick="handleClick()">Click me</div>
<!-- Valid: has keyboard handler -->
<div onclick="handleClick()" onkeydown="handleKeyDown()">Click me</div>
<!-- Valid: inherently keyboard-accessible -->
<button onclick="handleClick()">Submit</button>
```
- [#​9152](https://github.com/biomejs/biome/pull/9152) [`9ec8500`](https://github.com/biomejs/biome/commit/9ec8500dabc7305cbe04ecf27a84a1450f012c0b) Thanks [@​ematipico](https://github.com/ematipico)! - Added new nursery lint rule [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes/) for HTML, JSX, and SFC files (Vue, Astro, Svelte). The rule detects CSS class names used in `class="..."` (or `className`) attributes that are not defined in any `<style>` block or linked stylesheet reachable from the file.
```html
<!-- .typo is used but never defined -->
<html>
<head>
<style>
.button {
color: blue;
}
</style>
</head>
<body>
<div class="button typo"></div>
</body>
</html>
```
- [#​9152](https://github.com/biomejs/biome/pull/9152) [`9ec8500`](https://github.com/biomejs/biome/commit/9ec8500dabc7305cbe04ecf27a84a1450f012c0b) Thanks [@​ematipico](https://github.com/ematipico)! - Added new nursery lint rule [`noUnusedClasses`](https://biomejs.dev/linter/rules/no-unused-classes/) for CSS. The rule detects CSS class selectors that are never referenced in any HTML or JSX file that imports the stylesheet. This is a project-domain rule that requires the module graph.
```css
/* styles.css — .ghost is never used in any importing file */
.button {
color: blue;
}
.ghost {
color: red;
}
```
```jsx
/* App.jsx */
import "./styles.css";
export default () => <div className="button" />;
```
- [#​9546](https://github.com/biomejs/biome/pull/9546) [`6567efa`](https://github.com/biomejs/biome/commit/6567efa51ba074436b017e49b1d2d369e7252e74) Thanks [@​nhedger](https://github.com/nhedger)! - Added a `biome upgrade` command for standalone installations. It upgrades Homebrew installs with `brew upgrade biome`, updates manually installed binaries from the latest GitHub release, and tells npm users to upgrade with their package manager instead.
- [#​9716](https://github.com/biomejs/biome/pull/9716) [`701767a`](https://github.com/biomejs/biome/commit/701767a3c4de8bce032933588ef2b6e5e252919f) Thanks [@​faizkhairi](https://github.com/faizkhairi)! - Added the HTML version of the [`useHeadingContent`](https://biomejs.dev/linter/rules/use-heading-content/) rule. The rule now enforces that heading elements (`h1`-`h6`) have content accessible to screen readers in HTML, Vue, Svelte, and Astro files.
```html
<!-- Invalid: empty heading -->
<h1></h1>
<!-- Invalid: heading hidden from screen readers -->
<h1 aria-hidden="true">invisible content</h1>
<!-- Valid: heading with text content -->
<h1>heading</h1>
<!-- Valid: heading with accessible name -->
<h1 aria-label="Screen reader content"></h1>
```
- [#​9582](https://github.com/biomejs/biome/pull/9582) [`f437ef8`](https://github.com/biomejs/biome/commit/f437ef8b6b0eb8f909d523950cf2c543042083d5) Thanks [@​rahuld109](https://github.com/rahuld109)! - Added the HTML version of the [`useKeyWithMouseEvents`](https://biomejs.dev/linter/rules/use-key-with-mouse-events/) rule. The rule now enforces that `onmouseover` is accompanied by `onfocus` and `onmouseout` is accompanied by `onblur` in HTML, Vue, Svelte, and Astro files.
```html
<!-- Invalid: onmouseover without onfocus -->
<div onmouseover="handleMouseOver()"></div>
<!-- Valid: onmouseover paired with onfocus -->
<div onmouseover="handleMouseOver()" onfocus="handleFocus()"></div>
```
- [#​9275](https://github.com/biomejs/biome/pull/9275) [`1fdbcee`](https://github.com/biomejs/biome/commit/1fdbceea62d373f24da9c1e5cc0cdd169b573e84) Thanks [@​ff1451](https://github.com/ff1451)! - Added the new assist action [`useSortedTypeFields`](https://biomejs.dev/assist/actions/use-sorted-type-fields/), which sorts the fields of GraphQL object types, interface types and input object types alphabetically, e.g. `name, age, id` becomes `age, id, name`.
- [#​10561](https://github.com/biomejs/biome/pull/10561) [`78075b7`](https://github.com/biomejs/biome/commit/78075b7c7cb7490c730a96f4ee9776c9e77826e7) Thanks [@​Conaclos](https://github.com/Conaclos)! - Added a new `style` option to [useExportType](https://biomejs.dev/linter/rules/use-export-type/),
which enforces a style for exporting types.
This is the same option as the one provided by `useImportType`.
- [#​8987](https://github.com/biomejs/biome/pull/8987) [`d16e32b`](https://github.com/biomejs/biome/commit/d16e32b5b971a4ed9cd3bf5098782c8b752af69a) Thanks [@​DerTimonius](https://github.com/DerTimonius)! - Ported the [`useValidAnchor`](https://biomejs.dev/linter/rules/use-valid-anchor/) rule to HTML. This rule enforces that all anchors are valid and that they are navigable elements.
- [#​9533](https://github.com/biomejs/biome/pull/9533) [`4d251d4`](https://github.com/biomejs/biome/commit/4d251d489cfd33a83e42d425476f8d6c66b72d9b) Thanks [@​ematipico](https://github.com/ematipico)! - The `init` command now prints the Biome logo.
- [#​10069](https://github.com/biomejs/biome/pull/10069) [`0eb9310`](https://github.com/biomejs/biome/commit/0eb93109e1f9bfbb20744961681b4f0b9b781ad5) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/), which enforces that static, visible elements (such as `<div>`) that have click handlers use the valid role attribute.
**Invalid**:
```html
<div onclick="myFunction()"></div>
```
- [#​9134](https://github.com/biomejs/biome/pull/9134) [`2a43488`](https://github.com/biomejs/biome/commit/2a434882746d31e1bd3c8e0d711372a539ce88f8) Thanks [@​ematipico](https://github.com/ematipico)! - Added the assist action [`useSortedPackageJson`](https://biomejs.dev/assist/actions/use-sorted-package-json).
This action organizes package.json fields according to the same conventions as the popular [sort-package-json](https://github.com/keithamus/sort-package-json) tool.
- [#​9309](https://github.com/biomejs/biome/pull/9309) [`7daa18b`](https://github.com/biomejs/biome/commit/7daa18b07f7ab348942f4cb83b475e6a4b3d1125) Thanks [@​Bertie690](https://github.com/Bertie690)! - The `allowDoubleNegation` option has been added to [`noImplicitCoercions`](https://biomejs.dev/linter/rules/no-implicit-coercions) to allow ignoring double negations inside code.
With the option enabled, the following example is considered valid and is ignored by the rule:
```js
const truthy = !!value;
```
- [#​9700](https://github.com/biomejs/biome/pull/9700) [`894f3fb`](https://github.com/biomejs/biome/commit/894f3fb4c664b12ff9abd1527b535621fe4e22f6) Thanks [@​ematipico](https://github.com/ematipico)! - The Biome Language server now supports the "go-to definition" feature.
When the cursor of the mouse is hovering an entity (variable, CSS class, type, etc.), and the command <kbd>CTRL</kbd> + click is triggered, the editor jumps to where this entity is defined, if the language server can find it.
Here's what Biome is able to resolve:
- Variables and types used in JavaScript modules, defined in the same file or imported from another module.
- JSX Components used in JavaScript modules, defined in the same file or imported from another module.
- CSS classes used in JSX and HTML-ish files (Vue, Svelte and Astro), and defined in CSS files.
- Components used in HTML-ish files and defined in other HTML-ish.
- Variables used in HTML-ish files and defined in the same file or imported from another module (JavaScript or HTML-ish).
- [#​10070](https://github.com/biomejs/biome/pull/10070) [`bae0710`](https://github.com/biomejs/biome/commit/bae071050f5a9c335b4483ee384f21ac1e6f0b4d) Thanks [@​Conaclos](https://github.com/Conaclos)! - Added the `:STYLE:` group matcher for [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) that matches style imports.
For example, the following configuration...
```json
{
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "on",
"options": {
"groups": ["**", "!:STYLE:"],
"sortBareImports": true
}
}
}
}
}
}
```
...places style imports last:
```diff
- import "./style.css"
import A from "./a.js"
+ import "./style.css"
```
- [#​9170](https://github.com/biomejs/biome/pull/9170) [`e3107de`](https://github.com/biomejs/biome/commit/e3107deedcff0f02b61702c6645d89e8d8635b49) Thanks [@​mdrobny](https://github.com/mdrobny)! - Added `bundleDependencies` option to [NoUndeclaredDependencies](https://biomejs.dev/linter/rules/no-undeclared-dependencies) rule.
This rule now supports imports of packages that are defined only in `bundleDependencies` and `bundledDependencies` arrays.
- [#​9547](https://github.com/biomejs/biome/pull/9547) [`01f8473`](https://github.com/biomejs/biome/commit/01f847317820f805698e1b8ba9eaa8fa6c26205c) Thanks [@​mujpao](https://github.com/mujpao)! - Added new assist rule [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) for HTML, porting the existing JSX rule. This rule enforces sorted HTML attributes.
**Invalid**
```html
<input type="text" id="name" name="name" />
```
- [#​9366](https://github.com/biomejs/biome/pull/9366) [`2ca1117`](https://github.com/biomejs/biome/commit/2ca1117f1e63f6cd99c0ce8d4b82475625838e2e) Thanks [@​dyc3](https://github.com/dyc3)! - Added the `html.parser.vue` configuration option. When enabled, it adds support for the parsing of Vue in `.html` files. Most Vue users don't need to enable this option since Vue files typically use the `.vue` extension, but it can be useful for projects that embed Vue syntax in regular HTML files.
- [#​9073](https://github.com/biomejs/biome/pull/9073) [`74b20ee`](https://github.com/biomejs/biome/commit/74b20eee556c9acc72ad5ea335b1bf0983d2eb2e) Thanks [@​chocky335](https://github.com/chocky335)! - Added support for applying GritQL plugin rewrites as code actions. GritQL plugins that use the rewrite operator (`=>`) now produce fixable diagnostics for JavaScript, CSS, and JSON files. By default, plugin rewrites are treated as unsafe fixes and require `--write --unsafe` to apply. Plugin authors can pass `fix_kind = "safe"` to `register_diagnostic()` to mark a fix as safe, allowing it to be applied with just `--write`.
**Example plugin** (`useConsoleInfo.grit`):
```grit
language js
`console.log($msg)` as $call where {
register_diagnostic(span = $call, message = "Use console.info instead of console.log.", severity = "warn", fix_kind = "safe"),
$call => `console.info($msg)`
}
```
Running `biome check --write` applies safe rewrites. Unsafe rewrites (the default, or `fix_kind = "unsafe"`) still require `--write --unsafe`.
- [#​9384](https://github.com/biomejs/biome/pull/9384) [`f4c9edc`](https://github.com/biomejs/biome/commit/f4c9edca8f8772a1e65d9e6701fdc3f604a9f3fe) Thanks [@​Conaclos](https://github.com/Conaclos)! - Added the `sortBareImports` option to [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/),
which allows bare imports to be sorted within other imports when set to `false`.
```json
{
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "on",
"options": { "sortBareImports": true }
}
}
}
}
}
```
```diff
- import "b";
import "a";
+ import "b";
import { A } from "a";
+ import "./file";
import { Local } from "./file";
- import "./file";
```
- [#​8731](https://github.com/biomejs/biome/pull/8731) [`e7872bf`](https://github.com/biomejs/biome/commit/e7872bffba88f60d6c3cb6d0c2dd7a25452a0205) Thanks [@​siketyan](https://github.com/siketyan)! - Added the watch mode (`--watch`) to the CLI for `check`/`format`/`lint` commands. By enabling this option, Biome will re-run the check automatically when any file in the workspace has changed after the first run.
- [#​10106](https://github.com/biomejs/biome/pull/10106) [`9b35f78`](https://github.com/biomejs/biome/commit/9b35f78e183edf44a3d8b7077ebb0c548a7e92f5) Thanks [@​ematipico](https://github.com/ematipico)! - Biome can now format and lint `.svg` files.
- [#​9967](https://github.com/biomejs/biome/pull/9967) [`e9b6c17`](https://github.com/biomejs/biome/commit/e9b6c17cd6f7e870aea68da3b6c6474aa1a9b4f6) Thanks [@​dyc3](https://github.com/dyc3)! - Added HTML support for [`noExcessiveLinesPerFile`](https://biomejs.dev/linter/rules/no-excessive-lines-per-file/). Biome now reports HTML files that exceed the configured line limit, including when `skipBlankLines` is enabled.
- [#​9491](https://github.com/biomejs/biome/pull/9491) [`b3eb63c`](https://github.com/biomejs/biome/commit/b3eb63c7e19e6ebd41e463289de098bb003686e1) Thanks [@​IxxyDev](https://github.com/IxxyDev)! - Added the HTML lint rule [`noAriaUnsupportedElements`](https://biomejs.dev/linter/rules/no-aria-unsupported-elements/). This rule enforces that elements that do not support ARIA roles, states, and properties (`meta`, `html`, `script`, `style`) do not have `role` or `aria-*` attributes.
```html
<!-- Invalid: meta does not support aria attributes -->
<meta charset="UTF-8" role="meta" />
```
- [#​9306](https://github.com/biomejs/biome/pull/9306) [`afd57a6`](https://github.com/biomejs/biome/commit/afd57a634bdb6b0b161dc8a2522ac460503569b1) Thanks [@​viraxslot](https://github.com/viraxslot)! - Added the [`noNoninteractiveTabindex`](https://biomejs.dev/linter/rules/no-noninteractive-tabindex/) lint rule for HTML. This rule enforces that `tabindex` is not used on non-interactive elements, as it can cause usability issues for keyboard users.
```html
<div tabindex="0">Invalid: non-interactive element</div>
`
```
- [#​9276](https://github.com/biomejs/biome/pull/9276) [`6d041d9`](https://github.com/biomejs/biome/commit/6d041d919e06595553093e084e6aad0d39fb8109) Thanks [@​IxxyDev](https://github.com/IxxyDev)! - Added the HTML lint rule [`noRedundantRoles`](https://biomejs.dev/linter/rules/no-redundant-roles/). This rule enforces that explicit `role` attributes are not the same as the implicit/default role of an HTML element. It supports HTML, Vue, Svelte, and Astro files.
```html
<!-- Invalid: role="button" is redundant on <button> -->
<button role="button"></button>
```
- [#​9813](https://github.com/biomejs/biome/pull/9813) [`69aadc2`](https://github.com/biomejs/biome/commit/69aadc27741bb8a74c926e14a2a9777064cb1e03) Thanks [@​ematipico](https://github.com/ematipico)! - Added a new linter configuration called `preset`. With the new option, users can enable different kinds of rules at once.
The following presets are available:
- `"recommended"`: it enables all Biome-recommended rules, or recommended rules of a group;
- `"all"`: it enables all Biome rules, or enables all rules of a group;
- `"none"`: it disables all Biome rules, or disable all rules of a group.
You can enable recommended rules:
```json
{
"linter": {
"rules": {
"preset": "recommended"
}
}
}
```
You can enable **all rules** at once:
```json5
{
linter: {
rules: {
preset: "all", // enables all rules
},
},
}
```
Or enable all rules for a group:
```json5
{
linter: {
rules: {
style: {
preset: "all", // enables all rules in the style group
},
},
},
}
```
This new option, however, doesn't affect how nursery rules work. Nursery rules must be enabled singularly, due to their nature.
This new option is meant to replace `recommended`, so make sure to run the `migrate` command.
- [#​10022](https://github.com/biomejs/biome/pull/10022) [`3422d71`](https://github.com/biomejs/biome/commit/3422d71bc5e9d7f07fd4e7509566427e1591d760) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`noNoninteractiveElementToInteractiveRole`](https://biomejs.dev/linter/rules/no-noninteractive-element-to-interactive-role/), which enforces that interactive ARIA roles are not assigned to non-interactive HTML elements.
**Invalid**:
```html
<h1 role="checkbox"></h1>
```
- [#​8396](https://github.com/biomejs/biome/pull/8396) [`13785fc`](https://github.com/biomejs/biome/commit/13785fc8f4be068eccff84a8ad90ac8530d5c992) Thanks [@​apple-yagi](https://github.com/apple-yagi)! - Biome now supports pnpm catalogs (default and named) when resolving dependencies for linting. This behavior is opt-in and requires setting `javascript.resolver.experimentalPnpmCatalogs` to `true`.
- [#​10028](https://github.com/biomejs/biome/pull/10028) [`1009414`](https://github.com/biomejs/biome/commit/100941409f3ec5e6653e92b2cfbb4100df1becb0) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`noInteractiveElementToNoninteractiveRole`](https://biomejs.dev/linter/rules/no-interactive-element-to-noninteractive-role/), which enforces that non-interactive ARIA roles are not assigned to interactive HTML elements.
**Invalid**:
```html
<input role="img" />
```
- [#​9853](https://github.com/biomejs/biome/pull/9853) [`816302f`](https://github.com/biomejs/biome/commit/816302f8c8c9862585c283fce22ffd1817dedf9f) Thanks [@​Netail](https://github.com/Netail)! - Added the new assist action [`useSortedSelectionSet`](https://biomejs.dev/assist/actions/use-sorted-selection-set/), which sorts GraphQL selection sets alphabetically, e.g. `name, age, id` becomes `age, id, name`.
**Invalid**:
```graphql
query {
name
age
id
}
```
- [#​10074](https://github.com/biomejs/biome/pull/10074) [`9c7c6eb`](https://github.com/biomejs/biome/commit/9c7c6eb99f6880aa87ae0e7aff357e978361c4a3) Thanks [@​georgephillips](https://github.com/georgephillips)! - Added a `kind` field to the `ImportMatcher` used by the [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) assist action. The new field selects imports by their syntactic kind and currently supports `bare` (matching side-effect imports such as `import "polyfill"`) with optional `!` negation (`!bare`). The matcher composes with the existing `type` and `source` fields, so users can express patterns such as "only bare imports that import a CSS file" (`{ "kind": "bare", "source": "**/*.css" }`).
For example, with the following configuration:
```json
{
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "on",
"options": {
"sortBareImports": true,
"groups": [
{ "kind": "!bare" },
":BLANK_LINE:",
{ "kind": "bare" }
]
}
}
}
}
}
}
```
...the following code:
```ts
import "./register-my-component";
import { render } from "react-dom";
import "./polyfill";
import { Button } from "@/components/Button";
```
...is organized as:
```ts
import { render } from "react-dom";
import { Button } from "@/components/Button";
import "./polyfill";
import "./register-my-component";
```
- [#​9171](https://github.com/biomejs/biome/pull/9171) [`ce65710`](https://github.com/biomejs/biome/commit/ce65710f591eb2676df6833e9cd00e310981692b) Thanks [@​chocky335](https://github.com/chocky335)! - Added `includes` option for plugin file scoping. Plugins can now be configured with glob patterns to restrict which files they run on. Use negated globs for exclusions.
```json
{
"plugins": [
"global-plugin.grit",
{
"path": "scoped-plugin.grit",
"includes": ["src/**/*.ts", "!**/*.test.ts"]
}
]
}
```
- [#​9617](https://github.com/biomejs/biome/pull/9617) [`dcb99ef`](https://github.com/biomejs/biome/commit/dcb99ef0305d8431af40b526c449316bb8a70efa) Thanks [@​faizkhairi](https://github.com/faizkhairi)! - Ported [`useAriaActivedescendantWithTabindex`](https://biomejs.dev/linter/rules/use-aria-activedescendant-with-tabindex/) a11y rule to HTML.
- [#​9496](https://github.com/biomejs/biome/pull/9496) [`1dfb829`](https://github.com/biomejs/biome/commit/1dfb8291a0a2340e7c9220f9126317a7490ec466) Thanks [@​aviraldua93](https://github.com/aviraldua93)! - Added HTML support for the [`noAriaHiddenOnFocusable`](https://biomejs.dev/linter/rules/no-aria-hidden-on-focusable/) accessibility lint rule, which enforces that `aria-hidden="true"` is not set on focusable elements. Focusable elements include native interactive elements (`<button>`, `<input>`, `<select>`, `<textarea>`), elements with `href` (`<a>`, `<area>`), elements with `tabindex >= 0`, and editing hosts (`contenteditable`). Includes an unsafe fix to remove the `aria-hidden` attribute.
```html
<!-- Invalid: aria-hidden on a focusable element -->
<button aria-hidden="true">Submit</button>
<!-- Valid: aria-hidden on a non-focusable element -->
<div aria-hidden="true">decorative content</div>
```
- [#​9792](https://github.com/biomejs/biome/pull/9792) [`f516854`](https://github.com/biomejs/biome/commit/f51685404f015a5c6f0fc87b9070ac5d9f0a7b6b) Thanks [@​Maximiliano-Zeballos](https://github.com/Maximiliano-Zeballos)! - Added the [`useSemanticElements`](https://biomejs.dev/linter/rules/use-semantic-elements/) lint rule for HTML. The rule now detects the use of `role` attributes in HTML elements and suggests using semantic elements instead.
For example, the following code is now flagged:
```html
<div role="navigation"></div>
```
The rule suggests using `<nav>` instead.
- [#​9761](https://github.com/biomejs/biome/pull/9761) [`cbbb7d5`](https://github.com/biomejs/biome/commit/cbbb7d5bf21d8fb6db275da7adcc03c034538635) Thanks [@​Maximiliano-Zeballos](https://github.com/Maximiliano-Zeballos)! - Ported the [`useValidAriaProps`](https://biomejs.dev/linter/rules/use-valid-aria-props/) lint rule to HTML. This rule checks that all `aria-*` attributes used in HTML elements are valid ARIA attributes as defined by the WAI-ARIA specification.
- [#​9928](https://github.com/biomejs/biome/pull/9928) [`aa82576`](https://github.com/biomejs/biome/commit/aa82576ff66e03924e07729051ac9bfc59cd5aa1) Thanks [@​aviraldua93](https://github.com/aviraldua93)! - Ported [`useValidAriaValues`](https://biomejs.dev/linter/rules/use-valid-aria-values/) to HTML. Biome now validates static `aria-*` attribute values in HTML elements against WAI-ARIA types, catching invalid values such as `aria-hidden="yes"`.
- [#​10562](https://github.com/biomejs/biome/pull/10562) [`6642895`](https://github.com/biomejs/biome/commit/66428957e6ca393a802f365b8e643438f19a3039) Thanks [@​ematipico](https://github.com/ematipico)! - Promoted 73 nursery rules to stable groups.
Four rules were renamed as part of the promotion:
- `noFloatingClasses` is now [`noUnusedInstantiation`](https://biomejs.dev/linter/rules/no-unused-instantiation/), because the rule checks any discarded `new` expression, not only classes.
- `noMultiStr` is now [`noMultilineString`](https://biomejs.dev/linter/rules/no-multiline-string/).
- `useFind` is now [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/).
- `useSpread` is now [`useSpreadOverApply`](https://biomejs.dev/linter/rules/use-spread-over-apply/), because the rule enforces spread call arguments over `Function.apply()`, not array or object spread.
##### Correctness
Promoted the following rules to the `correctness` group:
- [`noBeforeInteractiveScriptOutsideDocument`](https://biomejs.dev/linter/rules/no-before-interactive-script-outside-document/)
- [`noUnusedInstantiation`](https://biomejs.dev/linter/rules/no-unused-instantiation/)
- [`useInlineScriptId`](https://biomejs.dev/linter/rules/use-inline-script-id/) (recommended, Next.js domain)
- [`noVueVIfWithVFor`](https://biomejs.dev/linter/rules/no-vue-v-if-with-v-for/) (recommended, Vue domain)
- [`useVueValidVBind`](https://biomejs.dev/linter/rules/use-vue-valid-v-bind/) (recommended, Vue domain)
- [`useVueValidVElse`](https://biomejs.dev/linter/rules/use-vue-valid-v-else/) (recommended, Vue domain)
- [`useVueValidVElseIf`](https://biomejs.dev/linter/rules/use-vue-valid-v-else-if/) (recommended, Vue domain)
- [`useVueValidVHtml`](https://biomejs.dev/linter/rules/use-vue-valid-v-html/) (recommended, Vue domain)
- [`useVueValidVIf`](https://biomejs.dev/linter/rules/use-vue-valid-v-if/) (recommended, Vue domain)
- [`useVueValidVOn`](https://biomejs.dev/linter/rules/use-vue-valid-v-on/) (recommended, Vue domain)
- [`useVueValidVText`](https://biomejs.dev/linter/rules/use-vue-valid-v-text/) (recommended, Vue domain)
- [`useVueValidTemplateRoot`](https://biomejs.dev/linter/rules/use-vue-valid-template-root/) (recommended, Vue domain)
- [`useVueValidVCloak`](https://biomejs.dev/linter/rules/use-vue-valid-v-cloak/) (recommended, Vue domain)
- [`useVueValidVOnce`](https://biomejs.dev/linter/rules/use-vue-valid-v-once/) (recommended, Vue domain)
- [`useVueValidVPre`](https://biomejs.dev/linter/rules/use-vue-valid-v-pre/) (recommended, Vue domain)
- [`useVueVForKey`](https://biomejs.dev/linter/rules/use-vue-v-for-key/) (recommended, Vue domain)
- [`noDuplicateAttributes`](https://biomejs.dev/linter/rules/no-duplicate-attributes/) (recommended)
- [`noDuplicateArgumentNames`](https://biomejs.dev/linter/rules/no-duplicate-argument-names/) (recommended)
- [`noDuplicateInputFieldNames`](https://biomejs.dev/linter/rules/no-duplicate-input-field-names/) (recommended)
- [`noDuplicateVariableNames`](https://biomejs.dev/linter/rules/no-duplicate-variable-names/) (recommended)
- [`noDuplicateEnumValueNames`](https://biomejs.dev/linter/rules/no-duplicate-enum-value-names/) (recommended)
- [`useLoneAnonymousOperation`](https://biomejs.dev/linter/rules/use-lone-anonymous-operation/) (recommended)
##### Suspicious
Promoted the following rules to the `suspicious` group:
- [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/)
- [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/)
- [`noParametersOnlyUsedInRecursion`](https://biomejs.dev/linter/rules/no-parameters-only-used-in-recursion/)
- [`noUnknownAttribute`](https://biomejs.dev/linter/rules/no-unknown-attribute/)
- [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/)
- [`noForIn`](https://biomejs.dev/linter/rules/no-for-in/)
- [`noDuplicatedSpreadProps`](https://biomejs.dev/linter/rules/no-duplicated-spread-props/)
- [`noEqualsToNull`](https://biomejs.dev/linter/rules/no-equals-to-null/)
- [`noProto`](https://biomejs.dev/linter/rules/no-proto/) (recommended)
- [`noUndeclaredEnvVars`](https://biomejs.dev/linter/rules/no-undeclared-env-vars/) (recommended, Turborepo domain)
- [`noReturnAssign`](https://biomejs.dev/linter/rules/no-return-assign/) (default severity: `error`)
- [`noDuplicateEnumValues`](https://biomejs.dev/linter/rules/no-duplicate-enum-values/) (recommended)
- [`noVueArrowFuncInWatch`](https://biomejs.dev/linter/rules/no-vue-arrow-func-in-watch/) (recommended, Vue domain)
- [`noNestedPromises`](https://biomejs.dev/linter/rules/no-nested-promises/)
- [`noLeakedRender`](https://biomejs.dev/linter/rules/no-leaked-render/)
- [`noDeprecatedMediaType`](https://biomejs.dev/linter/rules/no-deprecated-media-type/) (recommended)
- [`noDuplicateGraphqlOperationName`](https://biomejs.dev/linter/rules/no-duplicate-graphql-operation-name/)
- [`useRequiredScripts`](https://biomejs.dev/linter/rules/use-required-scripts/)
##### Style
Promoted the following rules to the `style` group:
- [`useVueMultiWordComponentNames`](https://biomejs.dev/linter/rules/use-vue-multi-word-component-names/) (recommended, Vue domain)
- [`useVueDefineMacrosOrder`](https://biomejs.dev/linter/rules/use-vue-define-macros-order/)
- [`noIncrementDecrement`](https://biomejs.dev/linter/rules/no-increment-decrement/)
- [`noContinue`](https://biomejs.dev/linter/rules/no-continue/)
- [`useSpreadOverApply`](https://biomejs.dev/linter/rules/use-spread-over-apply/)
- [`noTernary`](https://biomejs.dev/linter/rules/no-ternary/)
- [`noMultilineString`](https://biomejs.dev/linter/rules/no-multiline-string/)
- [`noMultiAssign`](https://biomejs.dev/linter/rules/no-multi-assign/)
- [`noExcessiveClassesPerFile`](https://biomejs.dev/linter/rules/no-excessive-classes-per-file/)
- [`noExcessiveLinesPerFile`](https://biomejs.dev/linter/rules/no-excessive-lines-per-file/)
- [`noVueOptionsApi`](https://biomejs.dev/linter/rules/no-vue-options-api/)
- [`useErrorCause`](https://biomejs.dev/linter/rules/use-error-cause/)
- [`useConsistentEnumValueType`](https://biomejs.dev/linter/rules/use-consistent-enum-value-type/)
- [`useConsistentMethodSignatures`](https://biomejs.dev/linter/rules/use-consistent-method-signatures/)
- [`useGlobalThis`](https://biomejs.dev/linter/rules/use-global-this/) (default severity: `warn`)
- [`useDestructuring`](https://biomejs.dev/linter/rules/use-destructuring/)
- [`useVueHyphenatedAttributes`](https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes/) (recommended, Vue domain)
- [`useVueConsistentVBindStyle`](https://biomejs.dev/linter/rules/use-vue-consistent-v-bind-style/) (recommended, Vue domain)
- [`useVueConsistentVOnStyle`](https://biomejs.dev/linter/rules/use-vue-consistent-v-on-style/) (recommended, Vue domain)
- [`noHexColors`](https://biomejs.dev/linter/rules/no-hex-colors/)
- [`useConsistentGraphqlDescriptions`](https://biomejs.dev/linter/rules/use-consistent-graphql-descriptions/)
- [`noRootType`](https://biomejs.dev/linter/rules/no-root-type/)
- [`useLoneExecutableDefinition`](https://biomejs.dev/linter/rules/use-lone-executable-definition/)
- [`useInputName`](https://biomejs.dev/linter/rules/use-input-name/)
##### Complexity
Promoted the following rules to the `complexity` group:
- [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/)
- [`noRedundantDefaultExport`](https://biomejs.dev/linter/rules/no-redundant-default-export/) (default severity: `warn`)
- [`noUselessReturn`](https://biomejs.dev/linter/rules/no-useless-return/)
- [`noDivRegex`](https://biomejs.dev/linter/rules/no-div-regex/)
##### Performance
Promoted the following rules to the `performance` group:
- [`noSyncScripts`](https://biomejs.dev/linter/rules/no-sync-scripts/)
- [`noJsxPropsBind`](https://biomejs.dev/linter/rules/no-jsx-props-bind/)
- [`useVueVapor`](https://biomejs.dev/linter/rules/use-vue-vapor/)
##### Security
Promoted the following rules to the `security` group:
- [`noScriptUrl`](https://biomejs.dev/linter/rules/no-script-url/) (recommended)
##### A11y
Promoted the following rules to the `a11y` group:
- [`noAmbiguousAnchorText`](https://biomejs.dev/linter/rules/no-ambiguous-anchor-text/) (recommended)
- [#​10121](https://github.com/biomejs/biome/pull/10121) [`450f8e1`](https://github.com/biomejs/biome/commit/450f8e1c0a46e8c867a63a0842deaa50dee95176) Thanks [@​jongwan56](https://github.com/jongwan56)! - Biome now applies Git's local exclude file when VCS ignore files are enabled. Files listed in `.git/info/exclude` are skipped the same way as files listed in `.gitignore`, including in linked worktrees.
- [#​9397](https://github.com/biomejs/biome/pull/9397) [`d5913c9`](https://github.com/biomejs/biome/commit/d5913c9d57b771b0b1c0097f8014017878cc14c2) Thanks [@​mvarendorff](https://github.com/mvarendorff)! - Added `ignore` option to the [noUnusedVariables](https://biomejs.dev/linter/rules/no-unused-variables/) rule. The option allows excluding identifiers by providing a list of ignored names. It also allows excluding kinds of identifiers from this rule entirely, which may be useful when loading classes dynamically.
For example, unused classes as well as all unused variables, functions, etc. called "unused" may be ignored entirely with the following configuration:
```json
{
"ignore": {
"*": ["unused"],
"class": ["*"]
}
}
```
- [#​10089](https://github.com/biomejs/biome/pull/10089) [`71a21f0`](https://github.com/biomejs/biome/commit/71a21f0ab4fd32739331d3b3068c6c1ae6392290) Thanks [@​Netail](https://github.com/Netail)! - Added the lint rule [`noLabelWithoutControl`](https://biomejs.dev/linter/rules/no-label-without-control/) to HTML, which enforces that a label element or component has a text label and an associated input.
```html
<label></label>
```
- [#​10015](https://github.com/biomejs/biome/pull/10015) [`1828261`](https://github.com/biomejs/biome/commit/182826178de9c1b23bad2e997c3567a9d5176ba2) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`useAriaPropsSupportedByRole`](https://biomejs.dev/linter/rules/use-aria-props-supported-by-role/), which enforces that ARIA properties are valid for the roles that are supported by the element.
```html
<a href="#" aria-checked></a>
```
- [#​10234](https://github.com/biomejs/biome/pull/10234) [`1a51569`](https://github.com/biomejs/biome/commit/1a51569229936b9ad1191d081ed6742e8342badd) Thanks [@​ematipico](https://github.com/ematipico)! - Added the `delimiterSpacing` formatter option. This option inserts spaces inside delimiters (after the opening delimiter and before the closing delimiter) when the content fits on a single line. Empty delimiters are not affected, and no space is added before the opening delimiter. The specific delimiters affected depend on the language. It can be configured globally via `formatter.delimiterSpacing` or per-language via `javascript.formatter.delimiterSpacing`, `json.formatter.delimiterSpacing`, and `css.formatter.delimiterSpacing`. Defaults to `false`.
```diff
- callFn(foo)
+ callFn( foo )
```
```diff
- const arr = [1, 2, 3];
+ const arr = [ 1, 2, 3 ];
```
##### JavaScript
When enabled, Biome inserts spaces inside parentheses (e.g., `foo( a, b )`), square brackets (e.g., `[ a, b ]`), template literal interpolations (e.g., `${ expr }`), and the logical NOT operator (e.g., `! x`, but in chains only after the last one: `!! x`). Only applies when the content fits on a single line. Empty delimiters and the space before the opening delimiter are not affected.
```diff
- if (condition) {}
+ if ( condition ) {}
```
```diff
- `Hello ${name}!`
+ `Hello ${ name }!`
```
##### JSX
When enabled, Biome inserts spaces inside JSX expression braces (e.g., `attr={ value }`) and spread attributes (e.g., `{ ...props }`). Only applies when the content fits on a single line. Empty delimiters are not affected.
```diff
- <Foo bar={value} />
+ <Foo bar={ value } />
```
##### TypeScript
When enabled, Biome inserts spaces inside TypeScript angle brackets (e.g., `foo< T >()`), indexed access types (e.g., `T[ K ]`), mapped types, tuple types, type parameters, and index signatures. Only applies when the content fits on a single line. Empty delimiters are not affected.
```diff
- type Result = Map<string, number>;
+ type Result = Map< string, number >;
```
##### JSON
When enabled, Biome inserts spaces inside square brackets when the content fits on a single line. Empty brackets are not affected.
```diff
- [1, 2, 3]
+ [ 1, 2, 3 ]
```
##### CSS
When enabled, Biome inserts spaces inside parentheses and square brackets when the content fits on a single line. Empty delimiters are not affected.
```diff
- rgba(0, 0, 0, 1)
+ rgba( 0, 0, 0, 1 )
```
```diff
- [data-attr]
+ [ data-attr ]
```
- [#​10461](https://github.com/biomejs/biome/pull/10461) [`6bac1c3`](https://github.com/biomejs/biome/commit/6bac1c3457d396215e4daed5fc59eaf23b42f4eb) Thanks [@​TXWSLYF](https://github.com/TXWSLYF)! - Implements [#​9445](https://github.com/biomejs/biome/issues/9445). Added the `allowImplicit` option to [`useIterableCallbackReturn`](https://biomejs.dev/linter/rules/use-iterable-callback-return/). When enabled, callbacks can use `return;` to implicitly return `undefined`, matching ESLint's `array-callback-return` rule.
- [#​9571](https://github.com/biomejs/biome/pull/9571) [`5a8eb75`](https://github.com/biomejs/biome/commit/5a8eb755fe07b38760d2b72ec46e24cd108f6619) Thanks [@​dyc3](https://github.com/dyc3)! - Added configurable options to the [`useNumericSeparators`](https://biomejs.dev/linter/rules/use-numeric-separators/) rule. Users can now customize the minimum number of digits required before adding separators and the group length for each type of numeric literal (`binary`, `octal`, `decimal`, `hexadecimal`).
```json
{
"linter": {
"rules": {
"style": {
"useNumericSeparators": {
"level": "error",
"options": {
"decimal": {
"minimumDigits": 7,
"groupLength": 3
},
"hexadecimal": {
"minimumDigits": 4,
"groupLength": 2
}
}
}
}
}
}
}
```
- [#​10067](https://github.com/biomejs/biome/pull/10067) [`6064312`](https://github.com/biomejs/biome/commit/60643120b5593104b311e184cf9581b9c7c2254d) Thanks [@​Netail](https://github.com/Netail)! - Added the lint rule [`useFocusableInteractive`](https://biomejs.dev/linter/rules/use-focusable-interactive/) to HTML, which enforces elements with an interactive role and interaction handler to be focusable.
**Invalid**:
```html
<div role="button"></div>
```
- [#​10026](https://github.com/biomejs/biome/pull/10026) [`fb42ac4`](https://github.com/biomejs/biome/commit/fb42ac42079ec7b8e699a507bce332f4446ac7f2) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`noNoninteractiveElementInteractions`](https://biomejs.dev/linter/rules/no-noninteractive-element-interactions/), which disallows use event handlers on non-interactive elements.
**Invalid**:
```html
<div onclick="myFunction()">button</div>
```
- [#​10000](https://github.com/biomejs/biome/pull/10000) [`2093e3e`](https://github.com/biomejs/biome/commit/2093e3ee2a615abecae159d35a5a17fe0df5f506) Thanks [@​Netail](https://github.com/Netail)! - Added the new assist action [`useSortedEnumMembers`](https://biomejs.dev/assist/actions/use-sorted-enum-members/), which sorts TypeScript & GraphQL enum members.
**Invalid**:
```graphql
enum Role {
SUPER_ADMIN
ADMIN
USER
GOD
}
```
- [#​10013](https://github.com/biomejs/biome/pull/10013) [`ad01d3d`](https://github.com/biomejs/biome/commit/ad01d3d882276b070433822f01cdf6afed63ca4e) Thanks [@​Netail](https://github.com/Netail)! - Added the HTML lint rule [`useValidAutocomplete`](https://biomejs.dev/linter/rules/use-valid-autocomplete/), which enforces using valid values for the `autocomplete` attribute on `input` elements.
```html
<input autocomplete="incorrect" />
```
##### Patch Changes
- [#​10498](https://github.com/biomejs/biome/pull/10498) [`995c1ff`](https://github.com/biomejs/biome/commit/995c1ffeca039787c93370fed8b970a057e9c073) Thanks [@​citadelgrad](https://github.com/citadelgrad)! - Added the nursery rule [`useReactFunctionComponentDefinition`](https://biomejs.dev/linter/rules/use-react-function-component-definition), which enforces a consistent function type for named React function components.
For example, the following snippet triggers the rule by default.
```jsx
const MyComponent = (props) => {
return <div>{props.name}</div>;
};
```
- [#​9974](https://github.com/biomejs/biome/pull/9974) [`ff635a9`](https://github.com/biomejs/biome/commit/ff635a90da3567a9006ae947b6c5983d87dfbb9f) Thanks [@​pkallos](https://github.com/pkallos)! - Added `ignoreMixedLogicalExpressions` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/), partially addressing [#​9232](https://github.com/biomejs/biome/issues/9232). When enabled, Biome ignores `||` and `||=` mixed with `&&` in the same expression tree.
- [#​10503](https://github.com/biomejs/biome/pull/10503) [`c656679`](https://github.com/biomejs/biome/commit/c656679d1f9e725a42e5d60fb3b9e76bb03d7f88) Thanks [@​Mokto](https://github.com/Mokto)! - Added the new nursery rule `useSvelteRequireEachKey`, a Svelte lint rule that reports `{#each}` blocks with item bindings that are missing a key.
- [#​10516](https://github.com/biomejs/biome/pull/10516) [`0f29b83`](https://github.com/biomejs/biome/commit/0f29b8361ba3cd11bdbfb91f8ff722184cfadf08) Thanks [@​Dotify71](https://github.com/Dotify71)! - Added [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/) to the nursery group. This rule flags comparisons of `String.prototype.indexOf()` or `Array.prototype.indexOf()` against `-1` and suggests replacing them with the clearer `includes()` / `!includes()` form.
- [#​10487](https://github.com/biomejs/biome/pull/10487) [`0c03ee3`](https://github.com/biomejs/biome/commit/0c03ee3deee068220175c3599e6bc3c4ed8ad247) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed a Svelte parser error that incorrectly required a binding variable after `{:then}` and `{:catch}`. Biome now correctly accepts `{:then}` and `{:catch}` without a binding, as well as the `{#await expr then}` and `{#await expr catch}` shorthand forms.
- [#​10566](https://github.com/biomejs/biome/pull/10566) [`a4a294c`](https://github.com/biomejs/biome/commit/a4a294c3c1128fc5b38634262d499d3d2601bf3b) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`useVueHyphenatedAttributes`](https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes/): The rule now only reports diagnostics in Vue files and ignores SVG elements.
- [#​10565](https://github.com/biomejs/biome/pull/10565) [`72ccf3b`](https://github.com/biomejs/biome/commit/72ccf3b042c4258f9871ff5b99d87f879cecccde) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [`useVueConsistentVBindStyle`](https://biomejs.dev/linter/rules/use-vue-consistent-v-bind-style/): The rule no longer reports argument-less `v-bind` directives because they cannot be converted to shorthand syntax.
- [#​10591](https://github.com/biomejs/biome/pull/10591) [`6e8557b`](https://github.com/biomejs/biome/commit/6e8557b1b8e49ce2383f6089a46624eb030178ad) Thanks [@​xsourabhsharma](https://github.com/xsourabhsharma)! - Fixed [#​10563](https://github.com/biomejs/biome/issues/10563): Biome now parses comma-separated CSS Modules `composes` values, such as `composes: classA from "./a.css", classB from "./b.css";`.
- [#​10603](https://github.com/biomejs/biome/pull/10603) [`174b21b`](https://github.com/biomejs/biome/commit/174b21b52993fc3e0237ceefe97c0d71c9b5264e) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting for `grid-template-areas` declarations with comments before multiline values. Biome now keeps grid area rows aligned instead of adding an extra declaration-boundary indent.
```diff
.grid {
grid-template-areas:
/* row */
- "header header"
- "footer footer";
+ "header header"
+ "footer footer";
}
```
- [#​10542](https://github.com/biomejs/biome/pull/10542) [`c3f07f7`](https://github.com/biomejs/biome/commit/c3f07f773edeb7f098c778392c5e2d6bb92b78fb) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10513](https://github.com/biomejs/biome/issues/10513): Biome no longer rejects literal `\u` sequences in quoted HTML attribute values.
- [#​10108](https://github.com/biomejs/biome/pull/10108) [`24e51d6`](https://github.com/biomejs/biome/commit/24e51d6edebaee0ffb938bc20633d9c3403110c9) Thanks [@​IxxyDev](https://github.com/IxxyDev)! - Fixed [#​6611](https://github.com/biomejs/biome/issues/6611): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) now uses type information to detect more redundant conditions, including `?.`, `??`, `||`, `&&`, comparisons against `null`/`undefined` on non-nullish operands, and `case` clauses that can never match the `switch` value.
- [#​10568](https://github.com/biomejs/biome/pull/10568) [`eb1ed0e`](https://github.com/biomejs/biome/commit/eb1ed0e90395a07e64ee763fe15ae00fb77682e0) Thanks [@​harsha-cpp](https://github.com/harsha-cpp)! - Fixed [#​10564](https://github.com/biomejs/biome/issues/10564): `useAriaPropsForRole` no longer reports false positives for Vue v-bind shorthand bindings (`:aria-checked`, `:aria-level`, etc.).
- [#​10570](https://github.com/biomejs/biome/pull/10570) [`2ceb4fe`](https://github.com/biomejs/biome/commit/2ceb4fe437b77b08a60ad48efde2a6c311b7d2e3) Thanks [@​Conaclos](https://github.com/Conaclos)! - Improved [`noTsIgnore`](https://biomejs.dev/linter/rules/no-ts-ignore/).
The rule now reports more precisely the range of the `@ts-ignore` comment.
- [#​10520](https://github.com/biomejs/biome/pull/10520) [`b55d10f`](https://github.com/biomejs/biome/commit/b55d10f5e8f3099b3f246911ca19cc79758d55e0) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10519](https://github.com/biomejs/biome/issues/10519): Vue `v-on` event handlers with multiple inline statements are now parsed consistently with Vue.
- [#​10204](https://github.com/biomejs/biome/pull/10204) [`ebbf0bd`](https://github.com/biomejs/biome/commit/ebbf0bd382059936ac00de29fc58931728f854d9) Thanks [@​ematipico](https://github.com/ematipico)! - Improved the performance of the Biome linter. The improvements are more visible in bigger projects that have more than \~1k files. Early tests showed that in a code base with \~2k files, Biome took less than 26% of time to finish the command.
- [#​10546](https://github.com/biomejs/biome/pull/10546) [`e39bb2c`](https://github.com/biomejs/biome/commit/e39bb2c23063ad0384a12e01d666909fd6b26735) Thanks [@​tim-we](https://github.com/tim-we)! - Fixed [`#10536`](https://github.com/biomejs/biome/issues/10536): [noUnknownFunction](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flagged CSS `contrast-color()` as unknown. `contrast-color()` is Baseline 2026.
- [#​8012](https://github.com/biomejs/biome/pull/8012) [`2be0264`](https://github.com/biomejs/biome/commit/2be02648a090153a93cf71fb63ef68feefd495c2) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Improved the performance of the formatter in some cases. The formatter is now up to \~20% faster at formatting files.
- [#​10467](https://github.com/biomejs/biome/pull/10467) [`9a5855e`](https://github.com/biomejs/biome/commit/9a5855e4191c98149f8278289569b2272b992684) Thanks [@​Netail](https://github.com/Netail)! - Added a new nursery rule [`noRestrictedDependencies`](https://biomejs.dev/linter/rules/no-restricted-dependencies/), which flags imports and `package.json` dependency entries that have better alternatives in e18e's module replacement data.
For example, the package `globby` is reported because there's a better alternative:
```js
import glob from "globby";
```
```json
{
"dependencies": {
"globby": "x.x.x"
}
}
```
- [#​10470](https://github.com/biomejs/biome/pull/10470) [`84b43c5`](https://github.com/biomejs/biome/commit/84b43c5969569cb3eea3d51ea6c602276723306b) Thanks [@​ShaharAviram1](https://github.com/ShaharAviram1)! - Fixed [#​10447](https://github.com/biomejs/biome/issues/10447): now the rule [`noProcessEnv`](https://biomejs.dev/linter/rules/no-process-env) detects the use of `env` when it's imported from `process` and `node:process`.
- [#​10556](https://github.com/biomejs/biome/pull/10556) [`7ff6b16`](https://github.com/biomejs/biome/commit/7ff6b165f2f62a0836446dee889d9868f12fb06e) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10492](https://github.com/biomejs/biome/issues/10492): Biome no longer crashes with a stack overflow on certain code when a type-aware rule such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/), or [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) is enabled. For example, the following code used to crash Biome:
```js
function f(visitor) {
let ctrl = visitor();
for (const x of [0]) ctrl = ctrl();
}
```
- [#​10532](https://github.com/biomejs/biome/pull/10532) [`1da3c75`](https://github.com/biomejs/biome/commit/1da3c7573cdb1d097fc1773fee686140d95f3f35) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - CSS declarations with comments before `:` or after `!important` now preserve spaces before `:` and `;`.
```diff
.selector {
- padding/* name */: 1px;
- color: red !important /* note */;
+ padding/* name */ : 1px;
+ color: red !important /* note */ ;
}
```
- [#​10491](https://github.com/biomejs/biome/pull/10491) [`a1b5834`](https://github.com/biomejs/biome/commit/a1b5834d4968fd518cc4adfa0e8b4b65b2232637) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed the Svelte parser rejecting `{#each}` blocks where the binding uses object destructuring with property renaming, e.g. `{#each items as { id, component: Filter }}`. Biome now correctly parses and formats these rename bindings.
- [#​10490](https://github.com/biomejs/biome/pull/10490) [`99bc7df`](https://github.com/biomejs/biome/commit/99bc7df1d1cbb599e9713da56c29763cd04bb53c) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed the CSS parser rejecting comma-separated selector lists inside `:global()` and `:local()` pseudo-class functions. Biome now correctly parses `:global(.foo, .bar)`.
- [#​10543](https://github.com/biomejs/biome/pull/10543) [`c394fae`](https://github.com/biomejs/biome/commit/c394faeaa27f9f7db8ba075afc6657c0245d8276) Thanks [@​mangod12](https://github.com/mangod12)! - Fixed [#​10477](https://github.com/biomejs/biome/issues/10477): The RDJSON reporter now emits code replacement text for fix suggestions instead of the human-readable fix description.
- [#​10530](https://github.com/biomejs/biome/pull/10530) [`e8e1e6a`](https://github.com/biomejs/biome/commit/e8e1e6aa1b39d1e19d33c12d4b56d6d3fd01a7ce) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​10493](https://github.com/biomejs/biome/issues/10493): [`useImportType`](https://biomejs.dev/linter/rules/use-import-type/) now correctly separates types from a default named import when all imports are types and the `style` option is set to `separatedType`.
- [#​10555](https://github.com/biomejs/biome/pull/10555) [`263c7cc`](https://github.com/biomejs/biome/commit/263c7ccd12cd8c0d4527fdf4797c652a223df012) Thanks [@​Mokto](https://github.com/Mokto)! - Improved Svelte lint rule accuracy for quoted attribute values containing `{expression}` interpolations.
- [`noRedundantAlt`](https://biomejs.dev/linter/rules/no-redundant-alt/) no longer emits false positives when the alt text contains an interpolation, e.g. `alt="image of {person}"`.
- [`useButtonType`](https://biomejs.dev/linter/rules/use-button-type/) no longer emits false positives for dynamic button types written as `type="{dynamicType}"`.
- [`noScriptUrl`](https://biomejs.dev/linter/rules/no-script-url/) no longer emits false positives for dynamic hrefs such as `href="{url}"`.
- [#​10489](https://github.com/biomejs/biome/pull/10489) [`96ef9a4`](https://github.com/biomejs/biome/commit/96ef9a4c2647a71d917485f6791e151cf8b88c96) Thanks [@​Mokto](https://github.com/Mokto)! - Fixed Svelte `{#each}` parser incorrectly rejecting TypeScript `as const` type assertions in the iterable expression. Biome now correctly parses `{#each arr as const as item}`.
- [#​10539](https://github.com/biomejs/biome/pull/10539) [`935c59a`](https://github.com/biomejs/biome/commit/935c59a6657022c37c9b9933c66cc29c236e5aff) Thanks [@​dyc3](https://github.com/dyc3)! - Improved how diagnostics print long lines of code, for example minified files where the entire source code is printed in one line.
### [`v2.4.16`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2416)
[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.15...@biomejs/biome@2.4.16)
##### Patch Changes
- [#​10329](https://github.com/biomejs/biome/pull/10329) [`ef764d5`](https://github.com/biomejs/biome/commit/ef764d51b9f5be18ec5a4f9b4dce732512e5d805) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed an issue where diagnostics showed an incorrect location in Astro files.
- [#​10363](https://github.com/biomejs/biome/pull/10363) [`50aa415`](https://github.com/biomejs/biome/commit/50aa4157599a1ac5c77c13bce81f5c87240beff0) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed HTML formatting for a case where comments could cause the formatter to split up a closing tag, which would cause the resulting HTML to be syntactically invalid.
Input:
```html
<span
><!-- 1
--><span>a</span
><!-- 2
--><span>b</span
><!-- 3
--></span>
```
Output:
```diff
<span
><!-- 1
- --> <span>a</span<!-- 2
- --> ><span>b</span><!-- 3
+ --><span>a</span><!-- 2
+ --><span>b</span><!-- 3
--></span
>
```
- [#​10465](https://github.com/biomejs/biome/pull/10465) [`0c718da`](https://github.com/biomejs/biome/commit/0c718da81770f47d65845bc1a006f99512d9359b) Thanks [@​dfedoryshchev](https://github.com/dfedoryshchev)! - Fixed diagnostics emitted by the `noUntrustedLicenses` rule.
- [#​10358](https://github.com/biomejs/biome/pull/10358) [`05c2617`](https://github.com/biomejs/biome/commit/05c26176573534a0abfa92d454d244f9569bc77d) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10356](https://github.com/biomejs/biome/issues/10356): `biome rage --linter` now displays rules enabled through linter domains in the enabled rules list.
- [#​10300](https://github.com/biomejs/biome/pull/10300) [`950247c`](https://github.com/biomejs/biome/commit/950247c389e693c16b47d61d8ef0f1b85d1a1b02) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10265](https://github.com/biomejs/biome/issues/10265): Svelte function bindings such as `bind:value={get, set}` are now parsed more precisely, so [`noCommaOperator`](https://biomejs.dev/linter/rules/no-comma-operator/) won't emit false positives for that syntax anymore.
- [#​9786](https://github.com/biomejs/biome/pull/9786) [`e71f584`](https://github.com/biomejs/biome/commit/e71f58490f3121432d1bc24ae5330ecf96391a40) Thanks [@​MeGaNeKoS](https://github.com/MeGaNeKoS)! - Fixed [#​8480](https://github.com/biomejs/biome/issues/8480): [`useDestructuring`](https://biomejs.dev/linter/rules/use-destructuring/) now provides `variableDeclarator` and `assignmentExpression` options to control which contexts enforce destructuring, matching ESLint's `prefer-destructuring` configuration. Both default to `{array: true, object: true}`. The diagnostic for object destructuring in assignment expressions now instructs users to wrap the assignment in parentheses.
- [#​10425](https://github.com/biomejs/biome/pull/10425) [`1948b72`](https://github.com/biomejs/biome/commit/1948b7242e092ed0cfcf501ef6f119202b8ea93b) Thanks [@​sjh9714](https://github.com/sjh9714)! - Fixed [#​10244](https://github.com/biomejs/biome/issues/10244): The `useOptionalChain` rule now detects negated guard inequality chains like `!foo || foo.bar !== "x"`.
- [#​10442](https://github.com/biomejs/biome/pull/10442) [`001f94f`](https://github.com/biomejs/biome/commit/001f94f696d9baca3c231d39895a01d4dd528d52) Thanks [@​ematipico](https://github.com/ematipico)! - Fixed [#​10411](https://github.com/biomejs/biome/issues/10411): [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) no longer causes a stack overflow when a nested function returns an object with shorthand properties that shadow destructured variables from an outer scope.
- [#​10318](https://github.com/biomejs/biome/pull/10318) [`9b1577f`](https://github.com/biomejs/biome/commit/9b1577fa400279d9b0222cbc920cfa9ddcf1c9d6) Thanks [@​dyc3](https://github.com/dyc3)! - Added support for `formatter.trailingCommas` in overrides. This option was previously available in the top-level formatter configuration but missing from formatter overrides.
- [#​10319](https://github.com/biomejs/biome/pull/10319) [`2e37709`](https://github.com/biomejs/biome/commit/2e3770923f9fb4e33606113e726014f7b63730d0) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed Vue and Svelte formatting for standalone interpolations in inline elements. Biome now preserves existing newlines in cases like:
```diff
- <span> {{ value }} </span>
+ <span>
+ {{ value }}
+ </span>
```
- [#​10365](https://github.com/biomejs/biome/pull/10365) [`0a58eb0`](https://github.com/biomejs/biome/commit/0a58eb0982460b757a26f94d958a7e40c0686227) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10361](https://github.com/biomejs/biome/issues/10361): [`noUnusedFunctionParameters`](https://biomejs.dev/linter/rules/no-unused-function-parameters/) now mentions the parameter name in the diagnostic.
- [#​10439](https://github.com/biomejs/biome/pull/10439) [`df6b867`](https://github.com/biomejs/biome/commit/df6b867bb6fd210cc75ac03d832e7281eced5b61) Thanks [@​denbezrukov](https://github.com/denbezrukov)! - Fixed CSS and SCSS formatting for comments around declaration colons so comments between property names, colons, and values stay at the same boundary as Prettier.
```diff
.selector {
- color: /* red, */
- blue;
+ color: /* red, */ blue;
}
```
- [#​10344](https://github.com/biomejs/biome/pull/10344) [`b30208c`](https://github.com/biomejs/biome/commit/b30208c06365907d6fb376f030bc75bbf5e3dea9) Thanks [@​siketyan](https://github.com/siketyan)! - Fixed [`#10123`](https://github.com/biomejs/biome/issues/10123): Corrected the [`noReactNativeDeepImports`](https://biomejs.dev/linter/rules/no-react-native-deep-imports/) source rule to point to the proper upstream rule, so users can migrate from the original rule correctly.
- [#​10328](https://github.com/biomejs/biome/pull/10328) [`b59133f`](https://github.com/biomejs/biome/commit/b59133fd2a8afa33564914df531f7f752b48ecee) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10309](https://github.com/biomejs/biome/issues/10309): Biome no longer adds newlines to Astro frontmatter when linter or assist `--write` mode is enabled.
</details>
<details>
<summary>haydenbleasel/ultracite (ultracite)</summary>
### [`v7.11.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.11.1)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.11.0...ultracite@7.11.1)
##### Patch Changes
- [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update oxfmt to 0.67.0 and re-target the markdown `:::` fence patch to the new dist chunk. The release changes no options; it fixes CSS/SCSS/Less comment preservation and a few JSDoc-cast edge cases in member chains.
- [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update oxlint to 1.82.0. The release adds and removes no rules, so the presets are unchanged apart from one new option: `no-unmodified-loop-condition` now runs with `checkConditionalExpressions: true` in the oxlint and ESLint core presets, so each branch of a ternary in a loop condition must be modified inside the loop rather than only the expression as a whole.
- [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update the ESLint family: `@angular-eslint/eslint-plugin` 22.5, `@typescript-eslint/*` 8.70, `eslint-plugin-solid` 0.18, `eslint-plugin-vue` 10.11, `eslint-plugin-jsdoc` 64.3.8, `eslint-plugin-cypress` 7.0.2, `@darraghor/eslint-plugin-nestjs-typed` 7.5.2 and `prettier-plugin-astro` 1.0. The dynamic presets pick up the seven new rules automatically: `@typescript-eslint/no-generated-empty-object-type`, `@angular-eslint/reactive-context-must-read-signal`, `vue/no-shadow-native-events`, and Solid's `no-boolean-enumerated-attribute`, `no-store-mutation-outside-setter`, `no-unused-signal` and `no-write-in-pure-computation`. Note that `prettier-plugin-astro` 1.0 is a rewrite on the Astro 7 Rust compiler (Node 22.12+); expect whitespace diffs on first run and mirror any custom `compressHTML` via its new `astroCompressHTML` option.
- [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Refresh the stylelint lock to 17.15.0 and enable its new `selector-no-unmatchable` rule, which flags selectors that can never match (for example `label:checked`, `::before:first-child` or `:is(::before)`).
- [`a71dda4`](https://github.com/haydenbleasel/ultracite/commit/a71dda4): Stop sorting object keys across the whole TanStack presets, not just route files. TanStack Query mutation options are order-sensitive too: TypeScript infers the `onMutate` context from context-sensitive callbacks in source order, so moving `onError`/`onSettled` above `onMutate` turns the context into `{}` and `ultracite fix` broke type-correct code (`TS2339: Property '...' does not exist on type '{}'`). Mutation and query options live anywhere (hooks, components, colocated files), so the route-file exemption could not cover them. `ultracite/oxlint/tanstack` now sets `sort-keys` to `off` and `ultracite/biome/tanstack` now sets `useSortedKeys` to `off` for all files.
- [`a9db61c`](https://github.com/haydenbleasel/ultracite/commit/a9db61c): Disable `github/filenames-match-regex` for file-based route directories (`**/routes/**`) in the oxlint js-plugins preset, matching the existing `unicorn/filename-case` exemption in the TanStack preset. TanStack Router filenames such as `__root.tsx`, `$.tsx`, and `posts.$postId.tsx` no longer fail the GitHub filename rule. Resolves [#​799](https://github.com/haydenbleasel/ultracite/issues/799).
### [`v7.11.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.11.0)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.8...ultracite@7.11.0)
##### Minor Changes
- [`d5d241f`](https://github.com/haydenbleasel/ultracite/commit/d5d241f): Add `ultracite upgrade`, and make version drift between Ultracite and its linter visible instead of a crash. Bumping `ultracite` without bumping the linter fails on the next `check`/`fix` with Biome's `Found an unknown key` error (and the equivalent for ESLint and Oxlint), because each release enables rules from a specific linter version.
- `ultracite upgrade` installs the latest `ultracite`, prints a release-notes link for the versions you crossed, then hands off to the freshly installed CLI to reinstall your toolchain at the versions that release was verified with: Biome; ESLint, Prettier, Stylelint and the plugins the preset imports; or Oxlint and Oxfmt. Optional extras already in your `package.json` (framework plugins, Oxlint JS plugins, `oxlint-tsgolint`) are bumped as well. Config files are never rewritten, and the run ends with the same diagnostics as `doctor`.
- `ultracite doctor` now checks the installed Biome, ESLint, Prettier, Stylelint, Oxlint and Oxfmt versions against the range this release supports. Too old fails the check and points at `ultracite upgrade`; newer than the verified range only warns.
- The supported ranges are declared as optional peer dependencies so package managers warn when they drift: `@biomejs/biome ^2.5.0`, `eslint ^10.0.0`, `prettier ^3.0.0`, `stylelint ^17.0.0`, `oxlint ^1.79.0`, `oxfmt >=0.40.0`. `ultracite init` now installs Prettier and Stylelint from those ranges instead of `latest`.
Requires Biome >= 2.5.0, ESLint >= 10.0.0, Prettier >= 3.0.0, Stylelint >= 17.0.0, Oxlint >= 1.79.0 and Oxfmt >= 0.40.0.
##### Patch Changes
- [`27d06f2`](https://github.com/haydenbleasel/ultracite/commit/27d06f2): Update dependencies (`@clack/prompts`, `semver`, `zod`, ESLint plugins).
- [`d322691`](https://github.com/haydenbleasel/ultracite/commit/d322691): Default `ultracite init` to Oxlint + Oxfmt when `--linter` is omitted in quiet or non-interactive mode
- [`c677cf5`](https://github.com/haydenbleasel/ultracite/commit/c677cf5): Recommend Oxlint + Oxfmt in the `ultracite init` linter prompt and list it first
- [`c5be848`](https://github.com/haydenbleasel/ultracite/commit/c5be848): Disable `no-use-before-define` in TanStack Router route files for the oxlint tanstack preset. File routes are mutually recursive (`Route` references the component, and the component calls `Route.useParams()`), so no declaration order could satisfy the rule.
### [`v7.10.8`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.8)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.7...ultracite@7.10.8)
##### Patch Changes
- [`2a43fdd`](https://github.com/haydenbleasel/ultracite/commit/2a43fdd): Turn off `unicorn/prefer-reflect-apply` in the `ultracite/oxlint/anti-slop` preset. When extended after `ultracite/oxlint/core`, the core rule recommended rewriting `Function#apply()` to `Reflect.apply()`, which anti-slop's `no-reflect-apply` then rejected, leaving no way to satisfy both. Direct-call guidance for `.apply()` still comes from `eslint/prefer-spread` and `eslint/no-useless-call`.
- [`03196df`](https://github.com/haydenbleasel/ultracite/commit/03196df): Update `@biomejs/biome` to 2.5.12. Releases 2.5.10 through 2.5.12 only add nursery rules, which the Biome presets exclude, so the presets are unchanged. The releases also carry linter and formatter fixes, including fewer `noUnusedVariables` false positives on merged interfaces, namespaces, and overload type parameters, an unsafe-by-default fix for `noThisInStatic`, and a large batch of Astro expression parsing fixes.
- [`031b867`](https://github.com/haydenbleasel/ultracite/commit/031b867): Update oxfmt to 0.66.0. The 0.65 and 0.66 releases are formatter fixes only, mainly around comment placement between a statement head and its body, suppressed statements (decorators, typecast parens, semicolons), custom side-effect groups in `sortImports`, CommonMark list interruption in JSDoc, and trailing whitespace in YAML block scalars. The `:::` container-directive fence patch is re-targeted to the new markdown bundle; the patched code itself is unchanged.
- [`54affee`](https://github.com/haydenbleasel/ultracite/commit/54affee): Update oxlint to 1.81.0. The 1.80 and 1.81 releases add no rules and remove none, so the presets are unchanged and the peer range stays at ^1.79.0. Notable fixes carried in: `no-use-before-define` now runs on JS and JSX files, `object-shorthand` preserves `__proto__` semantics, `unicorn/prefer-math-min-max` no longer applies an unsafe autofix, and JS plugin diagnostics with invalid or reversed locations are clamped instead of crashing.
- [`0b058d1`](https://github.com/haydenbleasel/ultracite/commit/0b058d1): Fix `ultracite fix --codex` failing on recent Codex CLI releases. The Codex adapter invoked `codex exec --full-auto`, a flag Codex has since removed, so every attempt failed at argument parsing. It now runs `codex exec --sandbox workspace-write`, the equivalent non-interactive, workspace-scoped mode, which is also accepted by older Codex versions. Resolves [#​794](https://github.com/haydenbleasel/ultracite/issues/794).
- [`e2346bb`](https://github.com/haydenbleasel/ultracite/commit/e2346bb): Update the ESLint family to latest: eslint 10.9.1, typescript-eslint 8.69.0, eslint-plugin-unicorn 74, eslint-plugin-solid 0.17, eslint-plugin-jsdoc 64.3.5, eslint-plugin-react-doctor and oxlint-plugin-react-doctor 0.9.13, globals 17.12, and the angular, nestjs-typed, next, tanstack-query, cypress, html, jest and storybook plugins. The dynamic presets pick up the new rules automatically: the solid preset gains the eleven rules added in eslint-plugin-solid 0.16 and 0.17 (`removed-api`, `no-single-arg-create-effect`, `no-accessor-as-prop`, `valid-use-server`, `require-async-server-function`, `no-invalid-server-capture`, `no-browser-globals-in-server-function`, `no-module-scope-reactive-primitive`, `no-restated-default-options`, `prefer-onSettled-for-side-effects`, `prefer-structured-class`), which only report Solid 2.0 issues when `settings.solid.version` is set to 2 and stay silent on Solid 1.x code; the nestjs preset gains `forward-ref-injection-should-use-wrapper-type`, `swagger-file-upload-should-be-documented` and `uploaded-file-should-be-validated`. The curated jsdoc and react-doctor lists are unchanged. No enabled rule was removed or deprecated, and the ESLint/oxlint parity check still passes.
- [`7b0456e`](https://github.com/haydenbleasel/ultracite/commit/7b0456e): `ultracite fix` now runs lint fixes before the formatter: oxlint before oxfmt, and ESLint then Stylelint before Prettier. A fixer can insert unformatted code, such as the braces `curly` adds, the imports `consistent-type-specifier-style` splits, or the font names Stylelint requotes, and running the formatter first left that code unformatted until the next run. Fixer-inserted code is now formatted in the same run. The `--claude` and `--codex` agent passes follow the same order.
`unicorn/no-nested-ternary` is now off in the oxlint and ESLint presets: its fixer adds parentheses that oxfmt and Prettier remove, so the two tools rewrote the file on every run. The core `no-nested-ternary` rule still reports nested ternaries.
- [`8ddc078`](https://github.com/haydenbleasel/ultracite/commit/8ddc078): Enable three rules added in Stylelint 17 in the Stylelint preset: `selector-no-deprecated` and `selector-no-invalid` report selectors that CSS has dropped or that cannot parse, and `relative-selector-nesting-notation` is set to `explicit`, so nested relative selectors are written `& > b` rather than `> b`. The `property-layout-mappings`, `unit-layout-mappings` and `value-keyword-layout-mappings` rules are deliberately left off, since they reject every physical property, unit and keyword and can only autofix with a per-project `languageOptions.directionality` setting. The repo's own Stylelint lock is refreshed from 16.26.1 to 17.14.1, which the config packages already required; `ultracite init` already installs `stylelint@latest` so users are unaffected by the lock change.
- [`4609d79`](https://github.com/haydenbleasel/ultracite/commit/4609d79): Update the vendored `anti-slop` Oxlint plugin to upstream v0.1.2 (commit `e8c4880`). The rule set is unchanged; this picks up a round of correctness fixes: `no-known-value-widening` now also reports known values passed into local `unknown`-typed type predicates, `no-object-parameters`, `no-unknown-parameters`, `no-unknown-returns` and `no-unknown-type-aliases` resolve scoped and transparent generic aliases (including block-scoped aliases and forward references), `no-unknown-returns` covers `PromiseLike<unknown>`, `no-unsafe-dictionary-type` allows generic constraints such as `T extends Record<string, unknown>`, `no-runtime-typeof` always allows existence probes against `"undefined"`, `no-shape-in-symbol-names` allows static member reads such as Zod's `schema.shape`, and `require-safety-comment-for-type-assertion` rejects empty justifications and gains a `markers` option (default `["SAFETY"]`). Upstream also added a separate opt-in `anti-slop-effect` plugin for Effect projects, which is not vendored.
### [`v7.10.7`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.7)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.6...ultracite@7.10.7)
##### Patch Changes
- [`15f7ae0`](https://github.com/haydenbleasel/ultracite/commit/15f7ae0): Add support for the Aube package manager: `ultracite init --pm aube` is now accepted and projects with an `aube-lock.yaml` lockfile are detected automatically
- [`1afc8fe`](https://github.com/haydenbleasel/ultracite/commit/1afc8fe): Re-declare selected Oxlint JS plugins on the root config so dependency analyzers see them. `ultracite init --linter oxlint --js-plugins ...` now generates `const jsPlugins = selectJsPlugins([...])` and adds `jsPlugins: jsPlugins.jsPlugins` to the root config (also when the full `ultracite/oxlint/js-plugins` preset is extended). Knip only resolves `jsPlugins` from the root Oxlint config and never walks `extends`, so `eslint-plugin-github`, `eslint-plugin-sonarjs`, and `oxlint-plugin-react-doctor` were reported as unused devDependencies. Oxlint dedupes the plugin between the root and the extended preset, so linting is unchanged.
Also fix `ultracite update` dropping the `js-plugins` preset from `extends` when the config used the documented `import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"` form: the import parser only matched bare default imports. The regenerated full-preset config keeps `settings: jsPluginSettings` on the root as well.
- [`20b06bf`](https://github.com/haydenbleasel/ultracite/commit/20b06bf): Ignore `.alchemy` across all linters and formatters. Alchemy (alchemy.run) writes local state and generated bindings to a `.alchemy` directory. It is now part of the shared ignore patterns synced into Biome's `files.includes` and imported by oxlint, oxfmt, and ESLint, and the Stylelint preset ignores it via `ignoreFiles`. Prettier needs no change: it already respects `.gitignore`/`.prettierignore`.
- [`6e9286c`](https://github.com/haydenbleasel/ultracite/commit/6e9286c): Run `lefthook install` during `ultracite init` through the same spawn adapter as every other tool invocation instead of `execSync`, so it no longer goes through a shell and gets the same Windows command resolution as `husky`, the linters, and editor extension installs.
- [`8b24f34`](https://github.com/haydenbleasel/ultracite/commit/8b24f34): Add support for the Nub package manager: `ultracite init --pm nub` is now accepted and projects with a `nub.lock` lockfile are detected automatically (requires nypm ^0.6.9)
- [`240cb6b`](https://github.com/haydenbleasel/ultracite/commit/240cb6b): Install into the workspace root correctly for Nub and Aube monorepos: nypm emits no root selector for them, so `nub add` ran without `-w` and was refused. Ultracite now hands nypm pnpm's flag set for these pnpm-compatible CLIs, producing `nub add --workspace-root --save-dev ultracite`
- [`44ecbba`](https://github.com/haydenbleasel/ultracite/commit/44ecbba): Add Vitest type-test files (`**/*.{test-d,spec-d}.{ts,tsx,js,jsx}`) to the test-file globs so the shared test relaxations and the Vitest rule overrides apply to them, and enable the Vitest plugin's `typecheck` setting in the ESLint preset so `expectTypeOf`/`assertType` count as assertions.
- [`7ba6bb8`](https://github.com/haydenbleasel/ultracite/commit/7ba6bb8): Package the reusable Ultracite agent skill with the npm distribution.
### [`v7.10.6`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.6)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.5...ultracite@7.10.6)
##### Patch Changes
- [`972b946`](https://github.com/haydenbleasel/ultracite/commit/972b946): Update the oxlint presets for oxlint 1.79: replace the removed `react/react-compiler` rule with the 22 new React Compiler rules in the react preset, add `jsdoc/no-blank-blocks` and `one-var` to the core preset (mirrored in the ESLint presets), and require oxlint ^1.79.0
- [`2d5bbdb`](https://github.com/haydenbleasel/ultracite/commit/2d5bbdb): Declare the `jsPluginSettings` named export in the `ultracite/oxlint/js-plugins` type declarations, so the documented (and `ultracite init`-generated) `import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"` type-checks ([#​773](https://github.com/haydenbleasel/ultracite/issues/773))
- [`56aef65`](https://github.com/haydenbleasel/ultracite/commit/56aef65): Refresh the toolchain versions that `ultracite init` installs into projects: `@biomejs/biome` 2.5.9, the ESLint plugin family (including eslint-plugin-cypress 7, eslint-plugin-jsdoc 64, eslint-plugin-solid 0.15, and eslint-plugin-unicorn 73 — the dynamic presets adopt their new rules automatically), and `prettier-plugin-svelte` 4.1.1 / `prettier-plugin-tailwindcss` 0.8.1
### [`v7.10.5`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.5)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.4...ultracite@7.10.5)
##### Patch Changes
- [`8df6ad0`](https://github.com/haydenbleasel/ultracite/commit/8df6ad0): Offer the vendored `anti-slop` Oxlint preset during `ultracite init` — it now appears in the JS-plugins prompt when you pick Oxlint, and non-interactive setup accepts it via `--js-plugins anti-slop`. Selecting it adds `ultracite/oxlint/anti-slop` to the generated config's `extends`; since the preset is vendored inside Ultracite, nothing extra is installed.
- [`cd229e9`](https://github.com/haydenbleasel/ultracite/commit/cd229e9): Bump the `oxlint-plugin-react-doctor` pin from `^0.7.1` to `^0.9.12`, so `ultracite init` installs the current plugin. All react-doctor rules enabled by the js-plugins presets still exist in 0.9.12, and the ported rules run in curated mode via the settings shipped alongside this release ([#​771](https://github.com/haydenbleasel/ultracite/issues/771)).
- [`e1ac886`](https://github.com/haydenbleasel/ultracite/commit/e1ac886): Pin React Doctor's ported rules to their framework-aware "curated" mode ([#​771](https://github.com/haydenbleasel/ultracite/issues/771)). react-doctor 0.9.x rewrote its ported oxc/react-refresh rules — notably `only-export-components` — with a stripped-down default mode: no framework detection, no route-file skipping, and `allowConstantExport` off, so Next.js route-segment exports like `export const dynamic = "force-static"` or `metadata` were flagged as non-component exports in every route file. The ESLint react preset now sets `settings["react-doctor"].portedRuleMode: "curated"`, and generated oxlint configs apply a new `jsPluginSettings` export from `ultracite/oxlint/js-plugins` on the root config (oxlint does not merge `settings` from extended configs, so the setting cannot ride along inside the preset). If you extend the js-plugins preset manually, add `settings: jsPluginSettings` to your root oxlint config.
- [`c27fe36`](https://github.com/haydenbleasel/ultracite/commit/c27fe36): Generate oxlint configs that enable a subset of the JS plugins via a new `selectJsPlugins` export from `ultracite/oxlint/js-plugins`, instead of inlining the filtering logic into the generated file. The inlined block contained a `typeof` check that user-side lint presets flagged (`anti-slop/no-runtime-typeof`, [#​770](https://github.com/haydenbleasel/ultracite/issues/770)); the generated config is now a one-line extend, is emitted already formatted (including the previously missing blank line after imports), and re-running `ultracite init` migrates existing configs with the old inlined block automatically.
- [`0616523`](https://github.com/haydenbleasel/ultracite/commit/0616523): Update the vendored `anti-slop` Oxlint plugin to upstream commit `446268e`, picking up fixes to `no-object-parameters` and `no-unknown-returns` (respect lexical type binders in alias resolution) and a new `allowInTypeGuards` option on `no-runtime-typeof`. The `ultracite/oxlint/anti-slop` preset enables `allowInTypeGuards`, so `typeof` checks inside type predicate functions (`(x): x is T`) no longer need disable comments — predicates are the named-boundary pattern the rule pushes toward ([dmmulroy/anti-slop#10](https://github.com/dmmulroy/anti-slop/issues/10)).
### [`v7.10.4`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.4)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.3...ultracite@7.10.4)
##### Patch Changes
- [`417a85a`](https://github.com/haydenbleasel/ultracite/commit/417a85a): Add an opt-in `ultracite/oxlint/anti-slop` preset that ships a vendored, self-contained build of the [anti-slop](https://github.com/dmmulroy/anti-slop) Oxlint plugin — fifteen rules that reject low-evidence TypeScript and JavaScript patterns (unjustified type assertions, `unknown` leaking through signatures, `Reflect`-based access, module mocking, and more). Extend it alongside `ultracite/oxlint/core`; nothing extra to install. The preset also turns off two core rules that conflict with anti-slop's widening checks (`typescript/consistent-indexed-object-style` and `unicorn/no-immediate-mutation`) when extended after core.
- [`4d3fab8`](https://github.com/haydenbleasel/ultracite/commit/4d3fab8): Move `suspicious/useArraySortCompare` from the Biome core config to the opt-in type-aware config. The rule is in Biome's `types` domain — it type-infers the receiver of every method call before checking the method name, which made `ultracite check` up to \~260x slower on projects with expensive library types (zod, better-auth, Prisma). It now only runs when type-aware linting is explicitly enabled, alongside the other type/project-domain rules. Fixes [#​768](https://github.com/haydenbleasel/ultracite/issues/768).
### [`v7.10.3`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.3)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.2...ultracite@7.10.3)
##### Patch Changes
- [`a1fa9c4`](https://github.com/haydenbleasel/ultracite/commit/a1fa9c4): Replace the hand-rolled package `exports` map matching in the config-resolution doctor check with the resolve.exports library, which implements Node's full `PACKAGE_TARGET_RESOLVE` algorithm (wildcard patterns, key-order precedence, conditional exports, and array fallbacks). The manual `node_modules` walk is kept intentionally — it exists to avoid Bun's auto-install cache resolving specifiers the project's own `node_modules` can't.
- [`414ea80`](https://github.com/haydenbleasel/ultracite/commit/414ea80): Replace the hand-rolled monorepo workspace scan in framework detection with the find-workspaces library. Workspace declarations from package.json (array and yarn-classic object form) and pnpm-workspace.yaml — including negated globs — are now resolved by the library instead of manual pattern collection and globbing, and lerna/bolt monorepos are picked up as well.
- [`a9a1989`](https://github.com/haydenbleasel/ultracite/commit/a9a1989): Replace the hand-rolled upward directory walks in `findNearestFile` and `detectLinter` with the empathic library's `find.any`, which checks candidate names in order within each directory before moving to the parent — the same per-directory precedence the previous implementation enforced manually.
- [`27b2707`](https://github.com/haydenbleasel/ultracite/commit/27b2707): Use magicast to update ESM lint-staged config files during `ultracite init`. The config is now edited as an AST instead of being imported and re-serialized, so comments and function-valued entries elsewhere in the config survive the update, and the user's config code is no longer executed. If the Ultracite glob pattern is already owned by a non-array value, or the config isn't a mergeable object literal (e.g. `defineConfig(...)`), init warns and leaves the file untouched instead of rewriting it. CommonJS configs keep the previous behavior.
- [`f2529b8`](https://github.com/haydenbleasel/ultracite/commit/f2529b8): Rewrite the agent-fix progress renderer on top of log-update, cli-truncate, and string-width. log-update now owns the in-place block rewriting that was previously done with manual cursor-up/clear-line escape sequences, and line truncation is measured by display width instead of code units — so lint messages containing emoji or CJK text can no longer overflow the terminal row and corrupt the animated block.
- [`277b9d6`](https://github.com/haydenbleasel/ultracite/commit/277b9d6): Replace the hand-rolled child-process handling in the agent fix runner with execa. The timeout → SIGTERM → grace period → SIGKILL escalation, stderr capture, and spawn-failure handling now use execa's `timeout` and `forceKillAfterDelay` options, which are battle-tested across platforms (including Windows kill semantics the manual implementation didn't cover). Behavior is unchanged: agent runs still time out after 5 minutes, escalate to SIGKILL after a 10-second grace period, and report a capped stderr tail.
- [`1614a80`](https://github.com/haydenbleasel/ultracite/commit/1614a80): Drop the direct cross-spawn dependency: all synchronous process spawning (linter runs, tool version checks, editor extension installs, skill installs) now goes through a small adapter over execa's sync API, which owns the Windows spawn semantics cross-spawn provided. The adapter preserves the spawnSync result shape (`status`/`signal`/`error`/`stdout`), always disables shell interpretation, and always decodes output as UTF-8. execa was already a dependency for the agent fix runner, so this consolidates on one process-spawning library.
- [`ac114b4`](https://github.com/haydenbleasel/ultracite/commit/ac114b4): Replace the glob dependency with fast-glob for the tsconfig.json scan during init. fast-glob was already in the dependency tree via find-workspaces, so this drops glob's transitive dependencies (minipass, path-scurry, etc.) from the install without changing behavior.
### [`v7.10.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.2)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.1...ultracite@7.10.2)
##### Patch Changes
- [`1c48c68`](https://github.com/haydenbleasel/ultracite/commit/1c48c68): Enable Tailwind CSS class sorting (`sortTailwindcss`) in the Oxfmt preset. Classes in `class`/`className` attributes and in `clsx`, `cva`, `tw`, `twMerge`, `cn`, `twJoin`, and `tv` calls are now sorted using the same algorithm as `prettier-plugin-tailwindcss`, matching the behavior of the Prettier preset (which always loads the Tailwind plugin) and the Biome preset's `useSortedClasses` rule. Projects without Tailwind installed are unaffected beyond class strings being sorted against the default theme, and oxfmt versions older than 0.35.0 ignore the option.
- [`dc78be4`](https://github.com/haydenbleasel/ultracite/commit/dc78be4): Stop sorting TanStack route option keys in route files. TanStack Router's route option types are order-sensitive (`head`/`component` infer `loaderData` from properties declared before them), so the Biome `useSortedKeys` source action rewrote `createFileRoute` literals into an order that breaks type inference (`loaderData` becomes `never`). The Biome TanStack preset now disables `useSortedKeys` for route files, and the oxlint TanStack preset disables `sort-keys` there so route files aren't caught between it and `react-doctor/tanstack-start-route-property-order`.
### [`v7.10.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.1)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.0...ultracite@7.10.1)
##### Patch Changes
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix several agent fix mode (`fix --claude`/`--codex`) issues: runs no longer abort with ENOBUFS when linter JSON output exceeds 1MB, user-supplied format/reporter flags can no longer override the JSON reporter and break parsing, a stuck agent process is force-killed 10 seconds after the timeout instead of hanging forever, and the progress renderer no longer garbles TTY output when file paths and rule names exceed the terminal width.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Biome config migration leaving the legacy bare `"extends": ["ultracite"]` form in place, which breaks Biome's module resolution since the package has no root export. It's now mapped to `ultracite/biome/core`.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite doctor` reporting spurious failures: config checks now walk up parent directories (matching `check`/`fix` and the linters themselves) so monorepo packages inheriting a root config pass, `.oxlintrc.json` is accepted as a valid oxlint config (with a migration suggestion), and Prettier/Stylelint configs declared via `package.json` keys are recognized.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite init` corrupting existing Prettier/Stylelint/ESLint configs by writing an ESM module into JSON/YAML/TOML/CJS config files (e.g. `.prettierrc`, `eslint.config.cjs`). Updates now write the default `.mjs` config instead and remove the incompatible file so it can't shadow the new one.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite check`/`fix` misrouting space-separated flag values (e.g. `--max-warnings 10`) into the file list, which scrambled the underlying linter invocation and made formatters fail on bogus targets. Positional files listed before a `--` separator are also kept as lint targets instead of being reclassified as passthrough, which could silently widen formatter runs to the whole project.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Lefthook and pre-commit YAML updates silently doing nothing on common config shapes: the Lefthook job is now inserted correctly when `jobs:` isn't the first key under `pre-commit:` (and no longer matches a `jobs:` key in a different hook), `repos: []` in `.pre-commit-config.yaml` is handled, and shapes that can't be safely edited produce a warning instead of writing the file back unchanged.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix the Husky integration overwriting an existing `.husky/pre-commit` hook: `ultracite init` ran `husky init`, which unconditionally replaces the hook with `npm test`. It now runs plain `husky` to set up the hooks infrastructure without touching the hook file.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite init` destroying user files it couldn't parse or merge: unparseable `tsconfig.json` files are no longer replaced with a minimal config, unparseable `.vscode`/`.zed` settings are no longer overwritten wholesale, and lint-staged configs with function-valued entries are left untouched — all now warn and skip instead.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix re-running `ultracite init` on an oxlint setup silently enabling the full js-plugins preset — the previously selected JS plugins are now preserved when no new selection is made. Init also no longer flips an explicit `"type": "commonjs"` in package.json to `"module"`; it warns instead.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix switching linters removing `storybook` from the project's dependencies. It was swept into the removal set as a peer of `eslint-plugin-storybook`, but it's a user-facing tool a project may use independently of linting.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Stylelint target generation dropping directories with a dot in their name (e.g. `app.web`) and producing non-matching globs from Windows-style backslash paths. Framework detection also handles negated workspace patterns (`!packages/legacy`) again.
- [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix the CLI becoming a silent no-op (exiting 0 without linting anything) when a generic `TEST` environment variable is set, as is common in CI matrices. The internal test guard now uses `ULTRACITE_TEST`.
- [`36c7b80`](https://github.com/haydenbleasel/ultracite/commit/36c7b80): Move [@​typescript-eslint/utils](https://github.com/typescript-eslint/utils) from dependencies to devDependencies. It was accidentally shipped as a runtime dependency in 7.9.0, pulling eslint and the typescript-eslint packages into every consumer's install (including oxlint-only setups) via npm's automatic peer dependency installation. Nothing in the published package imports it — it only exists to support the workspace-internal rule-parity script.
### [`v7.10.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.0)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.4...ultracite@7.10.0)
##### Minor Changes
- [`cd0a36c`](https://github.com/haydenbleasel/ultracite/commit/cd0a36c): Add `--claude` and `--codex` flags to `ultracite fix`. After the normal autofix pass, remaining diagnostics are handed to the Claude Code or Codex CLI non-interactively, one agent run per affected file, with a live per-issue spinner that flips to ✓/✗ once the fix is verified by a re-lint. Fixes that don't survive verification are retried (up to 3 attempts per file) with the fresh diagnostics and feedback that the previous approach failed. Works with all three linter modes (Oxlint, Biome, ESLint); exits non-zero if any issues remain, matching the plain `fix` contract.
- [`e089510`](https://github.com/haydenbleasel/ultracite/commit/e089510): Scope React Doctor's framework-specific rules to per-framework add-on presets ([#​752](https://github.com/haydenbleasel/ultracite/issues/752))
The `ultracite/oxlint/js-plugins` preset no longer enables React Doctor's `nextjs-*` and TanStack (`query-*`, `tanstack-start-*`) rules for every consumer. Rules like `nextjs-no-img-element` and `tanstack-start-no-anchor-element` fire on plain `<img>`/`<a>` JSX and recommend framework replacements, which falsely errored in Vite + React and other non-Next/non-TanStack projects.
Those rules now live in two new add-on presets:
- `ultracite/oxlint/next/js-plugins`
- `ultracite/oxlint/tanstack/js-plugins`
`ultracite init` wires the matching add-on automatically when you select the framework together with `oxlint-plugin-react-doctor`. If you manage `oxlint.config.ts` by hand and use Next.js or TanStack, add the matching add-on preset to `extends` alongside `js-plugins` to keep those rules — or re-run `npx ultracite init`.
Also fixes re-running `init` on a config that already extends `js-plugins` producing a duplicate `import jsPlugins` declaration.
##### Patch Changes
- [`3320cd8`](https://github.com/haydenbleasel/ultracite/commit/3320cd8): Update Biome to 2.5.6. No stable (non-nursery) rules were added, removed, or promoted between 2.5.3 and 2.5.6, so the preset configs are unchanged.
- [`477cd6e`](https://github.com/haydenbleasel/ultracite/commit/477cd6e): Update ESLint to 10.8.0 and all ESLint plugins to their latest versions. Highlights:
- `eslint-plugin-react-doctor` 0.9.3: the react preset expands from 149 to 417 rules, adopting the upstream `recommended` set (react-router, three.js/r3f, ink, motion, remotion, zustand/valtio/mobx, and more) while excluding rules that duplicate already-enabled `react`, `react-hooks`, and `jsx-a11y` rules. The next preset gains `nextjs-async-dynamic-api-not-awaited` and `nextjs-metadata-url-consistency`; the tanstack preset gains `tanstack-start-missing-scripts`, `query-floating-mutate-async`, and `query-no-mutation-in-effect-as-read`.
- `eslint-plugin-unicorn` 72: adds `no-missing-local-resource`, `no-multiple-promise-resolver-calls`, `no-shorthand-property-overrides`, `no-transition-all`, `no-unnecessary-string-trim`, `no-useless-re-export`, `prefer-then-catch`, and `require-frontmatter-fields`. CSS-only rules are excluded from the preset since they fail config validation for JS files.
- `eslint-plugin-sonarjs` 4.2: adds 11 rules including `no-fixed-wait-in-tests`, `parameterized-tests`, `assertions-in-test-cases`, `prefer-native-lodash-alternative`, and `explicit-test-skip`.
- `typescript-eslint` 8.65: `@typescript-eslint/no-loop-func` and `@typescript-eslint/no-restricted-imports` were deprecated upstream in favor of the base rules, which now apply to TypeScript files.
- `eslint-plugin-astro` 3: removes `astro/no-omitted-end-tags` and `astro/valid-compile`.
- `eslint-plugin-svelte` 3.22: adds `no-bind-value-on-checkable-inputs` and `no-conflicting-module-names`; `no-restricted-html-elements` is now off because its schema requires a user-supplied element list.
- `@angular-eslint/eslint-plugin` 22.1: adds `inject-at-top` and `prefer-service-decorator`.
- [`b81578b`](https://github.com/haydenbleasel/ultracite/commit/b81578b): Fix the useSortedPackageJson action not being executed by turning on assist actions for package.json-like files.
- [`9ec454a`](https://github.com/haydenbleasel/ultracite/commit/9ec454a): Update oxlint to 1.76.0 and oxfmt to 0.61.0. New stable rules added to the presets: `oxc/bad-match-all-arg`, `id-denylist`, `node/exports-style` (core), `react/function-component-definition` with arrow-function components (react), and `vitest/padding-around-test-blocks` (vitest). `node/no-top-level-await` is off — top-level await is idiomatic in ESM, Astro frontmatter, and build scripts — and the ESLint preset's `n/no-top-level-await` is now off to match. No rules were removed or promoted out of nursery.
- [`ba61c02`](https://github.com/haydenbleasel/ultracite/commit/ba61c02): Fix generated oxlint.config.ts accessing plugin.name on ExternalPluginEntry without narrowing the string form, which caused a TypeScript error in projects that type-check the config ([#​753](https://github.com/haydenbleasel/ultracite/issues/753))
### [`v7.9.4`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.4)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.3...ultracite@7.9.4)
##### Patch Changes
- [`f480c12`](https://github.com/haydenbleasel/ultracite/commit/f480c12): Upgrade Biome to 2.5.3 to fix the LSP scanner deadlock ([#​10845](https://github.com/biomejs/biome/issues/10845)) where editors get stuck on "Biome is scanning the project".
- [`1d70c40`](https://github.com/haydenbleasel/ultracite/commit/1d70c40): Fail fast with an actionable message when Biome can't resolve `ultracite/biome/core`. Biome resolves that config out of the project's `node_modules`, so it errors with an opaque "module not found" whenever Ultracite isn't installed there — a state `npx ultracite check` / `bunx ultracite check` hide, because they run the CLI from a temp cache regardless. `check` and `fix` now detect it before invoking Biome and say what's actually wrong, and `doctor` verifies that Ultracite resolves rather than just appearing in `package.json` ([#​750](https://github.com/haydenbleasel/ultracite/issues/750)).
- [`38d10bc`](https://github.com/haydenbleasel/ultracite/commit/38d10bc): Move Biome's `noUnknownAttribute` rule out of the core preset and into the `react` preset. The rule only recognises React's JSX attribute names, so projects using Solid, Svelte, Vue, or Qwik were incorrectly flagged for framework-standard attributes such as `class`.
- [`cf723bd`](https://github.com/haydenbleasel/ultracite/commit/cf723bd): Add interactive and non-interactive selection for optional Oxlint JS plugins during init.
### [`v7.9.3`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.3)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.2...ultracite@7.9.3)
##### Patch Changes
- [`dc6d760`](https://github.com/haydenbleasel/ultracite/commit/dc6d760): Disable the `n/no-unpublished-import` rule in the ESLint core config. This rule flags imports of packages that aren't listed as published dependencies, but it produces a lot of false positives in practice, so it's now turned off.
- [`15ecfba`](https://github.com/haydenbleasel/ultracite/commit/15ecfba): Fix `ultracite init --linter eslint` installing an unusable toolchain. The generated ESLint config imports `eslint-plugin-storybook` unconditionally (which requires the `storybook` peer) and the generated Stylelint config extends `stylelint-config-standard` / `stylelint-config-idiomatic-order` / `stylelint-prettier`, but none of those packages were installed — so a fresh ESLint setup failed to load with "Cannot find package 'storybook'" or "Could not find stylelint-config-standard". These four packages are now installed with the ESLint linter.
- [`2f73a41`](https://github.com/haydenbleasel/ultracite/commit/2f73a41): Upgrade to oxlint 1.73.0 and oxfmt 0.58.0, and enable the new lint rules they introduce: `no-unreachable-loop`, `unicorn/explicit-timer-delay`, and `unicorn/no-confusing-array-with`.
- [`83b2783`](https://github.com/haydenbleasel/ultracite/commit/83b2783): Add an `[astro]` formatter mapping (`astro-build.astro-vscode`) to the oxlint VS Code editor settings generated by `ultracite init`, since oxfmt doesn't format `.astro` files.
- [`d186c53`](https://github.com/haydenbleasel/ultracite/commit/d186c53): Move every JS-plugin-based rule set out of the Oxlint core and framework presets and into a single opt-in `ultracite/oxlint/js-plugins` preset. This covers `eslint-plugin-github` and `eslint-plugin-sonarjs` (previously in core) as well as `oxlint-plugin-react-doctor` (previously bundled into the `react`, `next`, and `tanstack` presets). The core, `react`, `next`, and `tanstack` presets now run entirely on Oxlint's native Rust rules, so new setups no longer install those dependencies and no longer pay the slower JS-plugin lint pass. To keep the extra ESLint-parity and React Doctor rules, install `eslint-plugin-github`, `eslint-plugin-sonarjs`, and `oxlint-plugin-react-doctor` and extend `ultracite/oxlint/js-plugins` alongside `core` (and your framework preset).
- [`057753e`](https://github.com/haydenbleasel/ultracite/commit/057753e): Add performance benchmarks for `ultracite check` / `ultracite fix` across all three providers (oxlint, biome, eslint). A new CI job builds the PR and its base branch on the same runner, benchmarks them interleaved, and fails on a statistically significant regression (median ratio > 1.25x with Mann-Whitney U p < 0.05) so config changes can't silently slow the linters down again.
### [`v7.9.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.2)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.1...ultracite@7.9.2)
##### Patch Changes
- [`c335a1f`](https://github.com/haydenbleasel/ultracite/commit/c335a1f): Add `**/node_modules` and `**/.git` to the shared ignore patterns. oxlint only skips `node_modules` when a `.gitignore` lists it, so in projects without one, `ultracite fix` would lint and autofix files inside `node_modules` — corrupting installed packages (e.g. rewriting `var` enum wrappers in `typescript/lib/typescript.js` to self-referencing `const`, causing "Cannot access 'Comparison' before initialization" when oxlint loads eslint-plugin-sonarjs). Fixes [#​737](https://github.com/haydenbleasel/ultracite/issues/737).
### [`v7.9.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.1)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.0...ultracite@7.9.1)
##### Patch Changes
- [`ecd10cc`](https://github.com/haydenbleasel/ultracite/commit/ecd10cc): Disable `sonarjs/no-implicit-dependencies` and `github/no-implicit-buggy-globals` in the oxlint and ESLint presets. Both produce false positives through oxlint's JS plugin bridge: `no-implicit-dependencies` has no dependency-manifest resolution so it flags builtin (`bun:test`) and workspace imports as missing dependencies, and `no-implicit-buggy-globals` misreads module-scoped declarations such as Astro frontmatter as implicit globals.
- [`c76f59d`](https://github.com/haydenbleasel/ultracite/commit/c76f59d): Disable `sonarjs/file-name-differ-from-class` in the oxlint and ESLint presets. It fires on any file whose name differs from an exported class, which is noise for the many config and module files that export objects rather than classes.
- [`29e30ce`](https://github.com/haydenbleasel/ultracite/commit/29e30ce): Fold the github and sonarjs rules into the oxlint core preset. The standalone `ultracite/oxlint/github` and `ultracite/oxlint/sonarjs` presets are removed — ultracite ships framework presets, not individual plugins. Their rules now live in `ultracite/oxlint/core`, so every oxlint setup gets eslint-plugin-github and eslint-plugin-sonarjs through oxlint's JS plugin bridge, matching how the ESLint preset already bundles them into core.
This is a breaking change to generated configs: `ultracite/oxlint/github` and `ultracite/oxlint/sonarjs` no longer exist. Re-run `ultracite init` to regenerate `oxlint.config.ts`.
Also fixed: nine sonarjs rules (`async-test-assertions`, `hooks-before-test-cases`, `no-duplicate-test-title`, `no-empty-test-title`, `no-floating-point-equality`, `no-forced-browser-interaction`, `no-trivial-assertions`, `prefer-specific-assertions`, `super-linear-regex`) that exist in eslint-plugin-sonarjs but that oxlint's JS plugin bridge does not register. Naming them made oxlint hard-fail config parsing, which broke `ultracite fix`/`check` for oxlint projects using the sonarjs preset. They are omitted from oxlint core (still enabled in the ESLint preset), and a test now runs oxlint against core to catch this class of regression.
The React Doctor, github, and sonarjs plugins are installed into your project's devDependencies at init (as the ESLint plugins already were), rather than bundled as dependencies of ultracite — oxlint resolves JS plugin specifiers from the project root, so they must be installed there directly.
- [`8a4291f`](https://github.com/haydenbleasel/ultracite/commit/8a4291f): Upgrade to Oxlint 1.72.0 and Oxfmt 0.57.0. Oxfmt 0.57 adds native CSS and GraphQL formatters. The five new non-nursery Oxlint rules from the 1.71/1.72 releases are already covered by the presets (`node/no-sync`, `node/no-mixed-requires`, `unicorn/prefer-number-coercion`, `unicorn/max-nested-calls`, `vue/no-async-in-computed-properties`). The markdown `:::` container-directive fence patch (which keeps `proseWrap: "never"` from folding fences into prose) was regenerated against the 0.57 bundle.
### [`v7.9.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.0)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.8.4...ultracite@7.9.0)
##### Minor Changes
- [`aea7fc0`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/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`](https://github.com/haydenbleasel/ultracite/commit/e24068b): Sort `package.json` keys when using Biome
### [`v7.8.4`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.8.4)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.8.3...ultracite@7.8.4)
##### Patch Changes
- [`e4ddd22`](https://github.com/haydenbleasel/ultracite/commit/e4ddd22): Ignore `.yarn` directories by default
- [`a1d5c06`](https://github.com/haydenbleasel/ultracite/commit/a1d5c06): Configure Oxfmt to never wrap prose (`proseWrap: "never"`)
- [`df709a4`](https://github.com/haydenbleasel/ultracite/commit/df709a4): Ignore `.wrangler` and `.wrangler-dry-run` output directories by default
### [`v7.8.3`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.8.3)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.8.2...ultracite@7.8.3)
##### Patch Changes
- [`c863d09`](https://github.com/haydenbleasel/ultracite/commit/c863d09): Fix automatic editor extension installation during `ultracite init`.
The whole command line (e.g. `code --install-extension`) was passed to
`spawnSync` as the executable name, which always failed with `ENOENT` and
silently fell back to the "install manually" message. The command is now split
into the binary and its arguments, so the linter extension actually installs
for VS Code-based editors.
- [`6888129`](https://github.com/haydenbleasel/ultracite/commit/6888129): Enable the `eslint/no-await-in-loop` rule as an error in the core Oxlint
preset.
Awaiting inside a loop forces each iteration to run sequentially, which can
lead to serious performance issues when the asynchronous operations could
otherwise run concurrently. Promoting this rule to an error encourages
collecting promises and resolving them together (e.g. with `Promise.all`)
instead of blocking on each one in turn.
- [`62a9b5c`](https://github.com/haydenbleasel/ultracite/commit/62a9b5c): Fix the generated Husky pre-commit hook's error handling and section
replacement.
The standalone hook script set `set -e` and then tried to capture the
formatter's exit code, re-stage files, and print a failure message — but a
non-zero formatter exit terminated the script immediately, so none of that
ever ran. The script now captures the exit code with `|| FORMAT_EXIT_CODE=$?`
so files are re-staged and failures are reported with the right exit code.
Re-running `ultracite init` also deleted everything from the `# ultracite`
marker to the end of the hook, including commands the user added after the
ultracite section. The section is now terminated with an explicit
`# ultracite end` marker and updates replace only the section between the
markers (legacy sections without an end marker are detected by their closing
echo line).
- [`6608ceb`](https://github.com/haydenbleasel/ultracite/commit/6608ceb): Make the lint-staged integration idempotent and respect dedicated config
files.
`package.json` was always treated as the lint-staged config because the file
exists in every project, so `ultracite init` wrote the lint-staged config into
`package.json` even when a dedicated `.lintstagedrc.*` or
`lint-staged.config.*` file was present — leaving two conflicting configs.
`package.json` now only counts when it actually has a `lint-staged` key;
otherwise the dedicated config file is updated (or `.lintstagedrc.json` is
created).
Re-running `ultracite init` also appended another `npx ultracite fix` entry on
every run because the merge concatenates arrays. Updates are now skipped when
the existing config already references ultracite.
- [`4e847f7`](https://github.com/haydenbleasel/ultracite/commit/4e847f7): Insert `--` before script arguments in npm hook commands.
The post-edit hook command generated for npm projects was
`npm run fix --skip=correctness/noUnusedImports`, where npm consumes the
`--skip` flag itself instead of forwarding it to the script — so agent hooks
ran a plain `ultracite fix`, including the unused-import removal the flag
exists to prevent mid-edit. The generated command is now
`npm run fix -- --skip=correctness/noUnusedImports`, matching the documented
form.
- [`ecb0d5b`](https://github.com/haydenbleasel/ultracite/commit/ecb0d5b): Scope the Stylelint step of `ultracite check` and `ultracite fix` (ESLint mode)
to style files.
Stylelint was previously given the same targets as ESLint and Prettier (or `.`
when no files were passed), so it tried to parse `.ts`/`.json` files as CSS and
failed with `CssSyntaxError`. Style files now pass through unchanged, directory
targets become `**/*.{css,scss,sass,less}` globs, other files are dropped, and
the step is skipped entirely when no style targets remain.
`--allow-empty-input` is passed so projects without CSS still succeed.
- [`61ea0a1`](https://github.com/haydenbleasel/ultracite/commit/61ea0a1): Fix the project-path write guard's error message and ordering.
The "Refusing to write through directory outside project" error interpolated
the `node:path` module instead of the offending file path, printing
`[object Object]`. It now reports the actual path.
`writeProjectFile` also created directories (`mkdir -p`) before running the
path-escape check, so directories could be created outside the project before
the guard threw. Validation now happens first; the parent-directory check
resolves the nearest existing ancestor so writes into not-yet-created nested
directories still work.
### [`v7.8.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.8.2)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.8.1...ultracite@7.8.2)
##### Patch Changes
- [`30971a8`](https://github.com/haydenbleasel/ultracite/commit/30971a8): Enable newly available Oxlint and Stylelint rules in the shared configs.
For Oxlint, the core preset now enables `eslint/prefer-named-capture-group`,
`jsdoc/require-yields-description`, `node/callback-return`,
`typescript/method-signature-style`, and `unicorn/import-style`.
The Vue preset now enables `vue/component-definition-name-casing`,
`vue/no-computed-properties-in-data`, `vue/no-deprecated-props-default-this`,
`vue/no-expose-after-await`, `vue/no-reserved-component-names`,
`vue/no-shared-component-data`, `vue/no-watch-after-await`,
`vue/require-prop-type-constructor`, `vue/require-render-return`,
`vue/require-slots-as-functions`, `vue/return-in-emits-validator`,
`vue/valid-define-options`, and `vue/valid-next-tick`.
The Stylelint preset now enables `display-notation` with the `short` option.
### [`v7.8.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.8.1)
[Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.8.0...ultracite@7.8.1)
##### Patch Changes
- [`8335be7`](https://github.com/haydenbleasel/ultracite/commit/8335be7): Build the CLI with `bun build` and a `tsgo` type-check gate instead of tsup.
- [`f747449`](https://github.com/haydenbleasel/ultracite/commit/f747449): Fix the Oxlint TanStack preset so route files under `routes/` and `app/routes/` are exempt from `unicorn/filename-case`, matching the documented 7.8.0 behavior.
- [`092597e`](https://github.com/haydenbleasel/ultracite/commit/092597e): Fix generated `oxlint.config.ts` to be pre-formatted according to oxfmt rules, so `ultracite check` passes immediately after `ultracite init` without requiring a separate format step.
- [`81da6e8`](https://github.com/haydenbleasel/ultracite/commit/81da6e8): Generate agent and editor hook commands through nypm's package-manager script helper.
- [`81da6e8`](https://github.com/haydenbleasel/ultracite/commit/81da6e8): Keep hyphen-prefixed file operands from being forwarded to linters as options.
</details>
<details>
<summary>astral-sh/uv (uv_build)</summary>
### [`v0.12.13`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#01213)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.12...0.12.13)
Released on 2026-09-10.
##### Python
- Add GraalPy 3.13.0 ([#​21431](https://github.com/astral-sh/uv/pull/21431))
##### Enhancements
- Verify hashes when downloading PEP 658 metadata sidecars ([#​21563](https://github.com/astral-sh/uv/pull/21563))
##### Preview features
- Respect `ty` exclusions when `uv check` automatically selects members of a virtual workspace ([#​21555](https://github.com/astral-sh/uv/pull/21555))
##### Performance
- Avoid full wheel downloads during resolution by reusing supported hashes from direct URL fragments when metadata is available separately ([#​21279](https://github.com/astral-sh/uv/pull/21279))
##### Bug fixes
- Edit Windows entry-point launcher resources in memory to support Nano Server and reduce antivirus contention ([#​18713](https://github.com/astral-sh/uv/pull/18713))
- Prefer `core-metadata` over legacy aliases in JSON index responses ([#​21563](https://github.com/astral-sh/uv/pull/21563))
### [`v0.12.12`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#01212)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.11...0.12.12)
Released on 2026-09-09.
The executables in our macOS and Windows release archives and `uv` and `uv_build` wheels are now code-signed. macOS executables are signed with an Apple Developer ID certificate and notarized by Apple. Windows executables have timestamped Authenticode signatures from Azure Artifact Signing. This enables verification of the release publisher and binary integrity, supports publisher-based allowlisting, and should reduce security warnings and antivirus false positives.
##### Bug fixes
- Exclude distributions uploaded after the `exclude-newer` cutoff from lockfiles and generated requirement hashes ([#​21539](https://github.com/astral-sh/uv/pull/21539))
### [`v0.12.11`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#01211)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.10...0.12.11)
Released on 2026-09-08.
##### Preview features
- Generate missing artifact hashes when exporting `pylock.toml` files to ensure they conform to PEP 751 ([#​20146](https://github.com/astral-sh/uv/pull/20146))
- Warn when `pylock.toml` artifact hash tables are empty, which will be rejected in a future uv release ([#​21462](https://github.com/astral-sh/uv/pull/21462))
##### Performance
- Speed up installs that overwrite existing files by eliminating per-file temporary directories for atomic hard-link, symlink, and reflink replacements ([#​21478](https://github.com/astral-sh/uv/pull/21478))
- Speed up installs that merge copied wheels into existing environments by replacing per-file temporary directories with adjacent temporary files ([#​21468](https://github.com/astral-sh/uv/pull/21468))
- Speed up local wheel installs by replacing the shared ZIP cursor lock with positioned reads ([#​21500](https://github.com/astral-sh/uv/pull/21500))
- Speed up local wheel installs by reusing ZIP readers and buffers across extracted files ([#​21499](https://github.com/astral-sh/uv/pull/21499))
- Avoid transitive dependency checks and unnecessary resolution when `uv pip install --no-deps` finds the requested packages already installed ([#​21523](https://github.com/astral-sh/uv/pull/21523))
##### Bug fixes
- Verify source archives against hashes recorded in `uv.lock` before reading their metadata or running their build backends ([#​21223](https://github.com/astral-sh/uv/pull/21223))
- Verify supplied hashes for registry requirements pinned with `===` under both `--verify-hashes` and `--require-hashes` ([#​21543](https://github.com/astral-sh/uv/pull/21543))
- Apply hashes from public-version pins to matching local versions when no exact local-version hash is provided ([#​21544](https://github.com/astral-sh/uv/pull/21544))
- Support PowerShell virtual environment activation from UNC paths, including WSL paths ([#​19159](https://github.com/astral-sh/uv/pull/19159))
- Trim surrounding whitespace from entries in `.python-version` and `.python-versions` files ([#​21529](https://github.com/astral-sh/uv/pull/21529))
- Suppress `VIRTUAL_ENV` mismatch warnings for `uv add --no-sync`, `uv remove --no-sync`, and `uv add --frozen` ([#​21496](https://github.com/astral-sh/uv/pull/21496))
- Warn and continue when `uv python list` cannot query an interpreter ([#​21498](https://github.com/astral-sh/uv/pull/21498))
##### Documentation
- Restore TOML syntax highlighting for `exclude-newer` examples ([#​21534](https://github.com/astral-sh/uv/pull/21534))
### [`v0.12.10`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#01210)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.9...0.12.10)
Released on 2026-09-04.
##### Enhancements
- Attempt to revoke short-lived PyPI trusted-publishing tokens after `uv publish` completes, including when publishing fails ([#​21423](https://github.com/astral-sh/uv/pull/21423))
##### Preview features
- Omit `exclude-newer-package` settings for packages outside the resolution from `uv.lock` with the `missing-exclude-newer-package-lock` preview feature ([#​21455](https://github.com/astral-sh/uv/pull/21455))
- Show terminal dependency cycles in `uv tree --invert` output ([#​21404](https://github.com/astral-sh/uv/pull/21404))
##### Performance
- Speed up locking large workspaces with conflicts by excluding unrelated extras and dependency groups from conflict simplification ([#​21399](https://github.com/astral-sh/uv/pull/21399))
- Speed up `uv publish` by hashing each artifact in a single blocking task and reusing the buffer across reads ([#​21389](https://github.com/astral-sh/uv/pull/21389))
##### Bug fixes
- Prevent `--locked` from failing when `exclude-newer-package` settings differ only for packages outside the resolution ([#​21454](https://github.com/astral-sh/uv/pull/21454))
- Allow `uv lock --check` to reuse a lockfile when an absolute `exclude-newer` cutoff is moved later ([#​19571](https://github.com/astral-sh/uv/pull/19571))
- Allow `uv lock --check` to reuse a lockfile when a package-specific `exclude-newer` cutoff is disabled ([#​21450](https://github.com/astral-sh/uv/pull/21450))
- Require an explicit `--name` when `uv init` would infer a project name reserved for a Python interpreter ([#​21395](https://github.com/astral-sh/uv/pull/21395))
- Write package-specific `exclude-newer` cutoffs to `uv.lock` in a deterministic order ([#​21453](https://github.com/astral-sh/uv/pull/21453))
### [`v0.12.9`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0129)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.8...0.12.9)
Released on 2026-09-01.
##### Python
- Add CPython 3.15.0rc2 ([#​21413](https://github.com/astral-sh/uv/pull/21413), [#​21415](https://github.com/astral-sh/uv/pull/21415))
##### Enhancements
- Add `--no-locked` and `--no-frozen` to disable lock modes enabled by `UV_LOCKED` and `UV_FROZEN` for a single invocation ([#​21408](https://github.com/astral-sh/uv/pull/21408))
- Report the exact command-line lock-mode flag in warnings and errors ([#​21402](https://github.com/astral-sh/uv/pull/21402))
##### Performance
- Speed up cold wheel installs by extracting each streaming ZIP archive in a single blocking task and reusing buffers across files ([#​21372](https://github.com/astral-sh/uv/pull/21372))
##### Bug fixes
- Update `async_http_range_reader` to 0.11.1 to address a potential memory-safety issue when reading metadata ranges from untrusted wheels ([#​21401](https://github.com/astral-sh/uv/pull/21401))
- Remove sensitive headers when redirects cross authentication realms, including same-host redirects that change URL schemes ([#​21382](https://github.com/astral-sh/uv/pull/21382))
- Redact secrets in signed URLs from retry diagnostics, including nested request errors ([#​21381](https://github.com/astral-sh/uv/pull/21381))
- Give `--locked`, `--frozen`, `--check`, and `--check-exists` precedence over conflicting `UV_LOCKED` and `UV_FROZEN` values ([#​21396](https://github.com/astral-sh/uv/pull/21396))
- Prevent concurrent uv processes from redundantly extracting the same local or source-built wheel ([#​21400](https://github.com/astral-sh/uv/pull/21400))
### [`v0.12.8`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0128)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.7...0.12.8)
Released on 2026-08-31.
##### Enhancements
- Warn about invalid tool directories and continue upgrading valid tools with `uv tool upgrade --all` ([#​21368](https://github.com/astral-sh/uv/pull/21368))
##### Preview features
- Deduplicate identical files within and across cached wheels with the `content-addressed-cache` preview feature ([#​21327](https://github.com/astral-sh/uv/pull/21327))
- Reduce allocations while extracting content-addressed wheels by reusing the hashing buffer across files ([#​21340](https://github.com/astral-sh/uv/pull/21340))
- Speed up content-addressed cache cleanup on macOS by reading hard-link counts in bulk ([#​21344](https://github.com/astral-sh/uv/pull/21344))
##### Performance
- Prevent concurrent uv processes from downloading and extracting the same remote wheel more than once ([#​21379](https://github.com/astral-sh/uv/pull/21379))
- Speed up dependency graph construction from large lockfiles by indexing packages during traversal ([#​21373](https://github.com/astral-sh/uv/pull/21373))
- Extend indexed lockfile traversal to exports, dependency trees, audits, and freshness checks ([#​21377](https://github.com/astral-sh/uv/pull/21377))
- Speed up warm resolutions by reducing repeated marker interner work ([#​21300](https://github.com/astral-sh/uv/pull/21300))
##### Bug fixes
- Do not trust hashes from direct URLs discovered only in wheel metadata when installing with `--require-hashes` ([#​21348](https://github.com/astral-sh/uv/pull/21348))
- Use a compatible Azure Storage API version for anonymous and authenticated requests, allowing credential retries when public access is disabled ([#​21366](https://github.com/astral-sh/uv/pull/21366))
- Redact Azure shared access signature (`sig`) query parameters from displayed URLs ([#​21360](https://github.com/astral-sh/uv/pull/21360))
- Treat projects below one-level workspace member globs as standalone instead of aborting workspace discovery ([#​21341](https://github.com/astral-sh/uv/pull/21341))
##### Other changes
- Update `astral-tokio-tar` to 0.7.0 and use effective sizes when tracking extracted hard links ([#​21346](https://github.com/astral-sh/uv/pull/21346))
### [`v0.12.7`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0127)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.6...0.12.7)
Released on 2026-08-27.
##### Python
- Replace managed Python installations when upgrading to a newer build of the same version ([#​21323](https://github.com/astral-sh/uv/pull/21323))
##### Enhancements
- Support Linux `s390x`, `ppc64le`, and `loongarch64` targets for cross-platform dependency resolution ([#​21313](https://github.com/astral-sh/uv/pull/21313))
- Retry downloads with configured credentials when Azure Storage denies anonymous access to an endpoint configured via `UV_AZURE_ENDPOINT_URL` ([#​21318](https://github.com/astral-sh/uv/pull/21318))
##### Preview features
- Use content-based directory hashes to deduplicate extracted wheels in the cache with the `content-addressed-cache` preview feature ([#​19693](https://github.com/astral-sh/uv/pull/19693))
##### Bug fixes
- Reject source archives with hash mismatches before persisting their extracted contents to the cache ([#​21248](https://github.com/astral-sh/uv/pull/21248))
##### Other changes
- remove pyx specific features ([#​21182](https://github.com/astral-sh/uv/pull/21182), [#​21183](https://github.com/astral-sh/uv/pull/21183), [#​21184](https://github.com/astral-sh/uv/pull/21184), [#​21185](https://github.com/astral-sh/uv/pull/21185), [#​21186](https://github.com/astral-sh/uv/pull/21186))
### [`v0.12.6`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0126)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.5...0.12.6)
Released on 2026-08-25.
##### Python
- Update CPython to use OpenSSL 3.5.8 and libffi 3.4.8 [#​21295](https://github.com/astral-sh/uv/pull/21295))
##### Enhancements
- Report cache-cleaning space savings from filesystem block allocation and avoid double-counting hard links ([#​21261](https://github.com/astral-sh/uv/pull/21261))
- Limit warnings about unbounded `uv_build` requirements to source-distribution builds ([#​21078](https://github.com/astral-sh/uv/pull/21078))
- Display byte counts below 1 KiB without a fractional part ([#​21237](https://github.com/astral-sh/uv/pull/21237))
##### Preview features
- Add `uv workspace metadata --sync --exact` to remove packages outside the selected resolution ([#​21117](https://github.com/astral-sh/uv/pull/21117))
- Add the `artifact-hash-filtering` preview feature to make `uv pip compile --generate-hashes` honor `--only-binary` and `--no-binary` ([#​21235](https://github.com/astral-sh/uv/pull/21235))
- Respect package-specific `exclude-newer` cutoffs when `uv check` selects its `ty` executable ([#​21227](https://github.com/astral-sh/uv/pull/21227))
- Preserve virtual-environment hints from `tar-codec` source-distribution errors when the base interpreter is outside a `bin` directory ([#​21146](https://github.com/astral-sh/uv/pull/21146))
##### Performance
- Enable profile-guided optimization for Linux x86-64 release binaries ([#​21001](https://github.com/astral-sh/uv/pull/21001))
- Enable profile-guided optimization for Windows x86-64 release binaries ([#​21003](https://github.com/astral-sh/uv/pull/21003))
- Enable profile-guided optimization for macOS ARM64 release binaries ([#​21002](https://github.com/astral-sh/uv/pull/21002))
- Enable profile-guided optimization for Linux ARM64 release binaries ([#​21004](https://github.com/astral-sh/uv/pull/21004))
- Speed up syncing projects with many activated conflict items by reusing their encoded representation ([#​21148](https://github.com/astral-sh/uv/pull/21148))
##### Bug fixes
- Allow explicit `uv build` and non-editable first-party workspace packages when `no-build` is enabled ([#​21294](https://github.com/astral-sh/uv/pull/21294))
- Reuse configured index credentials during `uv tool upgrade` when the tool receipt references the same index ([#​21275](https://github.com/astral-sh/uv/pull/21275))
- Ensure full 40-character Git commit pins resolve to the requested object instead of a SHA-named branch ([#​21224](https://github.com/astral-sh/uv/pull/21224))
- Prevent TLS segfaults in riscv64 musl release binaries ([#​21158](https://github.com/astral-sh/uv/pull/21158))
- Preserve dependencies selected by recursive extras when markers mix production and extra conditions ([#​21181](https://github.com/astral-sh/uv/pull/21181))
- Preserve version constraints from transitively referenced recursive extras ([#​21209](https://github.com/astral-sh/uv/pull/21209))
- Resolve repository-relative Git archive dependencies inside the checkout during the initial `uv sync` ([#​21264](https://github.com/astral-sh/uv/pull/21264))
- Return an error instead of panicking when a bearer token cannot be encoded as an HTTP header ([#​21282](https://github.com/astral-sh/uv/pull/21282))
- Do not misclassify package URLs ending in `.py` as local script paths ([#​21144](https://github.com/astral-sh/uv/pull/21144))
- Use directory creation times consistently across libc implementations for directory `cache-keys` entries ([#​21137](https://github.com/astral-sh/uv/pull/21137))
- Promote human-readable sizes to the next unit at rounding boundaries ([#​21136](https://github.com/astral-sh/uv/pull/21136))
##### Other changes
- Add Python 3.15 release-candidate Docker images ([#​21293](https://github.com/astral-sh/uv/pull/21293))
- Raise the minimum supported Rust version to 1.96 and update the repository toolchain to Rust 1.98 ([#​21258](https://github.com/astral-sh/uv/pull/21258))
### [`v0.12.5`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0125)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.4...0.12.5)
Released on 2026-08-14.
##### Python
- Add CPython 3.10.21, 3.11.16, and 3.12.14 ([#​21138](https://github.com/astral-sh/uv/pull/21138))
- Prefer newer versions and standard variants when selecting between equally prioritized Python interpreters ([#​21134](https://github.com/astral-sh/uv/pull/21134))
##### Enhancements
- Simplify errors and hints for invalid editable requirements, and redact credentials in requirement URLs ([#​21130](https://github.com/astral-sh/uv/pull/21130))
##### Preview features
- Allow `--index` and `--default-index` to select configured package indexes by name with the `index-by-name` preview feature ([#​17455](https://github.com/astral-sh/uv/pull/17455))
- Include distribution artifact URLs and hashes in CycloneDX SBOM exports by default ([#​21131](https://github.com/astral-sh/uv/pull/21131))
- Fall back to logical file sizes when using `cache-physical-space` on filesystems that do not support physical-space accounting ([#​21133](https://github.com/astral-sh/uv/pull/21133))
##### Bug fixes
- Resolve relative package index paths in PEP 723 scripts against the script directory ([#​21097](https://github.com/astral-sh/uv/pull/21097))
### [`v0.12.4`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0124)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.3...0.12.4)
Released on 2026-08-13.
##### Enhancements
- Prefer post-quantum key exchange and enable opt-in TLS diagnostics ([#​21054](https://github.com/astral-sh/uv/pull/21054))
- Accept whitespace before versions in noncompliant wildcard comparisons such as `Requires-Python: >= 3.5.*` ([#​21012](https://github.com/astral-sh/uv/pull/21012))
- Report a specific error when a PEP 723 closing tag contains trailing whitespace or other content ([#​20944](https://github.com/astral-sh/uv/pull/20944))
- Omit source-span carets from diagnostics for empty PEP 508 requirements ([#​21094](https://github.com/astral-sh/uv/pull/21094))
##### Preview features
- Add `uv check --no-install-project` and respect `UV_NO_INSTALL_PROJECT` to install dependencies without building or installing the project ([#​21085](https://github.com/astral-sh/uv/pull/21085))
- Make the ty subprocess invoked by `uv check` honor uv's color and progress settings, including quiet mode ([#​21086](https://github.com/astral-sh/uv/pull/21086))
##### Performance
- Speed up resolutions with long runs of unavailable package versions by coalescing gaps in the resolver's version ranges ([#​20804](https://github.com/astral-sh/uv/pull/20804))
- Speed up Simple API parsing by deserializing PyPI and Pyx file metadata directly ([#​21041](https://github.com/astral-sh/uv/pull/21041))
##### Bug fixes
- Use windowed `pythonw.exe` launchers for virtual environments created from managed Python minor-version links ([#​19235](https://github.com/astral-sh/uv/pull/19235))
- Allow `uv lock` to proceed when `.venv` is an unusable project environment ([#​21068](https://github.com/astral-sh/uv/pull/21068))
- Respect `fork-strategy` when ordering forks created from `environments` or existing lockfile `resolution-markers` ([#​21000](https://github.com/astral-sh/uv/pull/21000))
- Preserve consecutive wildcard Python minor-version exclusions such as `!=3.11.*, !=3.12.*` in `uv.lock` ([#​21045](https://github.com/astral-sh/uv/pull/21045))
- Preserve inline comments on the final item in dependency arrays when `uv add` updates it ([#​21008](https://github.com/astral-sh/uv/pull/21008))
- Recover from stale base-interpreter cache metadata when an existing virtual environment exposes a version mismatch ([#​21073](https://github.com/astral-sh/uv/pull/21073))
- Prevent interpreter cache reuse across different `PYTHONEXECUTABLE` and `__PYVENV_LAUNCHER__` overrides ([#​21075](https://github.com/astral-sh/uv/pull/21075))
- Show standard styling, usage guidance, and line termination for invalid `uv version --bump` values ([#​21076](https://github.com/astral-sh/uv/pull/21076))
### [`v0.12.3`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0123)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.2...0.12.3)
Released on 2026-08-07.
##### Python
- Add CPython 3.13.15 ([#​20997](https://github.com/astral-sh/uv/pull/20997))
##### Preview features
- Add `--output-format` to select automatic, human-readable, or raw-byte output for `uv cache size` ([#​20992](https://github.com/astral-sh/uv/pull/20992))
- Preserve JSON output from `uv workspace metadata --quiet` while suppressing diagnostics ([#​20991](https://github.com/astral-sh/uv/pull/20991))
- Reduce memory usage for large workspaces by streaming `uv workspace metadata` JSON output ([#​20990](https://github.com/astral-sh/uv/pull/20990))
##### Performance
- Reduce Linux startup latency by initializing the workspace cache before spawning another thread ([#​20989](https://github.com/astral-sh/uv/pull/20989))
- Reuse compiled workspace exclusion patterns during workspace discovery ([#​20988](https://github.com/astral-sh/uv/pull/20988))
- Speed up conflict-heavy resolutions by avoiding materialized range complements ([#​20982](https://github.com/astral-sh/uv/pull/20982))
- Avoid slow procfs reads during Python interpreter discovery on Linux ([#​20987](https://github.com/astral-sh/uv/pull/20987))
##### Documentation
- Add PEP 740 attestations to the GitHub Actions publishing example ([#​20986](https://github.com/astral-sh/uv/pull/20986))
- Restrict the GitHub Actions publishing example to Python version tags ([#​20973](https://github.com/astral-sh/uv/pull/20973))
- Correct `--python-pin` to `--pin-python` in the `uv init --bare` example ([#​20876](https://github.com/astral-sh/uv/pull/20876))
### [`v0.12.2`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0122)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.1...0.12.2)
Released on 2026-08-05.
##### Python
- Add CPython 3.15.0rc1 ([#​20948](https://github.com/astral-sh/uv/pull/20948))
- Add CPython 3.14.7 ([#​20971](https://github.com/astral-sh/uv/pull/20971))
##### Enhancements
- Ensure diagnostic hints end with a newline to prevent malformed terminal output ([#​20959](https://github.com/astral-sh/uv/pull/20959))
##### Preview features
- Audit one or all installed tools with `uv tool audit` ([#​20921](https://github.com/astral-sh/uv/pull/20921))
- Report physically reclaimed disk space during cache cleanup with the `cache-physical-space` preview feature ([#​20925](https://github.com/astral-sh/uv/pull/20925))
##### Configuration
- Add `UV_RUN_RLIMIT_NOFILE` to set the open-file limit for commands launched by `uv run` ([#​20926](https://github.com/astral-sh/uv/pull/20926))
##### Performance
- Speed up `uv.lock` parsing for wheel entries ([#​20881](https://github.com/astral-sh/uv/pull/20881))
- Speed up `uv.lock` parsing for source distribution entries ([#​20882](https://github.com/astral-sh/uv/pull/20882))
- Speed up filename extraction from distribution URLs ([#​20879](https://github.com/astral-sh/uv/pull/20879))
- Reduce filesystem metadata lookups during bytecode compilation ([#​20928](https://github.com/astral-sh/uv/pull/20928))
- Reuse file metadata when building source distributions ([#​20927](https://github.com/astral-sh/uv/pull/20927))
##### Bug fixes
- Preserve compatibility with older uv versions when recording artifact sizes in cached wheels and source distributions ([#​20963](https://github.com/astral-sh/uv/pull/20963))
- Avoid including workspace-root default dependency groups when syncing or exporting a selected workspace member unless explicitly requested ([#​20930](https://github.com/astral-sh/uv/pull/20930))
##### Documentation
- Separate build and publish jobs in the GitHub Actions publishing guide ([#​20946](https://github.com/astral-sh/uv/pull/20946))
- Ensure the GitHub Actions publishing example waits for the build job to finish ([#​20957](https://github.com/astral-sh/uv/pull/20957))
- Correct typos in the Docker integration guide ([#​20970](https://github.com/astral-sh/uv/pull/20970))
### [`v0.12.1`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#01215)
[Compare Source](https://github.com/astral-sh/uv/compare/0.12.0...0.12.1)
Released on 2026-09-15.
This release fixes a regression in 0.12.14 that lead to rejecting valid installation commands such as using
`uv pip install --system` in `python:*` docker images or when using `uv pip install --target .`. ([#​21699](https://github.com/astral-sh/uv/pull/21699))
##### Performance
- Speed up cold-cache resolution and HTTP cache revalidation by batching cache writes ([#​21675](https://github.com/astral-sh/uv/pull/21675))
##### Bug fixes
- Revert "Reject symlinked wheel installation destinations" ([#​21699](https://github.com/astral-sh/uv/pull/21699))
### [`v0.12.0`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0120)
[Compare Source](https://github.com/astral-sh/uv/compare/0.11.33...0.12.0)
Released on 2026-07-28.
Since we released uv [0.11.0](https://github.com/astral-sh/uv/releases/tag/0.11.0) in March, we've accumulated changes that improve correctness, safety, and compatibility with specifications, but could break some workflows. This release contains those changes; many have been marked as breaking out of an abundance of caution.
**We expect most users to be able to upgrade without making changes.**
There are no breaking changes to the configuration of the [uv build backend](https://docs.astral.sh/uv/concepts/build-backend/). If your `[build-system]` table includes an upper bound on `uv_build`, update it to allow `uv_build` 0.12, e.g., `uv_build>=0.11.32,<0.13`.
##### Breaking changes
- **Define build systems by default with `uv init`** ([#​19197](https://github.com/astral-sh/uv/pull/19197))
Projects created with `uv init` now declare a build system and are packaged by default. This was the default project layout all the way back in [v0.3](https://github.com/astral-sh/uv/releases/tag/0.3.0), but we found that the use of the `hatchling` build system was confusing to newcomers and consequently dropped use of a build system by default in [v0.4](https://github.com/astral-sh/uv/releases/tag/0.4.0). Since then, we've created our own build system (`uv_build`) with tight integration with uv and are excited to restore the default to a best-practice project layout.
Previously, `uv init example` created an unpackaged layout containing `main.py` and a `pyproject.toml` without a build system. The project could declare dependencies but was not itself installed into its virtual environment.
Now, `uv init example` defines a `[build-system]` using `uv_build`, places application source code in `src/example`, and includes a `[project.scripts]` entry named `example`. Defining a build system allows the project to be imported from tests or other code, installed as a dependency, and run as a command:
```console
$ uv init example
$ cd example
$ uv run example
Hello from example!
```
Existing projects are unaffected. Use [`uv init --no-package example`](https://docs.astral.sh/uv/concepts/projects/init/#creating-a-project-without-a-build-system) to create the previous unpackaged layout without a build system.
See the [project creation documentation](https://docs.astral.sh/uv/concepts/projects/init/#applications) for more details.
This stabilizes the `packaged-init` preview feature.
- **Reject unsupported source distribution and wheel archive formats** ([#​18927](https://github.com/astral-sh/uv/pull/18927))
[PEP 625](https://peps.python.org/pep-0625/) requires [source distributions](https://docs.astral.sh/uv/concepts/resolution/#source-distribution) to use `.tar.gz` archives. Previously, uv also accepted legacy formats such as `.tar.bz2` and `.tar.xz`. Those formats are now rejected, including when referenced by an existing lockfile. Legacy `.zip` source distributions remain supported for backwards compatibility.
Wheels and other ZIP archives can no longer contain entries compressed with bzip2, LZMA, or XZ. Entries must use the stored, DEFLATE, or zstd compression methods.
Removing support for uncommon compression methods reduces uv's compression dependencies and the attack surface exposed when processing untrusted packages.
You cannot opt out of this behavior. If you depend on a legacy source distribution that uses an unsupported format, we recommend rebuilding it as a `.tar.gz` archive and regenerating any lockfile containing references to the legacy archive.
- **Reject wheel files that could replace the Python interpreter** ([#​20748](https://github.com/astral-sh/uv/pull/20748), [#​20749](https://github.com/astral-sh/uv/pull/20749))
uv already rejected wheel entry points named `python`, but case variants such as `Python` were still accepted. On case-insensitive filesystems, including common macOS and Windows setups, these entry points could overwrite the virtual environment's interpreter.
Wheels could also place interpreter files in their `.data/scripts` directory or in paths such as `.data/data/bin/python`, bypassing the entry-point check and replacing the interpreter during installation.
uv now rejects case-insensitive variants of reserved interpreter names and wheel data files that would be installed over an interpreter. This includes names such as `Python`, `python.py`, and `Python.exe`, along with other reserved interpreter names and their versioned variants.
You cannot opt out of these checks. Rename conflicting entry points or wheel data files and rebuild the affected wheel.
- **Prefer stable releases before falling back to pre-releases** ([#​19993](https://github.com/astral-sh/uv/pull/19993))
A dependency can introduce a [pre-release requirement](https://docs.astral.sh/uv/concepts/resolution/#pre-release-handling) after resolution starts. uv previously required each package's pre-release eligibility to be known before resolution began: the default `if-necessary-or-explicit` mode allowed them for direct requirements that explicitly requested a pre-release, or for packages that only published pre-releases.
This meant that a pre-release requirement discovered in a dependency's metadata, e.g., `example>=2.0.0b1`, would fail to resolve even when a compatible pre-release existed. To resolve it, you had to add that dependency as a direct requirement or allow pre-releases across your entire dependency graph.
The default mode is now `if-necessary`. uv tries stable candidates first and falls back to pre-releases when no stable candidate satisfies the active constraints. Like pip, uv now supports [pre-release requirements discovered transitively](https://docs.astral.sh/uv/pip/compatibility/#pre-release-compatibility), but can select different versions than previous uv releases when both stable and pre-release candidates are available.
You can opt out of automatic pre-release selection with `--prerelease disallow`. Alternatively, `--prerelease allow` considers pre-releases without first preferring stable releases, and `--prerelease explicit` only allows them for direct requirements that mention a pre-release.
The old `if-necessary-or-explicit` mode distinguished between explicitly requested pre-releases and packages with no stable releases. That distinction is unnecessary now that `if-necessary` handles both cases, including transitive requirements. The old name remains available as an alias but is deprecated and will be removed in a future release.
- **Respect `--require-hashes` directives in `requirements.txt`** ([#​19336](https://github.com/astral-sh/uv/pull/19336))
Previously, `uv pip install` and `uv pip sync` warned about `--require-hashes` inside a `requirements.txt` file but still installed dependencies without checking their hashes. Now, the directive enables hash-checking mode, just as if `--require-hashes` had been passed on the command line.
For example, this requirements file is no longer accepted because the requirement is neither pinned nor hashed:
```text
--require-hashes
anyio
```
You cannot opt out while the directive is present. Pin every requirement with `==` and provide its hash, or remove `--require-hashes` if hash checking is not intended.
- **Reject MD5-only hashes in hash-checking mode** ([#​20758](https://github.com/astral-sh/uv/pull/20758))
Previously, `uv pip install --require-hashes` and `uv pip sync --require-hashes` accepted requirements whose only available digest used MD5. MD5 is not collision-resistant, so relying on it undermined installations that require hash verification and differed from pip's behavior.
Hash-checking mode now requires at least one secure digest for every requirement. For example, the following requirement is rejected unless a secure hash, such as SHA-256, is also supplied:
```text
anyio==4.0.0 --hash=md5:420d85e19168705cdf0223621b18831a
```
A secure hash can be supplied directly on the requirement or in a matching constraints file. Ordinary hash verification without `--require-hashes` continues to support MD5.
You cannot opt out while hash checking is required. Regenerate affected hashes with SHA-256 or another supported secure hash.
- **Reject invalid `pylock.toml` files and artifacts** ([#​20402](https://github.com/astral-sh/uv/pull/20402), [#​20440](https://github.com/astral-sh/uv/pull/20440), [#​20443](https://github.com/astral-sh/uv/pull/20443))
uv now validates additional requirements from the [`pylock.toml` specification](https://packaging.python.org/en/latest/specifications/pylock-toml/):
- The `packages` array must be present. Previously, uv interpreted a missing array as an empty lockfile, so `uv pip sync` could uninstall an environment instead of rejecting malformed input. An explicitly empty `packages = []` array remains valid.
- Lockfile filenames must be `pylock.toml` or a single-name variant such as `pylock.dev.toml`. Names such as `pylock..toml` and `pylock.foo.bar.toml` are rejected.
- If a wheel, source distribution, or other artifact declares a `size`, the downloaded or cached artifact must match. Previously, an incorrect size was accepted when the hash was correct. Sizes reported by package indexes remain advisory.
You cannot opt out of these checks. Regenerate malformed lockfiles, rename invalid filenames, and either correct or remove an incorrect optional `size` value.
- **Honor explicit certificate overrides even when no certificates can be loaded** ([#​20741](https://github.com/astral-sh/uv/pull/20741), [#​20767](https://github.com/astral-sh/uv/pull/20767))
Previously, uv ignored [`SSL_CERT_FILE` or `SSL_CERT_DIR`](https://docs.astral.sh/uv/concepts/authentication/certificates/#custom-certificates) values that pointed to missing or inaccessible paths, empty files or directories, or sources without valid certificates. Instead, it fell back to its default trust roots, potentially allowing HTTPS connections that the configured override was intended to reject.
Now, any non-empty `SSL_CERT_FILE` or `SSL_CERT_DIR` value replaces uv's default certificate roots, even when no valid certificates can be loaded. In that case, HTTPS requests fail because no certificates are trusted. This applies to package downloads and remote scripts, including GitHub Gists.
Fix or unset the certificate override. Unsetting it restores the default trust store; empty environment-variable values continue to be ignored.
- **Support pip-compatible `--cert` handling in `uv pip`** ([#​20418](https://github.com/astral-sh/uv/pull/20418))
The `uv pip` interface now accepts [`--cert <path>`](https://docs.astral.sh/uv/concepts/authentication/certificates/#custom-certificates), e.g.:
```console
$ uv pip install --cert ./company-ca.pem example
```
As in pip, the provided PEM bundle replaces all other certificate sources for that invocation, including system certificates and `SSL_CERT_FILE` or `SSL_CERT_DIR`. This change has no effect unless you pass `--cert`. Include the necessary certificate authorities in the bundle.
`--cert` is only supported by `uv pip` commands; other uv commands continue to use their existing certificate configuration.
- **Discover projects relative to the script passed to `uv run`** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
Previously, `uv run project/script.py` discovered its project from the current directory, even when the script belonged to another project. uv now starts project and workspace discovery from the script's directory instead.
For example, running `uv run other-project/script.py` now uses `other-project` and its dependencies. This fixes scripts that previously failed because their own dependencies were not installed, but can select a different environment than before.
You can opt out of script-relative discovery by selecting a project explicitly, e.g., `uv run --project . other-project/script.py`.
This stabilizes the `target-workspace-discovery` preview feature.
- **Require `--force` before clearing a directory that is not a virtual environment** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
`uv venv --clear` previously removed any existing target directory, even if it was not a virtual environment. uv emitted a warning but still deleted the directory and its contents. Now, uv refuses to clear directories that do not contain a virtual environment.
You can opt out of this safety check by explicitly passing `--force`, e.g., `uv venv --clear --force ./not-a-virtualenv`.
This stabilizes the `venv-safe-clear` preview feature.
- **Reject `--project` when initializing a project** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
`--project` selects an existing project, so it is not meaningful when initializing a new one. Previously, `uv init --project example` warned and initialized `example` anyway; if a positional path was also provided, `--project` was ignored.
This usage is now an error. Use `uv init example` to initialize a project at the requested path, or `uv init --directory example` to change the working directory first.
This stabilizes the `init-project-flag` preview feature.
- **Reject missing or invalid `--project` paths** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
uv previously warned when `--project` referred to a missing directory or a file other than `pyproject.toml`, but then attempted to continue. This could produce confusing errors later or run against an unintended project.
Now, `uv run --project missing python` fails immediately instead of continuing. You cannot opt out of this behavior. Create the directory first or select an existing project. Passing `--project path/to/pyproject.toml` remains supported and selects the file's parent directory.
This stabilizes the `project-directory-must-exist` preview feature.
- **Skip distributions with non-normalized filenames when publishing** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
Distribution filenames must use [normalized package names](https://packaging.python.org/en/latest/specifications/name-normalization/) and versions. For example, a wheel for version `1.01.0` should be named `example-1.1.0-py3-none-any.whl`, not `example-1.01.0-py3-none-any.whl`.
Previously, `uv publish` warned about non-normalized filenames but still attempted to upload them. It now skips the affected wheels and source distributions instead.
You cannot opt out of this behavior. Rebuild distributions with normalized filenames before publishing.
This stabilizes the `publish-require-normalized` preview feature.
- **Classify Conda environments named `base` and `root` by their paths** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
Conda environments named `base` or `root` were previously assumed to be the base Conda environment, even when they were ordinary child environments. uv now recognizes child Conda environments named `base` or `root` based on their paths, as it already does for other names.
You can opt out of automatic interpreter selection by requesting an interpreter explicitly with `--python /path/to/python`.
This stabilizes the `special-conda-env-names` preview feature.
- **Reject broken `.venv` symlinks during environment discovery** ([#​20433](https://github.com/astral-sh/uv/pull/20433))
Previously, uv could ignore a broken `.venv` symlink and continue searching parent directories for another virtual environment. As a result, commands such as `uv pip install` could unexpectedly modify an unrelated ancestor environment.
uv now stops at a broken `.venv` symlink and reports its exact path. Errors encountered while reading virtual environment metadata, including permission failures, are also reported immediately instead of being ignored.
You cannot opt out of this behavior. Repair or remove the broken `.venv` symlink and correct any permissions that prevent uv from inspecting the environment.
- **Reinstall matching installed Python patch versions instead of upgrading implicitly** ([#​20659](https://github.com/astral-sh/uv/pull/20659))
Before [Python upgrades](https://docs.astral.sh/uv/guides/install-python/#upgrading-python-versions) were supported, `uv python install 3.12 --reinstall` doubled as a way to install the latest Python 3.12 patch release. Now that `--upgrade` is available, `--reinstall` reinstalls the matching patch releases that are already present.
For example, if Python 3.12.6 and 3.12.7 are installed, `uv python install 3.12 --reinstall` reinstalls both versions instead of installing the latest available 3.12 release.
You can recover the previous upgrade behavior with `uv python install 3.12 --upgrade`. Combine `--upgrade --reinstall` to reinstall only the latest patch.
- **Require `--upgrade-group` to name an existing dependency group** ([#​18957](https://github.com/astral-sh/uv/pull/18957))
Previously, `uv lock --upgrade-group docs` silently succeeded even if no `docs` [dependency group](https://docs.astral.sh/uv/concepts/projects/dependencies/#dependency-groups) existed. uv now validates the requested group against the project, its workspace members, and workspace-level dependency groups.
You cannot opt out of this behavior. Correct the group name or add it to `[dependency-groups]`. Legacy `tool.uv.dev-dependencies` still satisfies `--upgrade-group dev`.
- **Resolve relative indexes and find-links against `--directory`** ([#​20740](https://github.com/astral-sh/uv/pull/20740))
The `--directory` option changes the directory in which uv operates. Previously, relative index and find-links paths supplied on the command line were still resolved against the original working directory.
uv now resolves `--index`, `--default-index`, `--index-url`, `--extra-index-url`, and `--find-links` relative to the directory selected by `--directory`. For example:
```console
$ uv add --directory project --index ./packages example
```
This now uses `project/packages` instead of `./packages` in the original working directory. Absolute paths and indexes loaded from configuration files are unaffected.
To preserve the previous target, pass an absolute path or adjust the relative path, e.g., `--index ../packages`.
- **Preserve absolute paths provided to `uv add`** ([#​18402](https://github.com/astral-sh/uv/pull/18402))
`uv add` previously converted every local dependency into a project-relative path, even when the original request used an absolute path or a literal `file://` URL. It now preserves the form of the request in `pyproject.toml` and `uv.lock`:
```console
$ uv add ../library # remains relative
$ uv add /projects/library # remains absolute
```
Absolute paths make a project less portable. Use a relative path to avoid recording an absolute path. URLs containing expanded variables retain their existing relative-path behavior.
- **Remove older PyPy distributions that are only available as bzip2 archives** ([#​20423](https://github.com/astral-sh/uv/pull/20423))
Older PyPy patch releases that are only distributed as `.tar.bz2` archives are no longer available through `uv python install`. These releases require unsupported bzip2 archives.
The latest PyPy release for each supported Python minor version is available as a gzip-compressed archive and remains supported. For example, `uv python list 3.10 --all-versions` still includes the latest PyPy 3.10 release, but older bzip2-only patch releases are omitted.
You cannot opt out of this behavior. Request a newer PyPy patch release instead.
- **Omit excluded-package comments when annotations are disabled** ([#​20085](https://github.com/astral-sh/uv/pull/20085))
`uv pip compile --no-annotate` suppresses comments describing the generated requirements file. Previously, a footer listing packages excluded with `--unsafe-package` was still included, even though annotations were disabled. That footer is now omitted.
You can recover the footer by removing `--no-annotate`.
##### Stabilizations
- **TOML 1.0-compatible source distributions** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
`uv_build` now writes a TOML 1.0-compatible `pyproject.toml` when building source distributions, allowing older Python build frontends to consume projects that use newer TOML syntax. The original project file remains available in the archive as `pyproject.toml.orig`.
This stabilizes the `toml-backwards-compatibility` preview feature.
- **Automatic open-file limit adjustment on Unix** ([#​20225](https://github.com/astral-sh/uv/pull/20225))
On Linux and macOS, uv now attempts to raise the soft open-file limit at startup toward the hard limit, capped at 1,048,576 descriptors. The new limit also applies to subprocesses and reduces failures caused by running out of file descriptors. If the limit cannot be raised, uv continues running with the existing limit.
This stabilizes the `adjust-ulimit` preview feature.
##### Preview features
- Allow `uv upgrade` to target multiple packages, upgrade all production dependencies, and exclude selected dependencies ([#​20338](https://github.com/astral-sh/uv/pull/20338))
##### Bug fixes
- Include extras activated by dependency groups when evaluating conflicts ([#​20237](https://github.com/astral-sh/uv/pull/20237))
</details>
---
### Configuration
📅 **Schedule**: (in timezone Europe/Warsaw)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC43NC4wIiwidXBkYXRlZEluVmVyIjoiNDQuNzQuMCIsInRhcmdldEJyYW5jaCI6ImRldiIsImxhYmVscyI6WyJkZXBzLWNvZGUiLCJyZW5vdmF0ZSJdfQ==-->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
This PR contains the following updates:
2.4.15→2.5.137.8.0→7.11.1>=0.11.14,<0.12.0→>=0.12.13,<0.13.0Release Notes
biomejs/biome (@biomejs/biome)
v2.5.13Compare Source
Patch Changes
#11379
07a0073Thanks @Netail! - Added the nursery ruleuseLayeredStyles, which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.#11667
e997900Thanks @devtechedge! - Added the nursery ruleuseBetterDomTraversing, which prefers.firstChild,.firstElementChild,.closest(), and merged.querySelector()calls over positional DOM traversal.#11620
20e513aThanks @jakeleventhal! - Fixed #11610, #11611, #11612, #11615, and #11616: Biome no longer fully infers an imported generic declaration just to apply its type arguments, restoring type-aware lint performance for large libraries such as Zod. This improvesuseRegexpExec,noFloatingPromises,noMisusedPromises,useNullishCoalescing, andnoUnsafePlusOperands.#11657
e322040Thanks @ematipico! - Fixed #7495:noUselessConstructornow ignores TypeScript constructors that forward at least one argument tosuper, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.#11670
4969ee1Thanks @ematipico! - Fixed #7076:useAriaPropsForRoleanduseFocusableInteractiveno longer report non-focusable elements withrole="separator". A separator with an explicittabIndexortabindexstill requiresaria-valuenow.#11627
23aad6dThanks @ematipico! - Fixed #6571 so Grit plugins can capture and inspect multiple named import specifiers.#11631
00dbd3aThanks @ematipico! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.#11628
a2f8ff7Thanks @dyc3! - Added the nursery rulenoXorAsExponentiation, which reports the bitwise XOR operator^between two decimal integer literals, where the exponentiation operator**was likely intended.#11670
4969ee1Thanks @ematipico! - Fixed #7192:noUnusedPrivateClassMembersnow considers compound assignments such as??=to read and use private class members.#11676
840a52aThanks @dyc3! - Fixed #11672 and #11671 by disabling the experimental capitalized-call and effect-dependency checks inuseReactCompiler, matching their exclusion from upstream's recommended lint preset. Valid calls such asIntl.NumberFormat()and captures of variables declared inside effects no longer produce these diagnostics.#11660
49485edThanks @ematipico! - Fixed #11653: Astro template suppression comments ({/* biome-ignore lint: reason */}) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.#11664
9a73b9cThanks @dyc3! - Improved the performance ofuseRegexpExec.#11661
5341b3fThanks @ematipico! - Fixed #7479.noUnusedVariablesnow treats Unicode escapes in identifiers as the same binding as their decoded spelling.#11630
62e1fc5Thanks @dyc3! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.#11658
ed4bfa4Thanks @fredrikblau! - Fixed #11644:useHeadingContentno longer reports headings that render their text with a directive:set:htmlandset:textin Astro files,v-htmlandv-textin Vue files.#11613
47d7383Thanks @ematipico! - Improved the performance of Biome Formatter up to ~50% in some cases.#11655
fd8fc74Thanks @ematipico! - Fixed #6974, wherenoUnusedPrivateClassMembersincorrectly reported TypeScript private constructor properties read through object destructuring fromthisas unused.#11618
21a10cfThanks @siketyan! - Fixed #11605: Type inference now infers the type of an unannotated callback parameter from the signature of the function the callback is passed to, and honours explicit type arguments on call expressions. This improves type-aware analysis fornoBaseToString,noFloatingPromises,noMisleadingReturnType,noMisusedPromises,noUnnecessaryConditions,noUnsafePlusOperands,noUselessTypeConversion,useArrayFind,useArraySortCompare,useAwaitThenable,useDisposables,useExhaustiveSwitchCases,useIncludes,useNullishCoalescing,useRegexpExec, anduseStringStartsEndsWith. For example,noFloatingPromisescan now detect Promises reached through such parameters:#11698
b019982Thanks @denbezrukov! - Fixed parsing of unquoted CSS URLs beginning with@or!, such asurl(@/assets/icon.svg)andurl(!font.woff2). Preserved escaped and non-ASCII whitespace in raw URLs during formatting.#11622
c23e4c7Thanks @Netail! - Added the nursery rulenoUnsafeIframeSandbox, which reportsiframeelements whosesandboxattribute combinesallow-scriptsandallow-same-origin, since that combination lets the embedded document remove its own sandboxing.#11606
de0528fThanks @dyc3! - Added the recommendednoSvelteAtHtmlTagsnursery rule, which reports Svelte{@html}tags that render unescaped HTML.#11670
4969ee1Thanks @ematipico! - Fixed #6782: GritQL plugins now match captured JSX component names against code snippets such asReact.Fragment.#11687
09d97d9Thanks @hori-design! - Fixed #11678:useReactCompilerno longer panics on files that contain non-ASCII characters. This bumps the React Compiler version.#11595
a64d757Thanks @dyc3! - Added the nursery Vue-domain ruleuseVueBaseImportrule, which enforces importing Vue APIs fromvueinstead of internal@vue/*packages.#11675
353cbaeThanks @dyc3! - FixeduseReactCompilersilently producing no diagnostics in WebAssembly builds, including the playground.#11625
ea20e5aThanks @denbezrukov! - Improved linting performance for large CSS and JSON files.#11670
4969ee1Thanks @ematipico! - Fixed #7527: suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressingnoTsIgnorenow places thebiome-ignorecomment before@ts-ignore.#11655
fd8fc74Thanks @ematipico! - Fixed #8629, wherenoUnusedPrivateClassMembersincorrectly reported used private TypeScript method overload signatures as unused.#11669
579f401Thanks @denbezrukov! - Improved the performance ofnoExcessiveLinesPerFilewhenskipBlankLinesisfalse.v2.5.12Compare Source
Patch Changes
#11440
b88f1eaThanks @Princesseuh! - Fixed Astro attribute expressions rejecting TypeScript and JSX syntax that is accepted in text expressions.#11440
b88f1eaThanks @Princesseuh! - Fixed Astro attribute names being split on:and.inside an expression, such as{x && <button x-on:keyup.enter={go} client:load.foo />}.#11440
b88f1eaThanks @Princesseuh! - Fixed a bare>in the children of an Astro expression being treated as markup, such as{x && <div>a > b</div>}.#11440
b88f1eaThanks @Princesseuh! - Fixed HTML comments inside an Astro expression failing to parse. They are now read as trivia, wherever they appear among the children.#11440
b88f1eaThanks @Princesseuh! - Fixedis:rawchildren inside an Astro expression being read as JSX, such as{x && <div is:raw>{not js} < & text</div>}.#11440
b88f1eaThanks @Princesseuh! - Fixed an apostrophe or quote in the text of a JSX element inside an Astro expression ending the expression early, such as{items.map((i) => <li>it's {i}</li>)}.#11440
b88f1eaThanks @Princesseuh! - Fixed the children of a<script>or<style>inside an Astro expression being read as JSX. Their contents are text, so braces and comparisons no longer have to be escaped.#11440
b88f1eaThanks @Princesseuh! - Added support for template literal attribute values inside an Astro expression, such as{x && <C data-x=`t${x}` />}.#11440
b88f1eaThanks @Princesseuh! - Fixed unquoted attribute values being rejected inside an Astro expression, such as{x && <a class=foo maxlength=255 href=/about>go</a>}.#11440
b88f1eaThanks @Princesseuh! - Fixed a template literal nested inside${}breaking the rest of an Astro file, such asconst href = `/blog${page === 0 ? '' : `/${page + 1}`}`;.#11440
b88f1eaThanks @Princesseuh! - Fixed a quote inside a regex character class breaking the rest of an Astro file, such asconst unsafe = /[/"]/;.#11508
54f3a2eThanks @dyc3! - Added the nursery ruleuseFlatMathMinMax. BecauseMath.min()andMath.max()accept any number of arguments, the rule reports unnecessary nested calls to the same method:The fix flattens this expression to
Math.max(a, b, c).#11585
c5c8315Thanks @Netail! - Fixed #11475:noUnresolvedImportsno longer reports Bun runtime built-in modules (bun,bun:bundle,bun:ffi,bun:jsc,bun:sqlite,bun:test).#11368
52a57b3Thanks @Austin1serb! - Fixed #6830: Biome now reports a diagnostic for excessively deep syntax instead of overflowing the native stack while releasing the parsed tree.#11596
1fc42edThanks @dyc3! - Added the nursery rulenoThisOutsideOfClass. The rule reportsthisoutside class members and TypeScript functions with an explicitthisparameter.#11555
2516335Thanks @dyc3! - Fixed #11529, wherenoFloatingPromisesmissed unhandled Promise chains when the imported function's module belonged to an import cycle. Cyclic modules now preserve types for exports that do not participate in recursive type dependencies.#11518
0fee70cThanks @HarperZ9! - Fixed #11500: the formatter now prints thedeclaremodifier before accessibility modifiers on class properties.private declare readonly name: stringis now formatted asdeclare private readonly name: string, matching Prettier and TypeScript's canonical modifier order.#11580
1277af2Thanks @ematipico! - Fixed #5091: Biome no longer moves comments next to the<of a generic, which causes invalid TypeScript syntax:#11577
42995d2Thanks @ematipico! - Fixed #4592. Biome no longer crashes while parsing malformeddeleteexpressions.#11590
67963b4Thanks @ematipico! - Fixed #6427 so Grit plugins can usefunction = ...as a node argument.#11600
a689cb5Thanks @ematipico! - Fixed #6644:noUnusedVariablesnow recognizes all interface declarations in a TypeScript declaration-merging group when the interface is referenced.The following snippet no longer triggers the rule.
#11591
d4a0716Thanks @ematipico! - Fixed #6615.noDuplicatePropertiesno longer reports declarations nested in block at-rules as duplicates of declarations in their parent block.#11492
f2a07aaThanks @santichausis! - Fixed #11454:noMisplacedAssertionnow recognises@fast-check/vitest'stest.prop(...)(and.concurrent.prop,.skip.prop, etc.) as a test function, the same way it already recognisestest.each. The JS formatter picks up the same recognition, so a curriedtest.prop(...)(...)call is now formatted with the regular breakable argument layout used fortest.each/test.for, instead of the single-line-hugging layout used for plainit/testcalls.For example, Biome no longer reports the assertion below as misplaced:
#11589
65742b3Thanks @ematipico! - Fixed #4928:noUnusedVariablesno longer reports a value declaration as unused when its merged namespace is referenced.#11559
472dbc2Thanks @levrik! - Fixed a false positive innoVueDuplicateKeyswhere a<script setup>variable initialized frompropswas reported as a duplicate of the prop it derives from. Biome now exempts any variable whose initializer referencesprops, instead of only recognizingdefineProps()andtoRefs(props).For example, Biome no longer reports
foobelow as a duplicate key:#11594
6586cebThanks @ematipico! - Fixed #6640. Biome no longer crashes when linting malformedfor...ofstatements.#11571
85b197dThanks @ematipico! - Fixed #10838:useSortedAttributesno longer corrupts JSX attributes when nested JSX elements also require sorting.#11533
97e76c0Thanks @ematipico! - Fixed #11520, where the Biome scanner would start analysing dependencies multiple times, leading to long and unresponsive sessions.#11564
18a0e1fThanks @Netail! - Fixed the diagnostic range ofnoInferrableTypesso it now highlights only the type instead of including the leading:colon, spaces and comments.#11540
124fdaaThanks @ematipico! - Fixed#11537:noShorthandPropertyOverridesnow compares declarations only within the same block. The rule no longer reports@supportsfeature queries and correctly checks nested,@keyframes, and@pageblocks.#11532
7ceb0eeThanks @dyc3! - Fixed #11528:noFloatingPromisesno longer reports statement-levelawaitexpressions that handle Promise values, including overloaded calls returning Promise aliases. Awaited values that resolve to arrays of Promises remain reported because their element Promises are not handled byawait.#11474
3c6412eThanks @dyc3! - Fixed #10241. Biome no longer reports unsupported text expression diagnostics for double-curly text in vanilla HTML, and the formatter preserves adjacent curly-brace text.#11593
6c7fd27Thanks @dyc3! - Added the nursery rulenoVueDeprecatedScopedSlots. It reports deprecated$scopedSlotsreferences in Vue templates and component objects, and offers an unsafe replacement with$slots. For example, Biome now reportsthis.$scopedSlots.defaultinside a Vue component.#11440
b88f1eaThanks @Princesseuh! - Fixed the formatter crashing on an Astro or Svelte expression spanning several lines in a file with CRLF line endings, such as<p>{a +\r\n b}</p>.#11581
f4e5ebbThanks @dyc3! - Added the nursery ruleuseModernMathApis. The rule reports legacy mathematical patterns that have direct modernMathequivalents.#11597
a20f44aThanks @Netail! - Added the nursery rulenoBunModules, which forbids the use of Bun builtin modules (e.g.bun:sqlite,bun:ffi).#11545
7d54688Thanks @dyc3! - Fixed #11542: Biome now reports HTML comments between Svelte tag attributes as parse errors.#11582
b6611ddThanks @ematipico! - Fixed #3862. Biome now parses legacy Internet Explorerfilterand-ms-filtervalues such asprogid:DXImageTransform...andalpha(opacity=40).#11575
65da251Thanks @dyc3! - Improved the Tailwind parser's ability to recover from parsing failures. Whitespace now always allows the parser to recover and start parsing a new class.#11576
0f78499Thanks @ematipico! - Fixed #3515 and #10395, where Biome could corrupt Unicode characters while writing source received through standard input to standard output. Characters such as⚠and✔are now preserved.#11539
0fca643Thanks @ematipico! - Fixed #11512, wherestyle/noDescendingSpecificitymissed lower-specificity selectors after a later higher-specificity selector with the same tail selector.#11544
040f867Thanks @dyc3! - Fixed #11541: formatting a Svelte render tag followed by an HTML comment no longer duplicates the comment.#11565
ee69e0eThanks @ematipico! - Fixed #11525. Now the configuration schema correctly provides auto-completion for linter domains.#11583
b19390cThanks @dyc3! - Fixed #11352:useExplicitLengthCheckno longer reportslength-like properties used as value-producing||fallbacks or optional chains, and it no longer offers fixes for value-producing&&checks or unsafe negations.#11562
753e955Thanks @ematipico! - Fixed an issue where the Biome Language Server would start with logging level set to debug. This would cause logs to grow exponentially in long sessions.#11217
7d3ee9cThanks @dyc3! - Fixed handling ofbiome-ignore formatsuppression comments on TypeScript declared class properties with string literal names.#11497
f5d7896Thanks @dyc3! - Added thenoInvalidFileInputAcceptnursery rule. The rule reports invalid literalacceptvalues on file inputs in JSX and HTML, and normalizes common mistakes.#11345
ac58958Thanks @jakeleventhal! - Improved type inference performance by avoiding resolution of unused members in object arguments.#11554
2d55931Thanks @Netail! - Added the new nursery ruleuseReactNamingConvention, which enforces naming conventions for React values assigned fromcreateContext,useId, anduseRef. A value fromcreateContextmust be a PascalCase component name ending withContext, a value fromuseIdmust be namedidor end withId, and a value fromuseRefmust be namedrefor end withRef.#11491
1d6210bThanks @dyc3! - Added the nursery rulenoUnmodifiedLoopCondition, which reports variables in loop conditions that are never modified in the loop.v2.5.11Compare Source
Patch Changes
#11499
9743d0cThanks @scs0209! - Fixed #11496:useValidAnchornow treats Astro JSX shorthand attributes like<a {href}>as a validhref.#11437
88f805eThanks @Princesseuh! - Fixed #9944: adjacent elements inside an Astro expression now parse as an implicit fragment instead of raising an error.#11437
88f805eThanks @Princesseuh! - Fixed Astro templates rejecting unclosed HTML void elements, such as{cond && <br>}.#11507
e2fc036Thanks @dyc3! - Fixed #11157:noUnusedVariablesno longer reports Vue<script setup>bindings used by CSSv-bind()as unused.#11398
afc4615Thanks @dyc3! - Fixed #11389: Files passed through--stdin-file-pathnow use full HTML support for Astro, Svelte, and Vue when it is enabled.#11526
372cd68Thanks @dyc3! - FixednoVueRefAsOperandto track Vue refs through declaration aliases andtoRefs()properties, and to recognizeuseTemplateRef()results. The rule no longer reports false positives such as plain ref transfers, plaintoRefs()property access,defineModel()modifiers, or the supported.effectmember as operands.The refactor enabling these fixes also improves the performance of the rule.
#11458
a7cd286Thanks @dyc3! - Fixed #11436: GritQL snippets such asexport { $specifiers } from $sourcenow match named re-exports with aliases, inlinetypemodifiers, and multiple specifiers.#11515
382b15dThanks @dyc3! - Fixed #11390, wherenoFloatingPromisesperformed expensive full type inference for calls to non-Promise methods declared on third-party TypeScript classes. The rule now classifies those calls using targeted type information.#11516
6f40e82Thanks @levrik! - FixednoVueRefAsOperandso it no longer reports a callback parameter (e.g. from.find(),.map()) as an unwrapped ref value just because it's nested inside aref(),computed(), or similar call.Previously,
itemhere was incorrectly treated as a ref value because the rule attributed it to the outercomputed()call.#11495
496268dThanks @Netail! - FixeduseGraphqlNamingConventionso it no longer reports GraphQL enum value definitions with comments & descriptions and now displays a more accurate diagnostic range.#11407
6ef52b0Thanks @1678092075! - Fixed #11214:noUnusedVariablesno longer reports type parameters declared by non-default function overload signatures that have an implementation.#11322
5c353e6Thanks @jp-knj! - Added a new nursery rulenoAstroSetHtmlDirective, which disallows Astro'sset:htmldirective because untrusted content can introduce cross-site scripting vulnerabilities.For example, the following snippet triggers the rule:
#11462
18883b7Thanks @dyc3! - Fixed #10776:useVueHyphenatedAttributesno longer reports lowercase attribute names containing punctuation, such aspt:header:data-test-idandsome_attr.#11476
3270ca4Thanks @dyc3! - Fixed #10330: Vue interpolation delimiters now stay attached to whitespace-sensitive element boundaries and adjacent inline siblings, wrapping their expression when needed to fit the configured line width. Interpolations followed by text now also converge after one formatting pass.#11191
3e5367fThanks @ematipico! - Added the nursery rulenoUndeclaredCustomProperties, which reports references to custom properties that are not defined in available CSS, static HTML-likestyleattributes, or JSX stringstyleattributes.For example, the following snippet triggers the rule:
#11435
7754894Thanks @levrik! - Fixed: Variables and imports used as custom Vue directives are no longer reported as unused.For example:
#11501
e6acdedThanks @aminya! - Improved the performance ofuseArraySortCompareby skipping type inference for calls to unrelated methods.#11467
66b282cThanks @dyc3! - Fixed #11464: Biome now parses parenthesized object literals returned from arrow functions when they contain a conditional expression and a nested arrow function.#11456
db9aa2aThanks @dyc3! - Fixed #10278: Marked the fix fornoThisInStaticas unsafe by default.#11502
652aedbThanks @levrik! -noGlobalAssignno longer reports assignments to a Vue<script setup>binding from a template expression, when the binding's name happens to match a built-in global (e.g.open,parent,top).For example, this no longer triggers a diagnostic:
v2.5.10Compare Source
Patch Changes
#11403
8f7786fThanks @Princesseuh! - Fixed Astro rejecting JavaScript comments between attributes.#11403
8f7786fThanks @Princesseuh! - Fixed a bare<in Astro text being treated as the start of a tag, such as<p>5 < 6 and 7 > 6</p>. As in HTML, a<that cannot open a tag is text and needs no escaping.#11438
3133ffaThanks @Princesseuh! - Fixed #8294: an Astro expression holding only a comment is no longer reported as a parse error, which also stopped the whole file from being formatted.#11403
8f7786fThanks @Princesseuh! - Fixed #9165: an empty Astro expression such as<div>{}</div>no longer fails to parse. Astro renders{}as nothing.#11403
8f7786fThanks @Princesseuh! - Fixed Astro expressions containing a comment failing to parse.#11403
8f7786fThanks @Princesseuh! - Added support for Astro's fragment shorthand.#11403
8f7786fThanks @Princesseuh! - Fixed an Astro frontmatter block being cut short by a closing tag inside a string or comment.#11403
8f7786fThanks @Princesseuh! - Fixed---being read as an Astro frontmatter fence when markup precedes it. Astro only recognizes frontmatter at the very start of a file, so a file opening with a comment now has no frontmatter, and its---lines are content.#11403
8f7786fThanks @Princesseuh! - Fixed an Astro frontmatter block ending early on a line that merely starts with a dash.#11403
8f7786fThanks @Princesseuh! - Fixed the children of an Astro element carryingis:rawbeing parsed as markup instead of raw text. This now also covers<script>and<style>, whose contents Astro emits verbatim rather than processing, so they are no longer linted as JavaScript or CSS.#11403
8f7786fThanks @Princesseuh! - Fixed Astro rejecting attribute names that start with a colon, such as:href.#11403
8f7786fThanks @Princesseuh! - Fixed the Astro parser failing to recover from a malformed closing tag such as<div></{<//, so that a later mistake is reported where it happens rather than cascading.#11403
8f7786fThanks @Princesseuh! - Fixed{inside an Astro<math>element opening an expression. MathML is foreign content where Astro parses no expressions, so LaTeX such asR^{2x}now survives as text.<svg>is unaffected.#11403
8f7786fThanks @Princesseuh! - Fixed{{at the start of an Astro expression being read as an interpolation. Astro has no{{ }}syntax, so{{ a: 1 }}and<Comp a={{ b: 1 }} />are object literals.#11403
8f7786fThanks @Princesseuh! - Fixed expressions inside an Astro<pre>or<textarea>being read as raw text. Astro parses both as ordinary elements, so their markup and interpolations are now parsed, and a variable used only inside one is no longer reported as unused.#11403
8f7786fThanks @Princesseuh! - Added support for template literal attribute values in Astro, such as<div class=`a ${b} c`>.#11403
8f7786fThanks @Princesseuh! - Fixed Astro rejecting HTML5 unquoted attribute values that contain`,=,'or", such as<a href=a=b>and<a href=a'b>.#11393
dec5a8fThanks @1678092075! - Fixed #11207:useStrictModeno longer reports Vue event handlers such as@click="count++".#11431
c065f99Thanks @levrik! - Fixed #11429: Variables and imports used by Vue same-name bindings such as:disabledorv-bind:disabledare no longer reported as unused.#11409
405dedbThanks @ematipico! - Fixed a memory leak in the LSP server where memory usage kept growing over long editor sessions.#11422
a51eff7Thanks @dyc3! - Fixed #11416: Biome no longer crashes when parsing incomplete{let}or{const}declarations in Svelte files.#11378
34b715cThanks @Netail! - Added extra rule sources from@eslint/css.biome migrate eslintdetects rules in your eslint configurations more reliably.#11403
8f7786fThanks @Princesseuh! - Fixed{#,{/,{:and{@being read as Svelte block openings in every HTML-like file. They are now Svelte-only, so in HTML, Vue and Angular files a sequence such as{#if x}is ordinary text instead of a parse error.#11443
8d45229Thanks @ematipico! - Fixed #11390:noFloatingPromisesno longer performs unnecessary type inference on call arguments when checking methods of non-generic class instances created withnew.#11425
9c2667bThanks @dyc3! - Fixed #6426: GritQL plugins now match and rewrite metavariables embedded in quoted strings.#11441
00317c3Thanks @dyc3! - Improved performance ofuseNamedCaptureGroup,noMisplacedAssertion,noSkippedTests,noExportsInTest,noDuplicateTestHooks,noIdenticalTestTitle,useTestHooksInOrder, anduseTestHooksOnTop.v2.5.9Compare Source
Patch Changes
#11321
41386f3Thanks @dyc3! - Fixed #11315: The CSS parser now recovers at declaration boundaries after bogus declarations, allowing subsequent valid declarations to be parsed.#11248
57b197eThanks @yanthomasdev! - Expanded the environment variable metadata used bybiome rageto includeBIOME_BINARY,BIOME_LOG_FILE, andRUST_BACKTRACEas well as reworded explanations for better readability.#11377
a8798eaThanks @Netail! - Added a new nursery ruleuseNamedLayerwhich disallows anonymous cascade layers.#11327
6771cf5Thanks @dyc3! - The HTML formatter now preserves meaningful blank lines in HTML, including spacing after elements with trailing spaces and blank lines between comment groups.#10312
ba8aa18Thanks @dyc3! - Added the nursery ruleuseTailwindShorthandClasses, which suggests shorter Tailwind utility classes. For example, the rule suggests replacingw-4 h-4withsize-4.#11333
715e0cdThanks @kkkhs! - Fixed #11328:lint/nursery/useExpectnow recognizes Vitest Browser Modeexpect.element()calls as assertions.#11343
9b98211Thanks @johncarmack1984! - Fixed #11311: the CSS parser now accepts Tailwind container-query variant names in@variant, such as@xland@max-xl. These previously produced a parse error and anoUnknownAtRulesdiagnostic.#11220
3e8c488Thanks @santichausis! - Fixed #9541:noUndeclaredVariables,noUnusedImports, andnoUnusedVariablesnow correctly recognise exported variables and functions declared in one embedded<script>block as usable from a sibling<script>block, in Svelte's<script module>/<script>pair and Vue's non-setup<script>blocks.For example, Biome no longer reports
greetas undeclared in the following Svelte component:#11300
36430ebThanks @dyc3! - Fixed the HTML formatter's whitespace handling formarquee,noscript,video,audio, andobjectelements.#11299
6559e6cThanks @jp-knj! - Added the nursery ruleuseAstroClientOnlyDirectiveValue, which reports Astroclient:onlydirectives without an initializer.For example,
<Component client:only />triggers the rule.#11365
7529811Thanks @MHJahanbakhsh! - Fixed #11229: TheuseGenericFontNamesrule now treatsmathas a valid generic font family.#11346
674f5f4Thanks @Jayllyz! - Fixed #11335:noComponentHookFactoriesnow reports ause-prefixed variable only when a function is assigned to it directly.#11334
c87c46aThanks @zkasuran! - Fixed #11317:noSvgWithoutTitleno longer reports ansvgthat uses the boolean shorthandaria-hidden(equivalent toaria-hidden={true}in React).#11364
13853b1Thanks @ematipico! - Fixed a bug whereuseJsxKeyInIterableincorrectly flagged Astro files.#11321
41386f3Thanks @dyc3! - Fixed #11315: Invalid CSS declarations in HTMLstyleattributes now produce parser diagnostics instead of causing a panic.#11325
67c3bf0Thanks @dyc3! - Fixed HTML text wrapping to account for the width of an adjacent closing tag, avoiding lines that exceed the configured width when the final word and tag must move together.#11367
fe5b5d4Thanks @ematipico! - Fixed TypeScriptcompilerOptions.pathsresolution when mapping targets omit./. Biome now resolves these targets relative to their configured path base.#11316
17e48d6Thanks @wanxiankai! - Fixed #11289: the safe fix fornoExtraBooleanCastnow preserves parentheses around nested conditional expressions.#11254
d25d113Thanks @dyc3! - Fixed #11242: Biome no longer crashes with an access violation when analysing files on Windows ARM64.#11221
85aac73Thanks @freeatnet! - Added the nursery rulenoUnsafeTypeAssertion, which disallows TypeScript type assertions while allowing const assertions.#11314
7ffb677Thanks @ematipico! - Fixed #11310: Restored the performance ofnoMisusedPromisesandnoFloatingPromiseswhen analyzed expressions share deep imported type paths.#11356
6cd3263Thanks @johncarmack1984! - The Tailwind parser now understands modifiers on bare utilities (@container/sidebar,shadow/50).#11318
76059e9Thanks @johncarmack1984! - The Tailwind parser now understands container-query variants (@sm:,@max-lg:,@min-[400px]:) and child and descendant variants (*:,**:).#11357
faa2074Thanks @johncarmack1984! - The Tailwind parser now accepts the legacy leading!important marker (!flex,hover:!p-4).#11344
f34e15cThanks @johncarmack1984! - The Tailwind parser now understands combinator selectors in arbitrary variants (has-[>svg]:,has-[+p]:), modifiers on variants (group-hover/menu:,@sm/main:), and arbitrary container-query sizes (@[400px]:).#11324
2f5d452Thanks @dyc3! - Fixed HTML formatting that inserted rendered whitespace between an element and touching text when the line wrapped.#11312
e65f07eThanks @xosnos! - Added a new nursery ruleuseControlLabelfor both HTML and JSX, which reports interactive control elements (button,menuitem) without an accessible label.#11364
13853b1Thanks @ematipico! - Fixed SVG parsing for files with an XML declaration followed by aPUBLICdoctype, such as<?xml version="1.0"?><!DOCTYPE svg PUBLIC "a" "b">.#11301
610ee28Thanks @dyc3! - Fixed parent tag wrapping when an HTML element starts or ends with a block-like or hidden child such assource,track, orparam.v2.5.8Compare Source
Patch Changes
#10710
0a0fbc1Thanks @dyc3! - Added a new nursery ruleuseReactCompiler, which reports diagnostics from React Compiler lint mode.#11251
ea9dd8aThanks @dyc3! - Improved performance ofnoImportCycles.#11247
52b44d6Thanks @dyc3! - Added the nursery rulenoSvelteLegacyConst, which disallows legacy Svelte{@const}tags and recommends declaration tags with$derived().Invalid:
Valid:
#11252
d5f5704Thanks @Turtle-Hwan! - Fixed #11250:useAwaitno longer reports async functions that contain anawait usingdeclaration.#11143
6be7be1Thanks @vznh! - Fixed #11017:noUselessUndefinedno longer reportsreturn undefinedwhen the enclosing function has a return type annotation other thanundefinedorvoid.#11234
caefe39Thanks @subotac! - Fixed #11228: CSS block comments between a declaration colon and value now preserve their source indentation.#11285
bca1f73Thanks @denbezrukov! - Fixed #11280: CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name.#11080
af16a0bThanks @dyc3! - HTMLstyleattribute values are now parsed as CSS. All Biome CSS lint rules are applied to thestyleattributes.#11195
6a85588Thanks @dyc3! - Fixed Svelte files failing to parse when an expression begins with an object literal.Now the following snippet is correctly parsed:
#11173
481d008Thanks @Austin1serb! - Fixed #10242: JavaScript GritQL patterns with multiple metavariables now match snippets consistently in WebAssembly.#11187
23c0369Thanks @ematipico! - Added the nursery rulenoInvalidPropertyInitValue, which reports an@propertywhoseinitial-valuedoes not match itssyntaxdescriptor. For example, the following declaration triggers the rule becauseredis not a<length>:#11272
73896e6Thanks @ematipico! - Improved the diagnostic emitted bynoRootType.#11240
bd0b68dThanks @ematipico! - Fixed #11223: Improved theperformance of
noMisusedPromiseswhen analyzing async class methods that call other methods through
this.#11172
4a0bc5cThanks @saberoueslati! - Fixed #10806:noUselessFragmentsno longer causes Biome to panic when its unsafe fix removes a fragment used as a JSX attribute value.#11227
4d603b0Thanks @saberoueslati! - Fixed #11178:noUndeclaredVariablesno longer reports Vue's built-in instance properties, such as$slotsand$attrs, in template expressions or$eventin inline event-handler expressions. The instance properties are still reported inside<script setup>, where they are not defined.#11187
23c0369Thanks @ematipico! - Fixed CSS parsing of registered custom properties: Biome now correctly validates thesyntaxdescriptor of@propertyrules.v2.5.7Compare Source
Patch Changes
#10822
c171b3bThanks @pkallos! - Added the optionignoreIfStatementsto useNullishCoalescing. Biome now flagsifstatements that only assign to a nullish variable (such asif (!a) { a = b }) and can rewrite them to??=. When enabled, Biome ignores thoseifstatements.#11136
e63354cThanks @AkashNaickar! - Added a new nursery rulenoExtendNative, which reports extending the prototype of a built-in object.#10094
e007143Thanks @THEjacob1000! - Added the nursery rulenoTailwindArbitraryValue. Biome now reports Tailwind CSS arbitrary values such asw-[400px], including in HTML/JSX class attributes, configured utility functions, and tagged templates.#11184
135f476Thanks @subotac! - Fixed #11176:noUnknownPseudoClassnow recognizes Vue's:deep()pseudo-class inside.vuestyle blocks.#8239
a519f9dThanks @cormacrelf! - Fixed #8233, where Biome CLI instdin mode didn't work correctly when handling files in projects with nested
configurations. For example, with the following structure,
--stdin-file-path=subdirectory/...would not use the nested configuration insubdirectory/biome.json:Now, the nested configuration is correctly picked up and applied.
In addition, Biome now shows a warning if
--stdin-file-pathis provided butthat path is ignored and therefore not formatted or fixed.
#11138
8c2c6bdThanks @ematipico! - FixednoUnnecessaryConditions: Biome now chooses the same function overload as TypeScript when an argument is a callback, so conditions that were previously missed are reported.The following code is now invalid, because a parameter typed
() => voidaccepts anasynccallback andscheduletherefore returnsstring:The following code is also now invalid, because
map(() => 42)returns42:#11138
8c2c6bdThanks @ematipico! - Fixed #11087:noUnnecessaryConditionsno longer reports optional chains and nullish coalescing whose receiver can be nullish.For example, the optional chain and fallback in the following code are no longer reported:
#11118
9c16840Thanks @subotac! - Fixed #11098: The HTML formatter now preserves the configured trailing newline when a file ends with a comment.#11201
0e80610Thanks @Bishwas-py! - Fixed #11182: suppression comments fornoPositiveTabindexnow suppress the rule in HTML files when the attributes of the element span multiple lines.#11079
607afd2Thanks @dyc3! - The HTML formatter now lays out thesrcsetattribute of<img>and<source>as the list of candidates it is. Runs of whitespace between candidates collapse, and once the list no longer fits on one line each candidate goes on its own line with the descriptors aligned:#11156
fed72c7Thanks @saberoueslati! - Fixed #11129:noUnusedVariablesno longer reports Vue bindings as unused when they are assigned through automatically unwrapped template refs.#11124
d890b39Thanks @denbezrukov! - Fixed CSS formatting of line comments between a declaration colon and value to preserve their source indentation.#11113
3d8ab73Thanks @denbezrukov! - Fixed CSS formatting of long block comments between comma-separated property values:#11127
da5c1a5Thanks @dyc3! - The HTML formatter now picks the quote character for an attribute by counting the quotes in the value rather than looking only for a double quote.'and"count as the characters they stand for, and only the character that ends up as the delimiter stays escaped:Entities that are not quotes, such as
&or&[#​39](https://github.com/biomejs/biome/issues/39);, are left exactly as written.#11193
77035bbThanks @dyc3! - Fixed the HTML formatter collapsing the blank line between an element and the text that follows it. A blank line before text is now kept, the way one before another element already was:#11106
ad80f57Thanks @dyc3! - The HTML formatter now writes the HTML5 doctype in lowercase, matching Prettier:This only applies to a plain
.htmlfile whose doctype stands alone. A doctype that names a DTD keeps the case it was written with, since the rest of the declaration is not lowercased either:A
.vue,.svelte, or.astrofile keeps whatever the author wrote.#11188
60679dbThanks @dyc3! - Fixed the HTML formatter printing a comment twice when it ended the line of the last element in a document:#11077
4dcd0d9Thanks @dyc3! - Fixed a bug where the HTML formatter collapsed the whitespace inside<textarea>,<xmp>and<plaintext>, changing what the page renders.Biome now prints the content of these elements exactly as it appears in the source, matching the existing behavior for
<pre>.#11194
abfbb11Thanks @dyc3! - Fixed the HTML formatter refusing to format a Svelte file containing an array pattern that skips a position:#10094
e007143Thanks @THEjacob1000! - FixeduseSortedClassesto correctly detect unsorted classes in static member expression tagged templates (e.g.tw.div\...``). Previously, these were silently skipped due to surrounding whitespace trivia not being stripped from the tag name.#11078
10da30eThanks @dyc3! - Fixed Vue single-file components failing to parse when they contain a custom block such as<i18n>or<docs>, or a<template>written in another language. Their content is no longer read as HTML, so a block may hold whatever its own tooling expects:Previously both blocks produced a parse error and the whole file was left unformatted. Biome now prints their content unchanged while still formatting the opening tag.
#11231
4afd901Thanks @ematipico! - Improved the performance of the following lint rules:noArguments.noGlobalAssign.noUndeclaredVariables.noRestrictedGlobals.noInvalidUseBeforeDeclaration.noShadow.noRedeclare.#11134
2fa0a62Thanks @yanthomasdev! - Clarified the warning emitted when using the experimentaljsonandjson-prettyreporters.#11198
ed88b13Thanks @saberoueslati! - Fixed #11171: variables referenced only inside a Svelte attachment ({@attach ...}) are no longer reported as unused bynoUnusedVariablesandnoUnusedImports.#11155
6ee17eaThanks @dyc3! - Improved performance when printing diagnostics to the console.#11160
217f8adThanks @dyc3! - Improved the performance ofnoFloatingPromisesby skipping type inference for assignment statements, which are always considered handled.#11159
26c23d9Thanks @saberoueslati! - Fixed #11144:noFloatingPromisesno longer reports already-awaited optional Promise values.#11138
8c2c6bdThanks @ematipico! - Fixed #11121:noUnnecessaryConditionsno longer reports conditions based on an inapplicable function overload.For example, the condition in the following code is no longer reported because
query({})selects the overload that returnsboolean:#11152
c4fc6a9Thanks @dyc3! - Improved the performance of collecting rule timings with--profile-rulesin heavily multithreaded environments.#11128
4d3ff76Thanks @ematipico! - Fixed #7635:noDeprecatedImportsnow detects deprecated ambient declarations that are exported separately.#11117
01f7ef5Thanks @subotac! - Fixed #11014:noDeleteno longer reportsprocess.env["FOO"]style property deletions.#11168
9847e68Thanks @saberoueslati! - Added the nursery rulenoNonScalableViewport, which reports viewport metadata that disables user scaling withuser-scalable=no.For example:
#11154
a1d6b1fThanks @dyc3! - Improved the performance ofnoImportCyclesby skipping graph traversals for imports that cannot be part of a cycle.#11175
d96d6ddThanks @ematipico! - Fixed CSS parsing of registered custom properties: Biome now correctly validates thesyntaxdescriptor of@propertyrules.v2.5.6Compare Source
Patch Changes
#11035
0e4b03bThanks @ematipico! - Fixed a performance regression innoMisusedPromisesthat caused type inference to run repeatedly while linting a file.#11043
22ec076Thanks @denbezrukov! - Fixed CSS formatting for multiline function arguments preceded by comments:#11007
c9acb25Thanks @BTF-Kabir-2020! - Fixed #9195:useHookAtTopLevelno longer reports hooks in namedforwardRefcomponents that receive arefparameter.#10152
50a9bd8Thanks @Zelys-DFKH! - Fixed #10131: Biome now correctly parses curried arrow functions in ternary consequents when the inner arrow's parameters use a destructuring pattern, e.g.cond ? (x) => ({ a, b }) => body : alt.#11105
8ffe2b9Thanks @dadavidtseng! - Fixed #11092: ThenoUselessTernaryquick fix now preserves operator spacing when simplifying or inverting boolean ternary expressions.#10533
5809875Thanks @Mokto! - Fixed #10515:biome check --writewas not idempotent on Svelte files — multi-line template literals in<script>blocks and block comments in<style>blocks gained an extra indent level on every run.#11040
0abb620Thanks @Mokto! - Fixed an issue where the HTML formatter would duplicate a comment placed directly before a Svelte{@const ...}or{@debug ...}block. The duplication compounded on every subsequent--write, causing the file to grow exponentially.#10858
6d18204Thanks @ruidosujeira! - Fixed #10839: Svelte{#each}array destructuring no longer includes spaces inside square brackets, and multiline bind function expressions now indent their getter, setter, and function body correctly.#11009
2c36626Thanks @ematipico! - Improved the accuracy of type-aware lint rules by resolving more inferred types. For example,noFloatingPromisesnow detects floating Promises returned by aliased callbacks and arrays of Promises created by async mapping callbacks.The following statements are now reported:
#10973
9cb044cThanks @ematipico! - Fixed false positives innoMisleadingReturnTypewhen generic-constraint, normalization, substitution, or structural return-type comparison cannot complete. The rule now suppresses diagnostics rather than suggesting a return type derived from partial information. For example, this unresolved return type is no longer reported:#11071
15047a2Thanks @dyc3! - The HTML parser now accepts mixed-casedoctypedeclarations.#11030
cc90e65Thanks @marschattha! - Therdjsonreporter now populates the severity field of each diagnostic (ERROR,WARNING, orINFO), so tools consuming Reviewdog Diagnostic Format output no longer need to assume a default severity.#11009
2c36626Thanks @ematipico! - Fixed a performance regression in type-aware JavaScript lint rules by inferring only requested types and memoizing export resolution.#11056
903b177Thanks @dyc3! - Added support for Svelte declaration tags usingletandconst. Biome can now parse, format, and lint bindings declared in these tags.#11045
89c27c6Thanks @ematipico! - Improved the performance of Biome formatter up to ~7% across the board.#9806
781d68dThanks @dyc3! - Added the nursery rulenoJsRestrictedProperties, which ports ESLint'sno-restricted-propertiesrule. Biome now flags restricted member access and object destructuring, andbiome migrate eslintpreserves the rule's options.v2.5.5Compare Source
Patch Changes
#10972
ab8c21bThanks @ematipico! - FixeduseExhaustiveSwitchCasesfor unions of bigint literals. The rule now reports missing bigint cases and compares bigint literals by value, including binary, octal, hexadecimal, and separator-containing spellings. For example, this switch now reports the missing2ncase:#10972
ab8c21bThanks @ematipico! - Fixed false positives innoBaseToStringanduseNullishCoalescingwhen member, stringification, or nullish inference cannot complete. These rules now suppress diagnostics instead of reporting from partial type information. For example, neither expression is reported when a recursive type cannot be fully resolved:#10977
0bf7486Thanks @ematipico! - Fixed #10922: the actionuseSortedAttributesno longer triggers for HTML instructions.#10957
cf263c4Thanks @dyc3! - FixednoThenPropertyfailing to detectObject.fromEntries,Object.defineProperty, andReflect.definePropertycalls with comments between their tokens.#10983
edc0ed7Thanks @ayaangazali! - Fixed #10980:useAriaPropsSupportedByRoleno longer reports false positives when the attribute that determines an element's implicit ARIA role is written as a shorthand attribute, such as<a {href} aria-label="...">in Astro and Svelte files.Shorthand attributes are now taken into account when computing the implicit role, so the anchor above correctly resolves to the
linkrole instead ofgeneric.#10889
89526e3Thanks @denbezrukov! - Fixed CSS formatter casing for syntax-owned names while preserving author-defined names, including scoped keyframes and container scroll-state queries.#10964
794ccd0Thanks @denbezrukov! - Fixed CSS formatting for comments between declaration values and!important.#10993
b7a9694Thanks @denbezrukov! - Fixed the CSS formatter to preserve comments on the correct side of selector combinators and before declaration blocks.It now also keeps selectors with escaped newlines in attribute values inline when they fit.
#10978
8ebafe1Thanks @ematipico! - Fixed #10870:noUnresolvedImportsno longer reports false positives such asimport type { NextRequest } from "next/server".#10901
68c10e6Thanks @Socialpranker! - Fixed #10622: the HTML/Vue parser no longer panics on the argument-lessv-bindshorthand (:="props").This syntax is valid Vue and equivalent to
v-bind="props", so the parser now accepts it (along with the longhandv-bind:="props") instead of crashing while building a diagnostic for a missing argument.#10936
7df46f5Thanks @ematipico! - Improved generic tuple inference foruseIncludes. The rule now recognizes specialised tuple element types returned through generic aliases.#10941
f787725Thanks @siketyan! - Fixed#10855: Biome now supports parsing and formatting CSS custom media queries declared with@custom-media.#10969
72d309bThanks @ematipico! - Fixed an issue where Biome logs became too verbose, dumping information not relevant to user's operations.e62f6b6Thanks @ematipico! - Fixed #10963: Biome no longer panics when a type-aware rule such asnoFloatingPromiseschecks a call to a function with multiple call signatures imported from another module.#10931
899c60dThanks @ematipico! - Fixedcheck --writecommand. Now the command reports code frame of the formatted code, if the formatter is enabled.#10904
ceee4f4Thanks @qzwxsaedc! - Fixed #10892:noUnnecessaryConditionsno longer reports a false positive when checking a member of a discriminated union that is accessed through a default type-only namespace import. The following code is no longer flagged:#10962
f0a67f2Thanks @ematipico! - Biome no longer removes embedded styles and scripts in HTML files.#11000
5039a1eThanks @ematipico! - Fixed a bug where closing one editor stopped a shared Biome daemon used by other editors. LSP proxy processes now exit when either the editor or daemon disconnects.#10957
cf263c4Thanks @dyc3! - Improved the performance of thenoThenPropertylint rule by about 50%.#10992
4bf9b21Thanks @ematipico! - FixednoMisusedPromises: The rule now reports Promise-returning callbacks where a synchronous callback is expected when calls use tuple spreads or tuple rest parameters, including generic and deeply nested tuples, and when constructor signatures come from interface or object types. Recursive or excessively nested tuple spreads use a conservative fallback so analysis terminates.For example, the following callback is now reported.
#10915
b3b12b3Thanks @Functionhx! - Added the rulenoNegationInEqualityCheck. The rule flags negated expressions on the left side of strict equality checks like!foo === bar— due to operator precedence this evaluates as(!foo) === barwhich is almost always a mistake forfoo !== bar.The rule provides an unsafe fix that flips the operator.
#10970
bd1038bThanks @ematipico! - Improved overload selection fornoMisusedPromises. Biome now handles overloaded calls, overloaded constructors, rest parameters, union arguments, and generic constraints without selecting an incompatible signature. For example,noMisusedPromisesnow reports the async callback passed to the synchronous overload:#10933
48a4abbThanks @ematipico! - FixeduseArrayFindto recognize bigint zero indexes.#10931
899c60dThanks @ematipico! - Fixed an orchestration issue that could lead to deadlocks when type-aware rules are enabled.#10969
72d309bThanks @ematipico! - Hardened the Biome Language Server by improving its synchronisation logic.#10972
ab8c21bThanks @ematipico! - Fixed false positives innoMisusedPromisesanduseAwaitThenablewhen Promise or thenable inference cannot complete. These rules now suppress diagnostics instead of treating incomplete type information as a definite result. For example,useAwaitThenableno longer reportsawait valuewhen the value's thenability is unknown:v2.5.4Compare Source
Patch Changes
#10665
55ff995Thanks @dyc3! - Improved the performance of the HTML parser slightly in our synthetic benchmarks.#10894
f4fb10eThanks @ematipico! - Fixed #6392: On-type formatting no longer moves comments before anifstatement into its body.#10939
f2799dbThanks @Netail! - Fixed #10930:noLabelWithoutControlnow correctly detects text interpolation in Astro, Svelte & Vue as valid accessible content.#10945
ae15d98Thanks @Netail! - Fixed #10942: Svelte directives don't throw an accidental debug log anymore.#10842
5e1abfeThanks @JamBalaya56562! - Fixed #9196:biome check --write --unsafeno longer hangs forever when applying thenoCommentTextcode fix.The rule's fix now wraps the comment in a real JSX expression container (
{/* comment */}) instead of re-inserting the braces as plain JSX text, so the fixed code is no longer reported again by the same rule.#10891
ecca79eThanks @ematipico! - Fixed#10885: prevented a module-inference regression introduced by a housekeeping change.#10886
60c8043Thanks @dyc3! - Fixed #10727: Biome now breaks the arguments of curriedtest.each,it.each,describe.each, andtest.forcalls when they exceed the configured line width.#10895
01a85f0Thanks @ematipico! - Biome will now remove stale Unix daemon sockets from older Biome versions when starting a newer daemon.v2.5.3Compare Source
Patch Changes
#10815
86613d5Thanks @WaterWhisperer! - Fixed a parser panic reported in #10708: Biome now recovers when unsupported CSS Modules@valuerules or scoped@keyframesnames end at EOF.#10534
da9b403Thanks @Mokto! - FixednoUnusedVariablesfalse positives in Svelte files: Svelte store subscriptions ($storereferences in templates now keep the underlyingstorebinding from being flagged), and$bindable()props that are only written to in the script block (write-only is intentional for bindable props) are no longer reported as unused.#10827
098ba41Thanks @Aqu1bp! - Fixed #10698: ThenoUnsafeOptionalChainingrule now reports unsafe optional chains wrapped in TypeScriptas,satisfies, type assertion, and instantiation expressions, such asnew (value?.constructor as Constructor)().#10773
3c6513dThanks @otkrickey! - Fixed #10772:useVueValidVOnno longer reports a missing handler for v-on directives using a verb modifier (.stop/.prevent) without an expression, e.g.<div @click.stop></div>. The rule also accepts the arg-less object syntax<div v-on="$listeners"></div>instead of reporting a missing event name.#10721
d83c66bThanks @minseong0324! - Improved type-aware lint rule inference for built-in globals and indexed function calls. Biome now resolvesError(...),new Error(...), optionalError#stack, and calls through indexed function values such ashandlers[0]()more accurately.#10865
6450276Thanks @ematipico! - Fixed #10845. Biome Language Server no longer goes in deadlock when the scanner is enabled.#10853
93d8e53Thanks @Netail! - Fixed #10840: Astro shorthand attribute syntax is now correctly being parsed from embedded nodes.#10820
bba3092Thanks @JamBalaya56562! - Fixed #10619:noProcessEnvnow also reports computed (bracket) member access. Previously only dot access was checked, soprocess["env"]andenv["NODE_ENV"](whereenvis imported fromnode:process) were missed. Both static and computed accesses are now reported.#10835
3447b2fThanks @dyc3! - Fixed #10824:useDomQuerySelectornow supports anignoreoption for receiver identifiers that should not be reported.#10875
b12e486Thanks @dyc3! - Fixed #10795:--profile-rulesnow reports timings for each plugin separately asplugin/<pluginName>, matching the naming used by plugin suppressions, instead of aggregating all plugins under a singleplugin/pluginentry.#10877
d6bc447Thanks @ematipico! - Fixed biome-zed#164: Biome no longer inserts stray whitespace when format-on-type runs after closing delimiters such as),], and}.#10867
a21463eThanks @dyc3! - Fixed #10864: Biome no longer crashes when checking or linting HTML files with unquoted attribute values such as<textarea rows=4></textarea>.v2.5.2Compare Source
Patch Changes
#10595
f458028Thanks @pkallos! - Added the optionignoreBooleanCoercionto useNullishCoalescing. When enabled, Biome ignores||and||=used inside aBoolean()call, where coalescing on falsy values is intentional.#10798
4a32b63Thanks @pkallos! - Added the optionignorePrimitivesto useNullishCoalescing. When enabled, Biome ignores||,||=, and ternary expressions whose non-nullish operands are all primitives the option opts out of. Usetrueto ignore all primitives, or an object selectingstring,number,boolean, orbigint.#10545
f3d4c00Thanks @Mokto! - Added the new nursery rulenoSvelteUnnecessaryStateWrap, which reports unnecessary$state()wrapping of classes fromsvelte/reactivitythat are already reactive.#10752
f62fb8bThanks @ematipico! - Fixed #10739. Now the ruleuseValidAutocompletecorrectly flags theautoCompleteattribute.#10796
f1b3ab2Thanks @ematipico! - Fixed #10768. Improved the performance of the Biome Language Server by cancelling certain in-flight operations when there are fast updates.#10719
aa649b5Thanks @minseong0324! - FixednoMisleadingReturnTypefalse positive on returns that use a widening type assertion:"a" as stringis no longer reported as misleading. The rule now also reports a literal-pinning assertion such asfalse as false, matching the existingas constbehavior.#10678
8f073a7Thanks @PranavAchar01! - Fixed #7718: Biome now correctly parses CSS nesting selectors when&appears as a trailing sub-selector after a type selector, e.g.h1& { color: red; }.#10756
5ec965aThanks @denbezrukov! - Fixed CSS formatter output for selector lists withallowWrongLineCommentsand//comments after a selector comma. Biome now keeps the selector before the line comment inline instead of breaking it across descendant combinators.#10757
6232fcdThanks @PranavAchar01! - Fixed #8269: the CSS parser now accepts Tailwind@variantand@utilitynames that start with a digit, such as the2xlbreakpoint.#10777
575ced6Thanks @WaterWhisperer! - Fixed an issue reported in #10708: the GitLab reporter now handles--verbosediagnostics filtering correctly.#10281
0efe244Thanks @Zelys-DFKH! - Fixed a bug where GritQL patterns rejected positional (unkeyed) arguments.#10758
e36fd8aThanks @henrybrewer00-dotcom! - Fixed #10697: The formatter no longer removes the parentheses around anawaitoryieldexpression used as the target of a TypeScript instantiation expression. For example,(await makeFactory)<Value>is no longer reformatted toawait makeFactory<Value>, which would change the meaning of the code.#10586
3617094Thanks @IxxyDev! - Fixed #9568:noFloatingPromisesno longer reports a false positive when calling an overloaded function and the selected overload does not return a promise.#10766
7aff4c1Thanks @JamBalaya56562! - Fixed #2862:noInteractiveElementToNoninteractiveRoleno longer reports custom elements (a tag name containing a dash, e.g.<my-button role="img" />). Per the W3C HTML-ARIA specification, a custom element may be given any role or none.#10680
771daa4Thanks @WaterWhisperer! - Fixed #10635: Biome now recognizes chainedtable tests such as
test.concurrent.each()andit.concurrent.each()as test calls, fixingnoMisplacedAssertionfalse positives and improving formatting for those test declarations.#10759
34570b5Thanks @henrybrewer00-dotcom! - Fixed #10636: noStaticElementInteractions no longer reports a false positive for event handlers on Svelte special elements such as<svelte:window>,<svelte:document>, and<svelte:body>. These are not real DOM elements, so they are now ignored by the rule.#10741
bd2364eThanks @JamBalaya56562! - Fixed #6686: theragecommand now respects the--config-pathoption and theBIOME_CONFIG_PATHenvironment variable when loading the Biome configuration. Previously it always used the default configuration resolution and reported the configuration asNot setwhen nobiome.jsonexisted in the working directory.#10763
2c3e82dThanks @Aqu1bp! - Fixed #10742:noSolidDestructuredPropsnow reports destructured props in Solid function components and JSX children.#10606
a4cc4abThanks @Mokto! - Fixed false positives innoUnusedImports,noUnusedVariables, anduseImportTypefor Svelte components that use both a<script module>and a<script>block. The two blocks compile to a single module and share a top-level scope, so a binding (import, function, or variable) declared in one block and used only in the other is no longer reported as unused.#10767
36d5aa7Thanks @otkrickey! - Fixed #10754:useVueValidVBindno longer reports the Vue 3.4+ same-name shorthand as missing a value.:fooandv-bind:fooare now accepted as equivalent to:foo="foo", whilev-bind,v-bind:[dynamicArg], and:[dynamicArg]without a value continue to be reported.#10775
a918af0Thanks @WaterWhisperer! - Fixed an issue reported in #10708:biome ragedidn't detect running Biome daemon pipes on Windows.#10730
5a2e65bThanks @dinocosta! - Fixed an issue where Biome was resolving the well-known Zed settings file from the wrong location on macOS and Windows.#10807
d97fffeThanks @ematipico! - Fixed an issue where.scssfiles were incorrectly analyzed when runningbiome check.#10672
53c6efcThanks @ematipico! - Fixed a bug where Biome incorrectly formatted snippets that have parsing errors.#10719
aa649b5Thanks @minseong0324! - FixeduseAwaitThenablefalse positive when awaiting a custom thenable that is not the globalPromise. A value with a callablethenmember is now recognized as awaitable.#10734
4396496Thanks @BangDori! - Fixed #10708:biome migratenow preserves trivia when migrating the deprecatedrecommendedoption topreset.#10683
ae31a00Thanks @Netail! - Fixed #10657 #10671 #10661 #10637 #10718: HTML rules now correctly handle dynamic attributes.#10746
54e8239Thanks @ematipico! - Fixed an issue wherenoUndeclaredClassesdidn't correctly detect styles defined inside the Astro directiveis:global.#10770
dd1429cThanks @ematipico! - Improved the Biome Language Server DX by orchestrating certain operations, so that they won't block the editor during typing. This improvement is more visible in large documents.#10473
d9b5133Thanks @Mokto! - ImprovednoUnusedImports,noUnusedVariables,noUnusedFunctionParameters, anduseImportTypefor Svelte, Vue, and Astro files (withhtml.experimentalFullSupportEnabled). Bindings used only in the template — including component tags, attribute interpolations, directives,bind:shorthand, and snippet parameters — are no longer reported as unused, while genuinely unused ones still are.#10796
f1b3ab2Thanks @ematipico! - Fixed an issue where the Biome Language Server didn't enable project or type-aware lint rules, even when they were explicitly enabled.#10746
54e8239Thanks @ematipico! - Fixed an issue wherenoUndeclaredClassesdidn't detect styles declared inside HTML documents.#10774
bde945bThanks @pattrickrice! - Fixed #10268 where a race condition resulted in internal errors such as:The file biome.json does not exist in the workspace.v2.5.1Compare Source
Patch Changes
#11379
07a0073Thanks @Netail! - Added the nursery ruleuseLayeredStyles, which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer.#11667
e997900Thanks @devtechedge! - Added the nursery ruleuseBetterDomTraversing, which prefers.firstChild,.firstElementChild,.closest(), and merged.querySelector()calls over positional DOM traversal.#11620
20e513aThanks @jakeleventhal! - Fixed #11610, #11611, #11612, #11615, and #11616: Biome no longer fully infers an imported generic declaration just to apply its type arguments, restoring type-aware lint performance for large libraries such as Zod. This improvesuseRegexpExec,noFloatingPromises,noMisusedPromises,useNullishCoalescing, andnoUnsafePlusOperands.#11657
e322040Thanks @ematipico! - Fixed #7495:noUselessConstructornow ignores TypeScript constructors that forward at least one argument tosuper, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged.#11670
4969ee1Thanks @ematipico! - Fixed #7076:useAriaPropsForRoleanduseFocusableInteractiveno longer report non-focusable elements withrole="separator". A separator with an explicittabIndexortabindexstill requiresaria-valuenow.#11627
23aad6dThanks @ematipico! - Fixed #6571 so Grit plugins can capture and inspect multiple named import specifiers.#11631
00dbd3aThanks @ematipico! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports.#11628
a2f8ff7Thanks @dyc3! - Added the nursery rulenoXorAsExponentiation, which reports the bitwise XOR operator^between two decimal integer literals, where the exponentiation operator**was likely intended.#11670
4969ee1Thanks @ematipico! - Fixed #7192:noUnusedPrivateClassMembersnow considers compound assignments such as??=to read and use private class members.#11676
840a52aThanks @dyc3! - Fixed #11672 and #11671 by disabling the experimental capitalized-call and effect-dependency checks inuseReactCompiler, matching their exclusion from upstream's recommended lint preset. Valid calls such asIntl.NumberFormat()and captures of variables declared inside effects no longer produce these diagnostics.#11660
49485edThanks @ematipico! - Fixed #11653: Astro template suppression comments ({/* biome-ignore lint: reason */}) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled.#11664
9a73b9cThanks @dyc3! - Improved the performance ofuseRegexpExec.#11661
5341b3fThanks @ematipico! - Fixed #7479.noUnusedVariablesnow treats Unicode escapes in identifiers as the same binding as their decoded spelling.#11630
62e1fc5Thanks @dyc3! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width.#11658
ed4bfa4Thanks @fredrikblau! - Fixed #11644:useHeadingContentno longer reports headings that render their text with a directive:set:htmlandset:textin Astro files,v-htmlandv-textin Vue files.#11613
47d7383Thanks @ematipico! - Improved the performance of Biome Formatter up to ~50% in some cases.#11655
fd8fc74Thanks @ematipico! - Fixed #6974, wherenoUnusedPrivateClassMembersincorrectly reported TypeScript private constructor properties read through object destructuring fromthisas unused.#11618
21a10cfThanks @siketyan! - Fixed #11605: Type inference now infers the type of an unannotated callback parameter from the signature of the function the callback is passed to, and honours explicit type arguments on call expressions. This improves type-aware analysis fornoBaseToString,noFloatingPromises,noMisleadingReturnType,noMisusedPromises,noUnnecessaryConditions,noUnsafePlusOperands,noUselessTypeConversion,useArrayFind,useArraySortCompare,useAwaitThenable,useDisposables,useExhaustiveSwitchCases,useIncludes,useNullishCoalescing,useRegexpExec, anduseStringStartsEndsWith. For example,noFloatingPromisescan now detect Promises reached through such parameters:#11698
b019982Thanks @denbezrukov! - Fixed parsing of unquoted CSS URLs beginning with@or!, such asurl(@/assets/icon.svg)andurl(!font.woff2). Preserved escaped and non-ASCII whitespace in raw URLs during formatting.#11622
c23e4c7Thanks @Netail! - Added the nursery rulenoUnsafeIframeSandbox, which reportsiframeelements whosesandboxattribute combinesallow-scriptsandallow-same-origin, since that combination lets the embedded document remove its own sandboxing.#11606
de0528fThanks @dyc3! - Added the recommendednoSvelteAtHtmlTagsnursery rule, which reports Svelte{@html}tags that render unescaped HTML.#11670
4969ee1Thanks @ematipico! - Fixed #6782: GritQL plugins now match captured JSX component names against code snippets such asReact.Fragment.#11687
09d97d9Thanks @hori-design! - Fixed #11678:useReactCompilerno longer panics on files that contain non-ASCII characters. This bumps the React Compiler version.#11595
a64d757Thanks @dyc3! - Added the nursery Vue-domain ruleuseVueBaseImportrule, which enforces importing Vue APIs fromvueinstead of internal@vue/*packages.#11675
353cbaeThanks @dyc3! - FixeduseReactCompilersilently producing no diagnostics in WebAssembly builds, including the playground.#11625
ea20e5aThanks @denbezrukov! - Improved linting performance for large CSS and JSON files.#11670
4969ee1Thanks @ematipico! - Fixed #7527: suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressingnoTsIgnorenow places thebiome-ignorecomment before@ts-ignore.#11655
fd8fc74Thanks @ematipico! - Fixed #8629, wherenoUnusedPrivateClassMembersincorrectly reported used private TypeScript method overload signatures as unused.#11669
579f401Thanks @denbezrukov! - Improved the performance ofnoExcessiveLinesPerFilewhenskipBlankLinesisfalse.v2.5.0Compare Source
Minor Changes
#9539
f0615fdThanks @ematipico! - Added a new reporter calledconcise. When--reporter=conciseis passed the commandsformat,lint,checkandci, the diagnostics are printed in a compact manner:#9495
2056b23Thanks @aviraldua93! - Added theuseKeyWithClickEventsa11y lint rule for HTML files (.html,.vue,.svelte,.astro). This is a port of the existing JSX rule. The rule enforces that elements with anonclickhandler also have at least one keyboard event handler (onkeydown,onkeyup, oronkeypress) to ensure keyboard accessibility.Inherently keyboard-accessible elements (
<a>,<button>,<input>,<select>,<textarea>,<option>) are excluded, as are elements hidden from assistive technologies (aria-hidden) or withrole="presentation"/role="none".#9152
9ec8500Thanks @ematipico! - Added new nursery lint rulenoUndeclaredClassesfor HTML, JSX, and SFC files (Vue, Astro, Svelte). The rule detects CSS class names used inclass="..."(orclassName) attributes that are not defined in any<style>block or linked stylesheet reachable from the file.#9152
9ec8500Thanks @ematipico! - Added new nursery lint rulenoUnusedClassesfor CSS. The rule detects CSS class selectors that are never referenced in any HTML or JSX file that imports the stylesheet. This is a project-domain rule that requires the module graph.#9546
6567efaThanks @nhedger! - Added abiome upgradecommand for standalone installations. It upgrades Homebrew installs withbrew upgrade biome, updates manually installed binaries from the latest GitHub release, and tells npm users to upgrade with their package manager instead.#9716
701767aThanks @faizkhairi! - Added the HTML version of theuseHeadingContentrule. The rule now enforces that heading elements (h1-h6) have content accessible to screen readers in HTML, Vue, Svelte, and Astro files.#9582
f437ef8Thanks @rahuld109! - Added the HTML version of theuseKeyWithMouseEventsrule. The rule now enforces thatonmouseoveris accompanied byonfocusandonmouseoutis accompanied byonblurin HTML, Vue, Svelte, and Astro files.#9275
1fdbceeThanks @ff1451! - Added the new assist actionuseSortedTypeFields, which sorts the fields of GraphQL object types, interface types and input object types alphabetically, e.g.name, age, idbecomesage, id, name.#10561
78075b7Thanks @Conaclos! - Added a newstyleoption to useExportType,which enforces a style for exporting types.
This is the same option as the one provided by
useImportType.#8987
d16e32bThanks @DerTimonius! - Ported theuseValidAnchorrule to HTML. This rule enforces that all anchors are valid and that they are navigable elements.#9533
4d251d4Thanks @ematipico! - Theinitcommand now prints the Biome logo.#10069
0eb9310Thanks @Netail! - Added the HTML lint rulenoStaticElementInteractions, which enforces that static, visible elements (such as<div>) that have click handlers use the valid role attribute.Invalid:
#9134
2a43488Thanks @ematipico! - Added the assist actionuseSortedPackageJson.This action organizes package.json fields according to the same conventions as the popular sort-package-json tool.
#9309
7daa18bThanks @Bertie690! - TheallowDoubleNegationoption has been added tonoImplicitCoercionsto allow ignoring double negations inside code.With the option enabled, the following example is considered valid and is ignored by the rule:
#9700
894f3fbThanks @ematipico! - The Biome Language server now supports the "go-to definition" feature.When the cursor of the mouse is hovering an entity (variable, CSS class, type, etc.), and the command CTRL + click is triggered, the editor jumps to where this entity is defined, if the language server can find it.
Here's what Biome is able to resolve:
#10070
bae0710Thanks @Conaclos! - Added the:STYLE:group matcher fororganizeImportsthat matches style imports.For example, the following configuration...
...places style imports last:
#9170
e3107deThanks @mdrobny! - AddedbundleDependenciesoption to NoUndeclaredDependencies rule.This rule now supports imports of packages that are defined only in
bundleDependenciesandbundledDependenciesarrays.#9547
01f8473Thanks @mujpao! - Added new assist ruleuseSortedAttributesfor HTML, porting the existing JSX rule. This rule enforces sorted HTML attributes.Invalid
#9366
2ca1117Thanks @dyc3! - Added thehtml.parser.vueconfiguration option. When enabled, it adds support for the parsing of Vue in.htmlfiles. Most Vue users don't need to enable this option since Vue files typically use the.vueextension, but it can be useful for projects that embed Vue syntax in regular HTML files.#9073
74b20eeThanks @chocky335! - Added support for applying GritQL plugin rewrites as code actions. GritQL plugins that use the rewrite operator (=>) now produce fixable diagnostics for JavaScript, CSS, and JSON files. By default, plugin rewrites are treated as unsafe fixes and require--write --unsafeto apply. Plugin authors can passfix_kind = "safe"toregister_diagnostic()to mark a fix as safe, allowing it to be applied with just--write.Example plugin (
useConsoleInfo.grit):Running
biome check --writeapplies safe rewrites. Unsafe rewrites (the default, orfix_kind = "unsafe") still require--write --unsafe.#9384
f4c9edcThanks @Conaclos! - Added thesortBareImportsoption toorganizeImports,which allows bare imports to be sorted within other imports when set to
false.#8731
e7872bfThanks @siketyan! - Added the watch mode (--watch) to the CLI forcheck/format/lintcommands. By enabling this option, Biome will re-run the check automatically when any file in the workspace has changed after the first run.#10106
9b35f78Thanks @ematipico! - Biome can now format and lint.svgfiles.#9967
e9b6c17Thanks @dyc3! - Added HTML support fornoExcessiveLinesPerFile. Biome now reports HTML files that exceed the configured line limit, including whenskipBlankLinesis enabled.#9491
b3eb63cThanks @IxxyDev! - Added the HTML lint rulenoAriaUnsupportedElements. This rule enforces that elements that do not support ARIA roles, states, and properties (meta,html,script,style) do not haveroleoraria-*attributes.#9306
afd57a6Thanks @viraxslot! - Added thenoNoninteractiveTabindexlint rule for HTML. This rule enforces thattabindexis not used on non-interactive elements, as it can cause usability issues for keyboard users.#9276
6d041d9Thanks @IxxyDev! - Added the HTML lint rulenoRedundantRoles. This rule enforces that explicitroleattributes are not the same as the implicit/default role of an HTML element. It supports HTML, Vue, Svelte, and Astro files.#9813
69aadc2Thanks @ematipico! - Added a new linter configuration calledpreset. With the new option, users can enable different kinds of rules at once.The following presets are available:
"recommended": it enables all Biome-recommended rules, or recommended rules of a group;"all": it enables all Biome rules, or enables all rules of a group;"none": it disables all Biome rules, or disable all rules of a group.You can enable recommended rules:
You can enable all rules at once:
Or enable all rules for a group:
This new option, however, doesn't affect how nursery rules work. Nursery rules must be enabled singularly, due to their nature.
This new option is meant to replace
recommended, so make sure to run themigratecommand.#10022
3422d71Thanks @Netail! - Added the HTML lint rulenoNoninteractiveElementToInteractiveRole, which enforces that interactive ARIA roles are not assigned to non-interactive HTML elements.Invalid:
#8396
13785fcThanks @apple-yagi! - Biome now supports pnpm catalogs (default and named) when resolving dependencies for linting. This behavior is opt-in and requires settingjavascript.resolver.experimentalPnpmCatalogstotrue.#10028
1009414Thanks @Netail! - Added the HTML lint rulenoInteractiveElementToNoninteractiveRole, which enforces that non-interactive ARIA roles are not assigned to interactive HTML elements.Invalid:
#9853
816302fThanks @Netail! - Added the new assist actionuseSortedSelectionSet, which sorts GraphQL selection sets alphabetically, e.g.name, age, idbecomesage, id, name.Invalid:
#10074
9c7c6ebThanks @georgephillips! - Added akindfield to theImportMatcherused by theorganizeImportsassist action. The new field selects imports by their syntactic kind and currently supportsbare(matching side-effect imports such asimport "polyfill") with optional!negation (!bare). The matcher composes with the existingtypeandsourcefields, so users can express patterns such as "only bare imports that import a CSS file" ({ "kind": "bare", "source": "**/*.css" }).For example, with the following configuration:
...the following code:
...is organized as:
#9171
ce65710Thanks @chocky335! - Addedincludesoption for plugin file scoping. Plugins can now be configured with glob patterns to restrict which files they run on. Use negated globs for exclusions.#9617
dcb99efThanks @faizkhairi! - PorteduseAriaActivedescendantWithTabindexa11y rule to HTML.#9496
1dfb829Thanks @aviraldua93! - Added HTML support for thenoAriaHiddenOnFocusableaccessibility lint rule, which enforces thataria-hidden="true"is not set on focusable elements. Focusable elements include native interactive elements (<button>,<input>,<select>,<textarea>), elements withhref(<a>,<area>), elements withtabindex >= 0, and editing hosts (contenteditable). Includes an unsafe fix to remove thearia-hiddenattribute.#9792
f516854Thanks @Maximiliano-Zeballos! - Added theuseSemanticElementslint rule for HTML. The rule now detects the use ofroleattributes in HTML elements and suggests using semantic elements instead.For example, the following code is now flagged:
The rule suggests using
<nav>instead.#9761
cbbb7d5Thanks @Maximiliano-Zeballos! - Ported theuseValidAriaPropslint rule to HTML. This rule checks that allaria-*attributes used in HTML elements are valid ARIA attributes as defined by the WAI-ARIA specification.#9928
aa82576Thanks @aviraldua93! - PorteduseValidAriaValuesto HTML. Biome now validates staticaria-*attribute values in HTML elements against WAI-ARIA types, catching invalid values such asaria-hidden="yes".#10562
6642895Thanks @ematipico! - Promoted 73 nursery rules to stable groups.Four rules were renamed as part of the promotion:
noFloatingClassesis nownoUnusedInstantiation, because the rule checks any discardednewexpression, not only classes.noMultiStris nownoMultilineString.useFindis nowuseArrayFind.useSpreadis nowuseSpreadOverApply, because the rule enforces spread call arguments overFunction.apply(), not array or object spread.Correctness
Promoted the following rules to the
correctnessgroup:noBeforeInteractiveScriptOutsideDocumentnoUnusedInstantiationuseInlineScriptId(recommended, Next.js domain)noVueVIfWithVFor(recommended, Vue domain)useVueValidVBind(recommended, Vue domain)useVueValidVElse(recommended, Vue domain)useVueValidVElseIf(recommended, Vue domain)useVueValidVHtml(recommended, Vue domain)useVueValidVIf(recommended, Vue domain)useVueValidVOn(recommended, Vue domain)useVueValidVText(recommended, Vue domain)useVueValidTemplateRoot(recommended, Vue domain)useVueValidVCloak(recommended, Vue domain)useVueValidVOnce(recommended, Vue domain)useVueValidVPre(recommended, Vue domain)useVueVForKey(recommended, Vue domain)noDuplicateAttributes(recommended)noDuplicateArgumentNames(recommended)noDuplicateInputFieldNames(recommended)noDuplicateVariableNames(recommended)noDuplicateEnumValueNames(recommended)useLoneAnonymousOperation(recommended)Suspicious
Promoted the following rules to the
suspiciousgroup:noShadownoUnnecessaryConditionsnoParametersOnlyUsedInRecursionnoUnknownAttributeuseArraySortComparenoForInnoDuplicatedSpreadPropsnoEqualsToNullnoProto(recommended)noUndeclaredEnvVars(recommended, Turborepo domain)noReturnAssign(default severity:error)noDuplicateEnumValues(recommended)noVueArrowFuncInWatch(recommended, Vue domain)noNestedPromisesnoLeakedRendernoDeprecatedMediaType(recommended)noDuplicateGraphqlOperationNameuseRequiredScriptsStyle
Promoted the following rules to the
stylegroup:useVueMultiWordComponentNames(recommended, Vue domain)useVueDefineMacrosOrdernoIncrementDecrementnoContinueuseSpreadOverApplynoTernarynoMultilineStringnoMultiAssignnoExcessiveClassesPerFilenoExcessiveLinesPerFilenoVueOptionsApiuseErrorCauseuseConsistentEnumValueTypeuseConsistentMethodSignaturesuseGlobalThis(default severity:warn)useDestructuringuseVueHyphenatedAttributes(recommended, Vue domain)useVueConsistentVBindStyle(recommended, Vue domain)useVueConsistentVOnStyle(recommended, Vue domain)noHexColorsuseConsistentGraphqlDescriptionsnoRootTypeuseLoneExecutableDefinitionuseInputNameComplexity
Promoted the following rules to the
complexitygroup:useArrayFindnoRedundantDefaultExport(default severity:warn)noUselessReturnnoDivRegexPerformance
Promoted the following rules to the
performancegroup:noSyncScriptsnoJsxPropsBinduseVueVaporSecurity
Promoted the following rules to the
securitygroup:noScriptUrl(recommended)A11y
Promoted the following rules to the
a11ygroup:noAmbiguousAnchorText(recommended)#10121
450f8e1Thanks @jongwan56! - Biome now applies Git's local exclude file when VCS ignore files are enabled. Files listed in.git/info/excludeare skipped the same way as files listed in.gitignore, including in linked worktrees.#9397
d5913c9Thanks @mvarendorff! - Addedignoreoption to the noUnusedVariables rule. The option allows excluding identifiers by providing a list of ignored names. It also allows excluding kinds of identifiers from this rule entirely, which may be useful when loading classes dynamically.For example, unused classes as well as all unused variables, functions, etc. called "unused" may be ignored entirely with the following configuration:
#10089
71a21f0Thanks @Netail! - Added the lint rulenoLabelWithoutControlto HTML, which enforces that a label element or component has a text label and an associated input.#10015
1828261Thanks @Netail! - Added the HTML lint ruleuseAriaPropsSupportedByRole, which enforces that ARIA properties are valid for the roles that are supported by the element.#10234
1a51569Thanks @ematipico! - Added thedelimiterSpacingformatter option. This option inserts spaces inside delimiters (after the opening delimiter and before the closing delimiter) when the content fits on a single line. Empty delimiters are not affected, and no space is added before the opening delimiter. The specific delimiters affected depend on the language. It can be configured globally viaformatter.delimiterSpacingor per-language viajavascript.formatter.delimiterSpacing,json.formatter.delimiterSpacing, andcss.formatter.delimiterSpacing. Defaults tofalse.JavaScript
When enabled, Biome inserts spaces inside parentheses (e.g.,
foo( a, b )), square brackets (e.g.,[ a, b ]), template literal interpolations (e.g.,${ expr }), and the logical NOT operator (e.g.,! x, but in chains only after the last one:!! x). Only applies when the content fits on a single line. Empty delimiters and the space before the opening delimiter are not affected.JSX
When enabled, Biome inserts spaces inside JSX expression braces (e.g.,
attr={ value }) and spread attributes (e.g.,{ ...props }). Only applies when the content fits on a single line. Empty delimiters are not affected.TypeScript
When enabled, Biome inserts spaces inside TypeScript angle brackets (e.g.,
foo< T >()), indexed access types (e.g.,T[ K ]), mapped types, tuple types, type parameters, and index signatures. Only applies when the content fits on a single line. Empty delimiters are not affected.JSON
When enabled, Biome inserts spaces inside square brackets when the content fits on a single line. Empty brackets are not affected.
CSS
When enabled, Biome inserts spaces inside parentheses and square brackets when the content fits on a single line. Empty delimiters are not affected.
#10461
6bac1c3Thanks @TXWSLYF! - Implements #9445. Added theallowImplicitoption touseIterableCallbackReturn. When enabled, callbacks can usereturn;to implicitly returnundefined, matching ESLint'sarray-callback-returnrule.#9571
5a8eb75Thanks @dyc3! - Added configurable options to theuseNumericSeparatorsrule. Users can now customize the minimum number of digits required before adding separators and the group length for each type of numeric literal (binary,octal,decimal,hexadecimal).#10067
6064312Thanks @Netail! - Added the lint ruleuseFocusableInteractiveto HTML, which enforces elements with an interactive role and interaction handler to be focusable.Invalid:
#10026
fb42ac4Thanks @Netail! - Added the HTML lint rulenoNoninteractiveElementInteractions, which disallows use event handlers on non-interactive elements.Invalid:
#10000
2093e3eThanks @Netail! - Added the new assist actionuseSortedEnumMembers, which sorts TypeScript & GraphQL enum members.Invalid:
#10013
ad01d3dThanks @Netail! - Added the HTML lint ruleuseValidAutocomplete, which enforces using valid values for theautocompleteattribute oninputelements.Patch Changes
#10498
995c1ffThanks @citadelgrad! - Added the nursery ruleuseReactFunctionComponentDefinition, which enforces a consistent function type for named React function components.For example, the following snippet triggers the rule by default.
#9974
ff635a9Thanks @pkallos! - AddedignoreMixedLogicalExpressionsto useNullishCoalescing, partially addressing #9232. When enabled, Biome ignores||and||=mixed with&&in the same expression tree.#10503
c656679Thanks @Mokto! - Added the new nursery ruleuseSvelteRequireEachKey, a Svelte lint rule that reports{#each}blocks with item bindings that are missing a key.#10516
0f29b83Thanks @Dotify71! - AddeduseIncludesto the nursery group. This rule flags comparisons ofString.prototype.indexOf()orArray.prototype.indexOf()against-1and suggests replacing them with the clearerincludes()/!includes()form.#10487
0c03ee3Thanks @Mokto! - Fixed a Svelte parser error that incorrectly required a binding variable after{:then}and{:catch}. Biome now correctly accepts{:then}and{:catch}without a binding, as well as the{#await expr then}and{#await expr catch}shorthand forms.#10566
a4a294cThanks @dyc3! - FixeduseVueHyphenatedAttributes: The rule now only reports diagnostics in Vue files and ignores SVG elements.#10565
72ccf3bThanks @dyc3! - FixeduseVueConsistentVBindStyle: The rule no longer reports argument-lessv-binddirectives because they cannot be converted to shorthand syntax.#10591
6e8557bThanks @xsourabhsharma! - Fixed #10563: Biome now parses comma-separated CSS Modulescomposesvalues, such ascomposes: classA from "./a.css", classB from "./b.css";.#10603
174b21bThanks @denbezrukov! - Fixed CSS formatting forgrid-template-areasdeclarations with comments before multiline values. Biome now keeps grid area rows aligned instead of adding an extra declaration-boundary indent.#10542
c3f07f7Thanks @dyc3! - Fixed #10513: Biome no longer rejects literal\usequences in quoted HTML attribute values.#10108
24e51d6Thanks @IxxyDev! - Fixed #6611:noUnnecessaryConditionsnow uses type information to detect more redundant conditions, including?.,??,||,&&, comparisons againstnull/undefinedon non-nullish operands, andcaseclauses that can never match theswitchvalue.#10568
eb1ed0eThanks @harsha-cpp! - Fixed #10564:useAriaPropsForRoleno longer reports false positives for Vue v-bind shorthand bindings (:aria-checked,:aria-level, etc.).#10570
2ceb4feThanks @Conaclos! - ImprovednoTsIgnore.The rule now reports more precisely the range of the
@ts-ignorecomment.#10520
b55d10fThanks @dyc3! - Fixed #10519: Vuev-onevent handlers with multiple inline statements are now parsed consistently with Vue.#10204
ebbf0bdThanks @ematipico! - Improved the performance of the Biome linter. The improvements are more visible in bigger projects that have more than ~1k files. Early tests showed that in a code base with ~2k files, Biome took less than 26% of time to finish the command.#10546
e39bb2cThanks @tim-we! - Fixed#10536: noUnknownFunction no longer flagged CSScontrast-color()as unknown.contrast-color()is Baseline 2026.#8012
2be0264Thanks @denbezrukov! - Improved the performance of the formatter in some cases. The formatter is now up to ~20% faster at formatting files.#10467
9a5855eThanks @Netail! - Added a new nursery rulenoRestrictedDependencies, which flags imports andpackage.jsondependency entries that have better alternatives in e18e's module replacement data.For example, the package
globbyis reported because there's a better alternative:#10470
84b43c5Thanks @ShaharAviram1! - Fixed #10447: now the rulenoProcessEnvdetects the use ofenvwhen it's imported fromprocessandnode:process.#10556
7ff6b16Thanks @ematipico! - Fixed #10492: Biome no longer crashes with a stack overflow on certain code when a type-aware rule such asnoFloatingPromises,noMisusedPromises, ornoUnnecessaryConditionsis enabled. For example, the following code used to crash Biome:#10532
1da3c75Thanks @denbezrukov! - CSS declarations with comments before:or after!importantnow preserve spaces before:and;.#10491
a1b5834Thanks @Mokto! - Fixed the Svelte parser rejecting{#each}blocks where the binding uses object destructuring with property renaming, e.g.{#each items as { id, component: Filter }}. Biome now correctly parses and formats these rename bindings.#10490
99bc7dfThanks @Mokto! - Fixed the CSS parser rejecting comma-separated selector lists inside:global()and:local()pseudo-class functions. Biome now correctly parses:global(.foo, .bar).#10543
c394faeThanks @mangod12! - Fixed #10477: The RDJSON reporter now emits code replacement text for fix suggestions instead of the human-readable fix description.#10530
e8e1e6aThanks @Conaclos! - Fixed #10493:useImportTypenow correctly separates types from a default named import when all imports are types and thestyleoption is set toseparatedType.#10555
263c7ccThanks @Mokto! - Improved Svelte lint rule accuracy for quoted attribute values containing{expression}interpolations.noRedundantAltno longer emits false positives when the alt text contains an interpolation, e.g.alt="image of {person}".useButtonTypeno longer emits false positives for dynamic button types written astype="{dynamicType}".noScriptUrlno longer emits false positives for dynamic hrefs such ashref="{url}".#10489
96ef9a4Thanks @Mokto! - Fixed Svelte{#each}parser incorrectly rejecting TypeScriptas consttype assertions in the iterable expression. Biome now correctly parses{#each arr as const as item}.#10539
935c59aThanks @dyc3! - Improved how diagnostics print long lines of code, for example minified files where the entire source code is printed in one line.v2.4.16Compare Source
Patch Changes
#10329
ef764d5Thanks @Conaclos! - Fixed an issue where diagnostics showed an incorrect location in Astro files.#10363
50aa415Thanks @dyc3! - Fixed HTML formatting for a case where comments could cause the formatter to split up a closing tag, which would cause the resulting HTML to be syntactically invalid.Input:
Output:
#10465
0c718daThanks @dfedoryshchev! - Fixed diagnostics emitted by thenoUntrustedLicensesrule.#10358
05c2617Thanks @dyc3! - Fixed #10356:biome rage --linternow displays rules enabled through linter domains in the enabled rules list.#10300
950247cThanks @dyc3! - Fixed #10265: Svelte function bindings such asbind:value={get, set}are now parsed more precisely, sonoCommaOperatorwon't emit false positives for that syntax anymore.#9786
e71f584Thanks @MeGaNeKoS! - Fixed #8480:useDestructuringnow providesvariableDeclaratorandassignmentExpressionoptions to control which contexts enforce destructuring, matching ESLint'sprefer-destructuringconfiguration. Both default to{array: true, object: true}. The diagnostic for object destructuring in assignment expressions now instructs users to wrap the assignment in parentheses.#10425
1948b72Thanks @sjh9714! - Fixed #10244: TheuseOptionalChainrule now detects negated guard inequality chains like!foo || foo.bar !== "x".#10442
001f94fThanks @ematipico! - Fixed #10411:noMisusedPromisesno longer causes a stack overflow when a nested function returns an object with shorthand properties that shadow destructured variables from an outer scope.#10318
9b1577fThanks @dyc3! - Added support forformatter.trailingCommasin overrides. This option was previously available in the top-level formatter configuration but missing from formatter overrides.#10319
2e37709Thanks @dyc3! - Fixed Vue and Svelte formatting for standalone interpolations in inline elements. Biome now preserves existing newlines in cases like:#10365
0a58eb0Thanks @Netail! - Fixed #10361:noUnusedFunctionParametersnow mentions the parameter name in the diagnostic.#10439
df6b867Thanks @denbezrukov! - Fixed CSS and SCSS formatting for comments around declaration colons so comments between property names, colons, and values stay at the same boundary as Prettier.#10344
b30208cThanks @siketyan! - Fixed#10123: Corrected thenoReactNativeDeepImportssource rule to point to the proper upstream rule, so users can migrate from the original rule correctly.#10328
b59133fThanks @dyc3! - Fixed #10309: Biome no longer adds newlines to Astro frontmatter when linter or assist--writemode is enabled.haydenbleasel/ultracite (ultracite)
v7.11.1Compare Source
Patch Changes
24b2797: Update oxfmt to 0.67.0 and re-target the markdown:::fence patch to the new dist chunk. The release changes no options; it fixes CSS/SCSS/Less comment preservation and a few JSDoc-cast edge cases in member chains.24b2797: Update oxlint to 1.82.0. The release adds and removes no rules, so the presets are unchanged apart from one new option:no-unmodified-loop-conditionnow runs withcheckConditionalExpressions: truein the oxlint and ESLint core presets, so each branch of a ternary in a loop condition must be modified inside the loop rather than only the expression as a whole.24b2797: Update the ESLint family:@angular-eslint/eslint-plugin22.5,@typescript-eslint/*8.70,eslint-plugin-solid0.18,eslint-plugin-vue10.11,eslint-plugin-jsdoc64.3.8,eslint-plugin-cypress7.0.2,@darraghor/eslint-plugin-nestjs-typed7.5.2 andprettier-plugin-astro1.0. The dynamic presets pick up the seven new rules automatically:@typescript-eslint/no-generated-empty-object-type,@angular-eslint/reactive-context-must-read-signal,vue/no-shadow-native-events, and Solid'sno-boolean-enumerated-attribute,no-store-mutation-outside-setter,no-unused-signalandno-write-in-pure-computation. Note thatprettier-plugin-astro1.0 is a rewrite on the Astro 7 Rust compiler (Node 22.12+); expect whitespace diffs on first run and mirror any customcompressHTMLvia its newastroCompressHTMLoption.24b2797: Refresh the stylelint lock to 17.15.0 and enable its newselector-no-unmatchablerule, which flags selectors that can never match (for examplelabel:checked,::before:first-childor:is(::before)).a71dda4: Stop sorting object keys across the whole TanStack presets, not just route files. TanStack Query mutation options are order-sensitive too: TypeScript infers theonMutatecontext from context-sensitive callbacks in source order, so movingonError/onSettledaboveonMutateturns the context into{}andultracite fixbroke type-correct code (TS2339: Property '...' does not exist on type '{}'). Mutation and query options live anywhere (hooks, components, colocated files), so the route-file exemption could not cover them.ultracite/oxlint/tanstacknow setssort-keystooffandultracite/biome/tanstacknow setsuseSortedKeystoofffor all files.a9db61c: Disablegithub/filenames-match-regexfor file-based route directories (**/routes/**) in the oxlint js-plugins preset, matching the existingunicorn/filename-caseexemption in the TanStack preset. TanStack Router filenames such as__root.tsx,$.tsx, andposts.$postId.tsxno longer fail the GitHub filename rule. Resolves #799.v7.11.0Compare Source
Minor Changes
d5d241f: Addultracite upgrade, and make version drift between Ultracite and its linter visible instead of a crash. Bumpingultracitewithout bumping the linter fails on the nextcheck/fixwith Biome'sFound an unknown keyerror (and the equivalent for ESLint and Oxlint), because each release enables rules from a specific linter version.ultracite upgradeinstalls the latestultracite, prints a release-notes link for the versions you crossed, then hands off to the freshly installed CLI to reinstall your toolchain at the versions that release was verified with: Biome; ESLint, Prettier, Stylelint and the plugins the preset imports; or Oxlint and Oxfmt. Optional extras already in yourpackage.json(framework plugins, Oxlint JS plugins,oxlint-tsgolint) are bumped as well. Config files are never rewritten, and the run ends with the same diagnostics asdoctor.ultracite doctornow checks the installed Biome, ESLint, Prettier, Stylelint, Oxlint and Oxfmt versions against the range this release supports. Too old fails the check and points atultracite upgrade; newer than the verified range only warns.@biomejs/biome ^2.5.0,eslint ^10.0.0,prettier ^3.0.0,stylelint ^17.0.0,oxlint ^1.79.0,oxfmt >=0.40.0.ultracite initnow installs Prettier and Stylelint from those ranges instead oflatest.Requires Biome >= 2.5.0, ESLint >= 10.0.0, Prettier >= 3.0.0, Stylelint >= 17.0.0, Oxlint >= 1.79.0 and Oxfmt >= 0.40.0.
Patch Changes
27d06f2: Update dependencies (@clack/prompts,semver,zod, ESLint plugins).d322691: Defaultultracite initto Oxlint + Oxfmt when--linteris omitted in quiet or non-interactive modec677cf5: Recommend Oxlint + Oxfmt in theultracite initlinter prompt and list it firstc5be848: Disableno-use-before-definein TanStack Router route files for the oxlint tanstack preset. File routes are mutually recursive (Routereferences the component, and the component callsRoute.useParams()), so no declaration order could satisfy the rule.v7.10.8Compare Source
Patch Changes
2a43fdd: Turn offunicorn/prefer-reflect-applyin theultracite/oxlint/anti-sloppreset. When extended afterultracite/oxlint/core, the core rule recommended rewritingFunction#apply()toReflect.apply(), which anti-slop'sno-reflect-applythen rejected, leaving no way to satisfy both. Direct-call guidance for.apply()still comes fromeslint/prefer-spreadandeslint/no-useless-call.03196df: Update@biomejs/biometo 2.5.12. Releases 2.5.10 through 2.5.12 only add nursery rules, which the Biome presets exclude, so the presets are unchanged. The releases also carry linter and formatter fixes, including fewernoUnusedVariablesfalse positives on merged interfaces, namespaces, and overload type parameters, an unsafe-by-default fix fornoThisInStatic, and a large batch of Astro expression parsing fixes.031b867: Update oxfmt to 0.66.0. The 0.65 and 0.66 releases are formatter fixes only, mainly around comment placement between a statement head and its body, suppressed statements (decorators, typecast parens, semicolons), custom side-effect groups insortImports, CommonMark list interruption in JSDoc, and trailing whitespace in YAML block scalars. The:::container-directive fence patch is re-targeted to the new markdown bundle; the patched code itself is unchanged.54affee: Update oxlint to 1.81.0. The 1.80 and 1.81 releases add no rules and remove none, so the presets are unchanged and the peer range stays at ^1.79.0. Notable fixes carried in:no-use-before-definenow runs on JS and JSX files,object-shorthandpreserves__proto__semantics,unicorn/prefer-math-min-maxno longer applies an unsafe autofix, and JS plugin diagnostics with invalid or reversed locations are clamped instead of crashing.0b058d1: Fixultracite fix --codexfailing on recent Codex CLI releases. The Codex adapter invokedcodex exec --full-auto, a flag Codex has since removed, so every attempt failed at argument parsing. It now runscodex exec --sandbox workspace-write, the equivalent non-interactive, workspace-scoped mode, which is also accepted by older Codex versions. Resolves #794.e2346bb: Update the ESLint family to latest: eslint 10.9.1, typescript-eslint 8.69.0, eslint-plugin-unicorn 74, eslint-plugin-solid 0.17, eslint-plugin-jsdoc 64.3.5, eslint-plugin-react-doctor and oxlint-plugin-react-doctor 0.9.13, globals 17.12, and the angular, nestjs-typed, next, tanstack-query, cypress, html, jest and storybook plugins. The dynamic presets pick up the new rules automatically: the solid preset gains the eleven rules added in eslint-plugin-solid 0.16 and 0.17 (removed-api,no-single-arg-create-effect,no-accessor-as-prop,valid-use-server,require-async-server-function,no-invalid-server-capture,no-browser-globals-in-server-function,no-module-scope-reactive-primitive,no-restated-default-options,prefer-onSettled-for-side-effects,prefer-structured-class), which only report Solid 2.0 issues whensettings.solid.versionis set to 2 and stay silent on Solid 1.x code; the nestjs preset gainsforward-ref-injection-should-use-wrapper-type,swagger-file-upload-should-be-documentedanduploaded-file-should-be-validated. The curated jsdoc and react-doctor lists are unchanged. No enabled rule was removed or deprecated, and the ESLint/oxlint parity check still passes.7b0456e:ultracite fixnow runs lint fixes before the formatter: oxlint before oxfmt, and ESLint then Stylelint before Prettier. A fixer can insert unformatted code, such as the bracescurlyadds, the importsconsistent-type-specifier-stylesplits, or the font names Stylelint requotes, and running the formatter first left that code unformatted until the next run. Fixer-inserted code is now formatted in the same run. The--claudeand--codexagent passes follow the same order.unicorn/no-nested-ternaryis now off in the oxlint and ESLint presets: its fixer adds parentheses that oxfmt and Prettier remove, so the two tools rewrote the file on every run. The coreno-nested-ternaryrule still reports nested ternaries.8ddc078: Enable three rules added in Stylelint 17 in the Stylelint preset:selector-no-deprecatedandselector-no-invalidreport selectors that CSS has dropped or that cannot parse, andrelative-selector-nesting-notationis set toexplicit, so nested relative selectors are written& > brather than> b. Theproperty-layout-mappings,unit-layout-mappingsandvalue-keyword-layout-mappingsrules are deliberately left off, since they reject every physical property, unit and keyword and can only autofix with a per-projectlanguageOptions.directionalitysetting. The repo's own Stylelint lock is refreshed from 16.26.1 to 17.14.1, which the config packages already required;ultracite initalready installsstylelint@latestso users are unaffected by the lock change.4609d79: Update the vendoredanti-slopOxlint plugin to upstream v0.1.2 (commite8c4880). The rule set is unchanged; this picks up a round of correctness fixes:no-known-value-wideningnow also reports known values passed into localunknown-typed type predicates,no-object-parameters,no-unknown-parameters,no-unknown-returnsandno-unknown-type-aliasesresolve scoped and transparent generic aliases (including block-scoped aliases and forward references),no-unknown-returnscoversPromiseLike<unknown>,no-unsafe-dictionary-typeallows generic constraints such asT extends Record<string, unknown>,no-runtime-typeofalways allows existence probes against"undefined",no-shape-in-symbol-namesallows static member reads such as Zod'sschema.shape, andrequire-safety-comment-for-type-assertionrejects empty justifications and gains amarkersoption (default["SAFETY"]). Upstream also added a separate opt-inanti-slop-effectplugin for Effect projects, which is not vendored.v7.10.7Compare Source
Patch Changes
15f7ae0: Add support for the Aube package manager:ultracite init --pm aubeis now accepted and projects with anaube-lock.yamllockfile are detected automatically1afc8fe: Re-declare selected Oxlint JS plugins on the root config so dependency analyzers see them.ultracite init --linter oxlint --js-plugins ...now generatesconst jsPlugins = selectJsPlugins([...])and addsjsPlugins: jsPlugins.jsPluginsto the root config (also when the fullultracite/oxlint/js-pluginspreset is extended). Knip only resolvesjsPluginsfrom the root Oxlint config and never walksextends, soeslint-plugin-github,eslint-plugin-sonarjs, andoxlint-plugin-react-doctorwere reported as unused devDependencies. Oxlint dedupes the plugin between the root and the extended preset, so linting is unchanged.Also fix
ultracite updatedropping thejs-pluginspreset fromextendswhen the config used the documentedimport jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"form: the import parser only matched bare default imports. The regenerated full-preset config keepssettings: jsPluginSettingson the root as well.20b06bf: Ignore.alchemyacross all linters and formatters. Alchemy (alchemy.run) writes local state and generated bindings to a.alchemydirectory. It is now part of the shared ignore patterns synced into Biome'sfiles.includesand imported by oxlint, oxfmt, and ESLint, and the Stylelint preset ignores it viaignoreFiles. Prettier needs no change: it already respects.gitignore/.prettierignore.6e9286c: Runlefthook installduringultracite initthrough the same spawn adapter as every other tool invocation instead ofexecSync, so it no longer goes through a shell and gets the same Windows command resolution ashusky, the linters, and editor extension installs.8b24f34: Add support for the Nub package manager:ultracite init --pm nubis now accepted and projects with anub.locklockfile are detected automatically (requires nypm ^0.6.9)240cb6b: Install into the workspace root correctly for Nub and Aube monorepos: nypm emits no root selector for them, sonub addran without-wand was refused. Ultracite now hands nypm pnpm's flag set for these pnpm-compatible CLIs, producingnub add --workspace-root --save-dev ultracite44ecbba: Add Vitest type-test files (**/*.{test-d,spec-d}.{ts,tsx,js,jsx}) to the test-file globs so the shared test relaxations and the Vitest rule overrides apply to them, and enable the Vitest plugin'stypechecksetting in the ESLint preset soexpectTypeOf/assertTypecount as assertions.7ba6bb8: Package the reusable Ultracite agent skill with the npm distribution.v7.10.6Compare Source
Patch Changes
972b946: Update the oxlint presets for oxlint 1.79: replace the removedreact/react-compilerrule with the 22 new React Compiler rules in the react preset, addjsdoc/no-blank-blocksandone-varto the core preset (mirrored in the ESLint presets), and require oxlint ^1.79.02d5bbdb: Declare thejsPluginSettingsnamed export in theultracite/oxlint/js-pluginstype declarations, so the documented (andultracite init-generated)import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"type-checks (#773)56aef65: Refresh the toolchain versions thatultracite initinstalls into projects:@biomejs/biome2.5.9, the ESLint plugin family (including eslint-plugin-cypress 7, eslint-plugin-jsdoc 64, eslint-plugin-solid 0.15, and eslint-plugin-unicorn 73 — the dynamic presets adopt their new rules automatically), andprettier-plugin-svelte4.1.1 /prettier-plugin-tailwindcss0.8.1v7.10.5Compare Source
Patch Changes
8df6ad0: Offer the vendoredanti-slopOxlint preset duringultracite init— it now appears in the JS-plugins prompt when you pick Oxlint, and non-interactive setup accepts it via--js-plugins anti-slop. Selecting it addsultracite/oxlint/anti-slopto the generated config'sextends; since the preset is vendored inside Ultracite, nothing extra is installed.cd229e9: Bump theoxlint-plugin-react-doctorpin from^0.7.1to^0.9.12, soultracite initinstalls the current plugin. All react-doctor rules enabled by the js-plugins presets still exist in 0.9.12, and the ported rules run in curated mode via the settings shipped alongside this release (#771).e1ac886: Pin React Doctor's ported rules to their framework-aware "curated" mode (#771). react-doctor 0.9.x rewrote its ported oxc/react-refresh rules — notablyonly-export-components— with a stripped-down default mode: no framework detection, no route-file skipping, andallowConstantExportoff, so Next.js route-segment exports likeexport const dynamic = "force-static"ormetadatawere flagged as non-component exports in every route file. The ESLint react preset now setssettings["react-doctor"].portedRuleMode: "curated", and generated oxlint configs apply a newjsPluginSettingsexport fromultracite/oxlint/js-pluginson the root config (oxlint does not mergesettingsfrom extended configs, so the setting cannot ride along inside the preset). If you extend the js-plugins preset manually, addsettings: jsPluginSettingsto your root oxlint config.c27fe36: Generate oxlint configs that enable a subset of the JS plugins via a newselectJsPluginsexport fromultracite/oxlint/js-plugins, instead of inlining the filtering logic into the generated file. The inlined block contained atypeofcheck that user-side lint presets flagged (anti-slop/no-runtime-typeof, #770); the generated config is now a one-line extend, is emitted already formatted (including the previously missing blank line after imports), and re-runningultracite initmigrates existing configs with the old inlined block automatically.0616523: Update the vendoredanti-slopOxlint plugin to upstream commit446268e, picking up fixes tono-object-parametersandno-unknown-returns(respect lexical type binders in alias resolution) and a newallowInTypeGuardsoption onno-runtime-typeof. Theultracite/oxlint/anti-sloppreset enablesallowInTypeGuards, sotypeofchecks inside type predicate functions ((x): x is T) no longer need disable comments — predicates are the named-boundary pattern the rule pushes toward (dmmulroy/anti-slop#10).v7.10.4Compare Source
Patch Changes
417a85a: Add an opt-inultracite/oxlint/anti-sloppreset that ships a vendored, self-contained build of the anti-slop Oxlint plugin — fifteen rules that reject low-evidence TypeScript and JavaScript patterns (unjustified type assertions,unknownleaking through signatures,Reflect-based access, module mocking, and more). Extend it alongsideultracite/oxlint/core; nothing extra to install. The preset also turns off two core rules that conflict with anti-slop's widening checks (typescript/consistent-indexed-object-styleandunicorn/no-immediate-mutation) when extended after core.4d3fab8: Movesuspicious/useArraySortComparefrom the Biome core config to the opt-in type-aware config. The rule is in Biome'stypesdomain — it type-infers the receiver of every method call before checking the method name, which madeultracite checkup to ~260x slower on projects with expensive library types (zod, better-auth, Prisma). It now only runs when type-aware linting is explicitly enabled, alongside the other type/project-domain rules. Fixes #768.v7.10.3Compare Source
Patch Changes
a1fa9c4: Replace the hand-rolled packageexportsmap matching in the config-resolution doctor check with the resolve.exports library, which implements Node's fullPACKAGE_TARGET_RESOLVEalgorithm (wildcard patterns, key-order precedence, conditional exports, and array fallbacks). The manualnode_moduleswalk is kept intentionally — it exists to avoid Bun's auto-install cache resolving specifiers the project's ownnode_modulescan't.414ea80: Replace the hand-rolled monorepo workspace scan in framework detection with the find-workspaces library. Workspace declarations from package.json (array and yarn-classic object form) and pnpm-workspace.yaml — including negated globs — are now resolved by the library instead of manual pattern collection and globbing, and lerna/bolt monorepos are picked up as well.a9a1989: Replace the hand-rolled upward directory walks infindNearestFileanddetectLinterwith the empathic library'sfind.any, which checks candidate names in order within each directory before moving to the parent — the same per-directory precedence the previous implementation enforced manually.27b2707: Use magicast to update ESM lint-staged config files duringultracite init. The config is now edited as an AST instead of being imported and re-serialized, so comments and function-valued entries elsewhere in the config survive the update, and the user's config code is no longer executed. If the Ultracite glob pattern is already owned by a non-array value, or the config isn't a mergeable object literal (e.g.defineConfig(...)), init warns and leaves the file untouched instead of rewriting it. CommonJS configs keep the previous behavior.f2529b8: Rewrite the agent-fix progress renderer on top of log-update, cli-truncate, and string-width. log-update now owns the in-place block rewriting that was previously done with manual cursor-up/clear-line escape sequences, and line truncation is measured by display width instead of code units — so lint messages containing emoji or CJK text can no longer overflow the terminal row and corrupt the animated block.277b9d6: Replace the hand-rolled child-process handling in the agent fix runner with execa. The timeout → SIGTERM → grace period → SIGKILL escalation, stderr capture, and spawn-failure handling now use execa'stimeoutandforceKillAfterDelayoptions, which are battle-tested across platforms (including Windows kill semantics the manual implementation didn't cover). Behavior is unchanged: agent runs still time out after 5 minutes, escalate to SIGKILL after a 10-second grace period, and report a capped stderr tail.1614a80: Drop the direct cross-spawn dependency: all synchronous process spawning (linter runs, tool version checks, editor extension installs, skill installs) now goes through a small adapter over execa's sync API, which owns the Windows spawn semantics cross-spawn provided. The adapter preserves the spawnSync result shape (status/signal/error/stdout), always disables shell interpretation, and always decodes output as UTF-8. execa was already a dependency for the agent fix runner, so this consolidates on one process-spawning library.ac114b4: Replace the glob dependency with fast-glob for the tsconfig.json scan during init. fast-glob was already in the dependency tree via find-workspaces, so this drops glob's transitive dependencies (minipass, path-scurry, etc.) from the install without changing behavior.v7.10.2Compare Source
Patch Changes
1c48c68: Enable Tailwind CSS class sorting (sortTailwindcss) in the Oxfmt preset. Classes inclass/classNameattributes and inclsx,cva,tw,twMerge,cn,twJoin, andtvcalls are now sorted using the same algorithm asprettier-plugin-tailwindcss, matching the behavior of the Prettier preset (which always loads the Tailwind plugin) and the Biome preset'suseSortedClassesrule. Projects without Tailwind installed are unaffected beyond class strings being sorted against the default theme, and oxfmt versions older than 0.35.0 ignore the option.dc78be4: Stop sorting TanStack route option keys in route files. TanStack Router's route option types are order-sensitive (head/componentinferloaderDatafrom properties declared before them), so the BiomeuseSortedKeyssource action rewrotecreateFileRouteliterals into an order that breaks type inference (loaderDatabecomesnever). The Biome TanStack preset now disablesuseSortedKeysfor route files, and the oxlint TanStack preset disablessort-keysthere so route files aren't caught between it andreact-doctor/tanstack-start-route-property-order.v7.10.1Compare Source
Patch Changes
d018b7f: Fix several agent fix mode (fix --claude/--codex) issues: runs no longer abort with ENOBUFS when linter JSON output exceeds 1MB, user-supplied format/reporter flags can no longer override the JSON reporter and break parsing, a stuck agent process is force-killed 10 seconds after the timeout instead of hanging forever, and the progress renderer no longer garbles TTY output when file paths and rule names exceed the terminal width.d018b7f: Fix Biome config migration leaving the legacy bare"extends": ["ultracite"]form in place, which breaks Biome's module resolution since the package has no root export. It's now mapped toultracite/biome/core.d018b7f: Fixultracite doctorreporting spurious failures: config checks now walk up parent directories (matchingcheck/fixand the linters themselves) so monorepo packages inheriting a root config pass,.oxlintrc.jsonis accepted as a valid oxlint config (with a migration suggestion), and Prettier/Stylelint configs declared viapackage.jsonkeys are recognized.d018b7f: Fixultracite initcorrupting existing Prettier/Stylelint/ESLint configs by writing an ESM module into JSON/YAML/TOML/CJS config files (e.g..prettierrc,eslint.config.cjs). Updates now write the default.mjsconfig instead and remove the incompatible file so it can't shadow the new one.d018b7f: Fixultracite check/fixmisrouting space-separated flag values (e.g.--max-warnings 10) into the file list, which scrambled the underlying linter invocation and made formatters fail on bogus targets. Positional files listed before a--separator are also kept as lint targets instead of being reclassified as passthrough, which could silently widen formatter runs to the whole project.d018b7f: Fix Lefthook and pre-commit YAML updates silently doing nothing on common config shapes: the Lefthook job is now inserted correctly whenjobs:isn't the first key underpre-commit:(and no longer matches ajobs:key in a different hook),repos: []in.pre-commit-config.yamlis handled, and shapes that can't be safely edited produce a warning instead of writing the file back unchanged.d018b7f: Fix the Husky integration overwriting an existing.husky/pre-commithook:ultracite initranhusky init, which unconditionally replaces the hook withnpm test. It now runs plainhuskyto set up the hooks infrastructure without touching the hook file.d018b7f: Fixultracite initdestroying user files it couldn't parse or merge: unparseabletsconfig.jsonfiles are no longer replaced with a minimal config, unparseable.vscode/.zedsettings are no longer overwritten wholesale, and lint-staged configs with function-valued entries are left untouched — all now warn and skip instead.d018b7f: Fix re-runningultracite initon an oxlint setup silently enabling the full js-plugins preset — the previously selected JS plugins are now preserved when no new selection is made. Init also no longer flips an explicit"type": "commonjs"in package.json to"module"; it warns instead.d018b7f: Fix switching linters removingstorybookfrom the project's dependencies. It was swept into the removal set as a peer ofeslint-plugin-storybook, but it's a user-facing tool a project may use independently of linting.d018b7f: Fix Stylelint target generation dropping directories with a dot in their name (e.g.app.web) and producing non-matching globs from Windows-style backslash paths. Framework detection also handles negated workspace patterns (!packages/legacy) again.d018b7f: Fix the CLI becoming a silent no-op (exiting 0 without linting anything) when a genericTESTenvironment variable is set, as is common in CI matrices. The internal test guard now usesULTRACITE_TEST.36c7b80: Move @typescript-eslint/utils from dependencies to devDependencies. It was accidentally shipped as a runtime dependency in 7.9.0, pulling eslint and the typescript-eslint packages into every consumer's install (including oxlint-only setups) via npm's automatic peer dependency installation. Nothing in the published package imports it — it only exists to support the workspace-internal rule-parity script.v7.10.0Compare Source
Minor Changes
cd0a36c: Add--claudeand--codexflags toultracite fix. After the normal autofix pass, remaining diagnostics are handed to the Claude Code or Codex CLI non-interactively, one agent run per affected file, with a live per-issue spinner that flips to ✓/✗ once the fix is verified by a re-lint. Fixes that don't survive verification are retried (up to 3 attempts per file) with the fresh diagnostics and feedback that the previous approach failed. Works with all three linter modes (Oxlint, Biome, ESLint); exits non-zero if any issues remain, matching the plainfixcontract.e089510: Scope React Doctor's framework-specific rules to per-framework add-on presets (#752)The
ultracite/oxlint/js-pluginspreset no longer enables React Doctor'snextjs-*and TanStack (query-*,tanstack-start-*) rules for every consumer. Rules likenextjs-no-img-elementandtanstack-start-no-anchor-elementfire on plain<img>/<a>JSX and recommend framework replacements, which falsely errored in Vite + React and other non-Next/non-TanStack projects.Those rules now live in two new add-on presets:
ultracite/oxlint/next/js-pluginsultracite/oxlint/tanstack/js-pluginsultracite initwires the matching add-on automatically when you select the framework together withoxlint-plugin-react-doctor. If you manageoxlint.config.tsby hand and use Next.js or TanStack, add the matching add-on preset toextendsalongsidejs-pluginsto keep those rules — or re-runnpx ultracite init.Also fixes re-running
initon a config that already extendsjs-pluginsproducing a duplicateimport jsPluginsdeclaration.Patch Changes
3320cd8: Update Biome to 2.5.6. No stable (non-nursery) rules were added, removed, or promoted between 2.5.3 and 2.5.6, so the preset configs are unchanged.477cd6e: Update ESLint to 10.8.0 and all ESLint plugins to their latest versions. Highlights:eslint-plugin-react-doctor0.9.3: the react preset expands from 149 to 417 rules, adopting the upstreamrecommendedset (react-router, three.js/r3f, ink, motion, remotion, zustand/valtio/mobx, and more) while excluding rules that duplicate already-enabledreact,react-hooks, andjsx-a11yrules. The next preset gainsnextjs-async-dynamic-api-not-awaitedandnextjs-metadata-url-consistency; the tanstack preset gainstanstack-start-missing-scripts,query-floating-mutate-async, andquery-no-mutation-in-effect-as-read.eslint-plugin-unicorn72: addsno-missing-local-resource,no-multiple-promise-resolver-calls,no-shorthand-property-overrides,no-transition-all,no-unnecessary-string-trim,no-useless-re-export,prefer-then-catch, andrequire-frontmatter-fields. CSS-only rules are excluded from the preset since they fail config validation for JS files.eslint-plugin-sonarjs4.2: adds 11 rules includingno-fixed-wait-in-tests,parameterized-tests,assertions-in-test-cases,prefer-native-lodash-alternative, andexplicit-test-skip.typescript-eslint8.65:@typescript-eslint/no-loop-funcand@typescript-eslint/no-restricted-importswere deprecated upstream in favor of the base rules, which now apply to TypeScript files.eslint-plugin-astro3: removesastro/no-omitted-end-tagsandastro/valid-compile.eslint-plugin-svelte3.22: addsno-bind-value-on-checkable-inputsandno-conflicting-module-names;no-restricted-html-elementsis now off because its schema requires a user-supplied element list.@angular-eslint/eslint-plugin22.1: addsinject-at-topandprefer-service-decorator.b81578b: Fix the useSortedPackageJson action not being executed by turning on assist actions for package.json-like files.9ec454a: Update oxlint to 1.76.0 and oxfmt to 0.61.0. New stable rules added to the presets:oxc/bad-match-all-arg,id-denylist,node/exports-style(core),react/function-component-definitionwith arrow-function components (react), andvitest/padding-around-test-blocks(vitest).node/no-top-level-awaitis off — top-level await is idiomatic in ESM, Astro frontmatter, and build scripts — and the ESLint preset'sn/no-top-level-awaitis now off to match. No rules were removed or promoted out of nursery.ba61c02: Fix generated oxlint.config.ts accessing plugin.name on ExternalPluginEntry without narrowing the string form, which caused a TypeScript error in projects that type-check the config (#753)v7.9.4Compare Source
Patch Changes
f480c12: Upgrade Biome to 2.5.3 to fix the LSP scanner deadlock (#10845) where editors get stuck on "Biome is scanning the project".1d70c40: Fail fast with an actionable message when Biome can't resolveultracite/biome/core. Biome resolves that config out of the project'snode_modules, so it errors with an opaque "module not found" whenever Ultracite isn't installed there — a statenpx ultracite check/bunx ultracite checkhide, because they run the CLI from a temp cache regardless.checkandfixnow detect it before invoking Biome and say what's actually wrong, anddoctorverifies that Ultracite resolves rather than just appearing inpackage.json(#750).38d10bc: Move Biome'snoUnknownAttributerule out of the core preset and into thereactpreset. The rule only recognises React's JSX attribute names, so projects using Solid, Svelte, Vue, or Qwik were incorrectly flagged for framework-standard attributes such asclass.cf723bd: Add interactive and non-interactive selection for optional Oxlint JS plugins during init.v7.9.3Compare Source
Patch Changes
dc6d760: Disable then/no-unpublished-importrule in the ESLint core config. This rule flags imports of packages that aren't listed as published dependencies, but it produces a lot of false positives in practice, so it's now turned off.15ecfba: Fixultracite init --linter eslintinstalling an unusable toolchain. The generated ESLint config importseslint-plugin-storybookunconditionally (which requires thestorybookpeer) and the generated Stylelint config extendsstylelint-config-standard/stylelint-config-idiomatic-order/stylelint-prettier, but none of those packages were installed — so a fresh ESLint setup failed to load with "Cannot find package 'storybook'" or "Could not find stylelint-config-standard". These four packages are now installed with the ESLint linter.2f73a41: Upgrade to oxlint 1.73.0 and oxfmt 0.58.0, and enable the new lint rules they introduce:no-unreachable-loop,unicorn/explicit-timer-delay, andunicorn/no-confusing-array-with.83b2783: Add an[astro]formatter mapping (astro-build.astro-vscode) to the oxlint VS Code editor settings generated byultracite init, since oxfmt doesn't format.astrofiles.d186c53: Move every JS-plugin-based rule set out of the Oxlint core and framework presets and into a single opt-inultracite/oxlint/js-pluginspreset. This coverseslint-plugin-githubandeslint-plugin-sonarjs(previously in core) as well asoxlint-plugin-react-doctor(previously bundled into thereact,next, andtanstackpresets). The core,react,next, andtanstackpresets now run entirely on Oxlint's native Rust rules, so new setups no longer install those dependencies and no longer pay the slower JS-plugin lint pass. To keep the extra ESLint-parity and React Doctor rules, installeslint-plugin-github,eslint-plugin-sonarjs, andoxlint-plugin-react-doctorand extendultracite/oxlint/js-pluginsalongsidecore(and your framework preset).057753e: Add performance benchmarks forultracite check/ultracite fixacross all three providers (oxlint, biome, eslint). A new CI job builds the PR and its base branch on the same runner, benchmarks them interleaved, and fails on a statistically significant regression (median ratio > 1.25x with Mann-Whitney U p < 0.05) so config changes can't silently slow the linters down again.v7.9.2Compare Source
Patch Changes
c335a1f: Add**/node_modulesand**/.gitto the shared ignore patterns. oxlint only skipsnode_moduleswhen a.gitignorelists it, so in projects without one,ultracite fixwould lint and autofix files insidenode_modules— corrupting installed packages (e.g. rewritingvarenum wrappers intypescript/lib/typescript.jsto self-referencingconst, causing "Cannot access 'Comparison' before initialization" when oxlint loads eslint-plugin-sonarjs). Fixes #737.v7.9.1Compare Source
Patch Changes
ecd10cc: Disablesonarjs/no-implicit-dependenciesandgithub/no-implicit-buggy-globalsin the oxlint and ESLint presets. Both produce false positives through oxlint's JS plugin bridge:no-implicit-dependencieshas no dependency-manifest resolution so it flags builtin (bun:test) and workspace imports as missing dependencies, andno-implicit-buggy-globalsmisreads module-scoped declarations such as Astro frontmatter as implicit globals.c76f59d: Disablesonarjs/file-name-differ-from-classin the oxlint and ESLint presets. It fires on any file whose name differs from an exported class, which is noise for the many config and module files that export objects rather than classes.29e30ce: Fold the github and sonarjs rules into the oxlint core preset. The standaloneultracite/oxlint/githubandultracite/oxlint/sonarjspresets are removed — ultracite ships framework presets, not individual plugins. Their rules now live inultracite/oxlint/core, so every oxlint setup gets eslint-plugin-github and eslint-plugin-sonarjs through oxlint's JS plugin bridge, matching how the ESLint preset already bundles them into core.This is a breaking change to generated configs:
ultracite/oxlint/githubandultracite/oxlint/sonarjsno longer exist. Re-runultracite initto regenerateoxlint.config.ts.Also fixed: nine sonarjs rules (
async-test-assertions,hooks-before-test-cases,no-duplicate-test-title,no-empty-test-title,no-floating-point-equality,no-forced-browser-interaction,no-trivial-assertions,prefer-specific-assertions,super-linear-regex) that exist in eslint-plugin-sonarjs but that oxlint's JS plugin bridge does not register. Naming them made oxlint hard-fail config parsing, which brokeultracite fix/checkfor oxlint projects using the sonarjs preset. They are omitted from oxlint core (still enabled in the ESLint preset), and a test now runs oxlint against core to catch this class of regression.The React Doctor, github, and sonarjs plugins are installed into your project's devDependencies at init (as the ESLint plugins already were), rather than bundled as dependencies of ultracite — oxlint resolves JS plugin specifiers from the project root, so they must be installed there directly.
8a4291f: Upgrade to Oxlint 1.72.0 and Oxfmt 0.57.0. Oxfmt 0.57 adds native CSS and GraphQL formatters. The five new non-nursery Oxlint rules from the 1.71/1.72 releases are already covered by the presets (node/no-sync,node/no-mixed-requires,unicorn/prefer-number-coercion,unicorn/max-nested-calls,vue/no-async-in-computed-properties). The markdown:::container-directive fence patch (which keepsproseWrap: "never"from folding fences into prose) was regenerated against the 0.57 bundle.v7.9.0Compare Source
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, includingnoShadow,noUnnecessaryConditions,noUnusedInstantiation(formerlynoFloatingClasses),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 theunicornrulesexplicit-length-check,max-nested-calls,no-process-exit,prefer-global-this,prefer-string-raw,prefer-top-level-await);consistent-type-definitionsnow enforcesinterfaceinstead oftype, matching oxlint and Biome;no-voidallows statement position to coexist withno-floating-promises;import-x/no-named-as-defaultis enabled; andcurlyandno-unexpected-multilineare re-enabled pasteslint-config-prettier. Biome:noAwaitInLoopsandnoIncrementDecrementare now errors and theuseSortedKeysassist is on (matchingno-await-in-loop,no-plusplus, andsort-keysin the other presets), whileuseGlobalThisis off (matchingunicorn/prefer-global-this).73c1993: Require ESLint 10 for ESLint setups. The plugin suite upgrade (notablyeslint-plugin-unicorn70 andeslint-plugin-astro2) requires ESLint 10, butultracite initstill installedeslint@^9.0.0, which crashed at config load time. Init now installseslint@^10.0.0and@eslint/js@^10.0.0, and the presets are fixed for ESLint 10 compatibility:settings.react.versionis pinned to19.0.0instead of"detect"(detection uses an API removed in ESLint 10),react/jsx-filename-extensionandreact/forward-ref-uses-refare disabled (their implementations use removed APIs; the former is already off in the oxlint preset and the latter is covered byreact-doctor/no-react19-deprecated-apis), the react config re-applieseslint-config-prettierso JSX formatting rules stay off (several crash under ESLint 10), andimport-x/no-unused-modulesis 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: Addeslint-plugin-jsdocto 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 byultracite initfor 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 therequire-*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-unicorn64 → 70 (adds a large batch of new correctness and quality rules),eslint-plugin-astro1 → 2 (addsno-omitted-end-tags, now requires ESLint 10),eslint-plugin-sonarjs4.0 → 4.1 (adds test-assertion and ReDoS rules likesuper-linear-regex),eslint-plugin-svelte3.19 → 3.20 (addsno-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(sinceTemporalstill lacks broad runtime support) andno-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) andultracite/oxlint/sonarjs(eslint-plugin-sonarjs, 187 rules — type-aware rules are excluded since the JS plugin bridge provides no type information, andno-reference-erroris off because the bridge provides no globals).ultracite initnow adds both presets to generated oxlint configs and installs the two plugins; existing configs are untouched until the nextinit, and either preset can be dropped fromextendsto 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 disablessonarjs/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 withsort-keys), andgithub/no-dataset(conflicts withunicorn/prefer-dom-node-dataset), and setssonarjs/cognitive-complexityto 20 to match Biome'snoExcessiveCognitiveComplexity. Switching linters withinitno 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 (theoxlint --rulesmarkdown 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, andunicorn/prefer-single-call. ESLint preset fixes that fell out of the audit:no-loss-of-precisionandno-duplicate-importsare re-enabled for TypeScript files (their@typescript-eslinttwins were removed in v8, leaving TS uncovered),no-duplicate-importsgetsallowSeparateTypeImportsto match oxlint, the react/vue configs now only re-apply thereact/-vue/-prefixed entries ofeslint-config-prettierso they can't clobber unrelated rules, the svelte preset keeps the formatting rules disabled thateslint-plugin-svelte's own prettier preset lists, andastro/semiis off (Prettier owns formatting). A newcompare-rule-parityscript runs as part ofvalidate: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 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 — viaeslint-plugin-react-doctorand theoxlint-plugin-react-doctorJS plugin. Rules that React Doctor ports fromeslint-plugin-react,eslint-plugin-react-hooks, andeslint-plugin-jsx-a11yare 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. Runningultracite initnow removes config files and dependencies for unselected Biome, ESLint/Prettier/Stylelint, or Oxlint/Oxfmt setups before writing the selected toolchain config.e24068b: Sortpackage.jsonkeys when using Biomev7.8.4Compare Source
Patch Changes
e4ddd22: Ignore.yarndirectories by defaulta1d5c06: Configure Oxfmt to never wrap prose (proseWrap: "never")df709a4: Ignore.wranglerand.wrangler-dry-runoutput directories by defaultv7.8.3Compare Source
Patch Changes
c863d09: Fix automatic editor extension installation duringultracite init.The whole command line (e.g.
code --install-extension) was passed tospawnSyncas the executable name, which always failed withENOENTandsilently fell back to the "install manually" message. The command is now split
into the binary and its arguments, so the linter extension actually installs
for VS Code-based editors.
6888129: Enable theeslint/no-await-in-looprule as an error in the core Oxlintpreset.
Awaiting inside a loop forces each iteration to run sequentially, which can
lead to serious performance issues when the asynchronous operations could
otherwise run concurrently. Promoting this rule to an error encourages
collecting promises and resolving them together (e.g. with
Promise.all)instead of blocking on each one in turn.
62a9b5c: Fix the generated Husky pre-commit hook's error handling and sectionreplacement.
The standalone hook script set
set -eand then tried to capture theformatter's exit code, re-stage files, and print a failure message — but a
non-zero formatter exit terminated the script immediately, so none of that
ever ran. The script now captures the exit code with
|| FORMAT_EXIT_CODE=$?so files are re-staged and failures are reported with the right exit code.
Re-running
ultracite initalso deleted everything from the# ultracitemarker to the end of the hook, including commands the user added after the
ultracite section. The section is now terminated with an explicit
# ultracite endmarker and updates replace only the section between themarkers (legacy sections without an end marker are detected by their closing
echo line).
6608ceb: Make the lint-staged integration idempotent and respect dedicated configfiles.
package.jsonwas always treated as the lint-staged config because the fileexists in every project, so
ultracite initwrote the lint-staged config intopackage.jsoneven when a dedicated.lintstagedrc.*orlint-staged.config.*file was present — leaving two conflicting configs.package.jsonnow only counts when it actually has alint-stagedkey;otherwise the dedicated config file is updated (or
.lintstagedrc.jsoniscreated).
Re-running
ultracite initalso appended anothernpx ultracite fixentry onevery run because the merge concatenates arrays. Updates are now skipped when
the existing config already references ultracite.
4e847f7: Insert--before script arguments in npm hook commands.The post-edit hook command generated for npm projects was
npm run fix --skip=correctness/noUnusedImports, where npm consumes the--skipflag itself instead of forwarding it to the script — so agent hooksran a plain
ultracite fix, including the unused-import removal the flagexists to prevent mid-edit. The generated command is now
npm run fix -- --skip=correctness/noUnusedImports, matching the documentedform.
ecb0d5b: Scope the Stylelint step ofultracite checkandultracite fix(ESLint mode)to style files.
Stylelint was previously given the same targets as ESLint and Prettier (or
.when no files were passed), so it tried to parse
.ts/.jsonfiles as CSS andfailed with
CssSyntaxError. Style files now pass through unchanged, directorytargets become
**/*.{css,scss,sass,less}globs, other files are dropped, andthe step is skipped entirely when no style targets remain.
--allow-empty-inputis passed so projects without CSS still succeed.61ea0a1: Fix the project-path write guard's error message and ordering.The "Refusing to write through directory outside project" error interpolated
the
node:pathmodule instead of the offending file path, printing[object Object]. It now reports the actual path.writeProjectFilealso created directories (mkdir -p) before running thepath-escape check, so directories could be created outside the project before
the guard threw. Validation now happens first; the parent-directory check
resolves the nearest existing ancestor so writes into not-yet-created nested
directories still work.
v7.8.2Compare Source
Patch Changes
30971a8: Enable newly available Oxlint and Stylelint rules in the shared configs.For Oxlint, the core preset now enables
eslint/prefer-named-capture-group,jsdoc/require-yields-description,node/callback-return,typescript/method-signature-style, andunicorn/import-style.The Vue preset now enables
vue/component-definition-name-casing,vue/no-computed-properties-in-data,vue/no-deprecated-props-default-this,vue/no-expose-after-await,vue/no-reserved-component-names,vue/no-shared-component-data,vue/no-watch-after-await,vue/require-prop-type-constructor,vue/require-render-return,vue/require-slots-as-functions,vue/return-in-emits-validator,vue/valid-define-options, andvue/valid-next-tick.The Stylelint preset now enables
display-notationwith theshortoption.v7.8.1Compare Source
Patch Changes
8335be7: Build the CLI withbun buildand atsgotype-check gate instead of tsup.f747449: Fix the Oxlint TanStack preset so route files underroutes/andapp/routes/are exempt fromunicorn/filename-case, matching the documented 7.8.0 behavior.092597e: Fix generatedoxlint.config.tsto be pre-formatted according to oxfmt rules, soultracite checkpasses immediately afterultracite initwithout requiring a separate format step.81da6e8: Generate agent and editor hook commands through nypm's package-manager script helper.81da6e8: Keep hyphen-prefixed file operands from being forwarded to linters as options.astral-sh/uv (uv_build)
v0.12.13Compare Source
Released on 2026-09-10.
Python
Enhancements
Preview features
tyexclusions whenuv checkautomatically selects members of a virtual workspace (#21555)Performance
Bug fixes
core-metadataover legacy aliases in JSON index responses (#21563)v0.12.12Compare Source
Released on 2026-09-09.
The executables in our macOS and Windows release archives and
uvanduv_buildwheels are now code-signed. macOS executables are signed with an Apple Developer ID certificate and notarized by Apple. Windows executables have timestamped Authenticode signatures from Azure Artifact Signing. This enables verification of the release publisher and binary integrity, supports publisher-based allowlisting, and should reduce security warnings and antivirus false positives.Bug fixes
exclude-newercutoff from lockfiles and generated requirement hashes (#21539)v0.12.11Compare Source
Released on 2026-09-08.
Preview features
pylock.tomlfiles to ensure they conform to PEP 751 (#20146)pylock.tomlartifact hash tables are empty, which will be rejected in a future uv release (#21462)Performance
uv pip install --no-depsfinds the requested packages already installed (#21523)Bug fixes
uv.lockbefore reading their metadata or running their build backends (#21223)===under both--verify-hashesand--require-hashes(#21543).python-versionand.python-versionsfiles (#21529)VIRTUAL_ENVmismatch warnings foruv add --no-sync,uv remove --no-sync, anduv add --frozen(#21496)uv python listcannot query an interpreter (#21498)Documentation
exclude-newerexamples (#21534)v0.12.10Compare Source
Released on 2026-09-04.
Enhancements
uv publishcompletes, including when publishing fails (#21423)Preview features
exclude-newer-packagesettings for packages outside the resolution fromuv.lockwith themissing-exclude-newer-package-lockpreview feature (#21455)uv tree --invertoutput (#21404)Performance
uv publishby hashing each artifact in a single blocking task and reusing the buffer across reads (#21389)Bug fixes
--lockedfrom failing whenexclude-newer-packagesettings differ only for packages outside the resolution (#21454)uv lock --checkto reuse a lockfile when an absoluteexclude-newercutoff is moved later (#19571)uv lock --checkto reuse a lockfile when a package-specificexclude-newercutoff is disabled (#21450)--namewhenuv initwould infer a project name reserved for a Python interpreter (#21395)exclude-newercutoffs touv.lockin a deterministic order (#21453)v0.12.9Compare Source
Released on 2026-09-01.
Python
Enhancements
--no-lockedand--no-frozento disable lock modes enabled byUV_LOCKEDandUV_FROZENfor a single invocation (#21408)Performance
Bug fixes
async_http_range_readerto 0.11.1 to address a potential memory-safety issue when reading metadata ranges from untrusted wheels (#21401)--locked,--frozen,--check, and--check-existsprecedence over conflictingUV_LOCKEDandUV_FROZENvalues (#21396)v0.12.8Compare Source
Released on 2026-08-31.
Enhancements
uv tool upgrade --all(#21368)Preview features
content-addressed-cachepreview feature (#21327)Performance
Bug fixes
--require-hashes(#21348)sig) query parameters from displayed URLs (#21360)Other changes
astral-tokio-tarto 0.7.0 and use effective sizes when tracking extracted hard links (#21346)v0.12.7Compare Source
Released on 2026-08-27.
Python
Enhancements
s390x,ppc64le, andloongarch64targets for cross-platform dependency resolution (#21313)UV_AZURE_ENDPOINT_URL(#21318)Preview features
content-addressed-cachepreview feature (#19693)Bug fixes
Other changes
v0.12.6Compare Source
Released on 2026-08-25.
Python
Enhancements
uv_buildrequirements to source-distribution builds (#21078)Preview features
uv workspace metadata --sync --exactto remove packages outside the selected resolution (#21117)artifact-hash-filteringpreview feature to makeuv pip compile --generate-hasheshonor--only-binaryand--no-binary(#21235)exclude-newercutoffs whenuv checkselects itstyexecutable (#21227)tar-codecsource-distribution errors when the base interpreter is outside abindirectory (#21146)Performance
Bug fixes
uv buildand non-editable first-party workspace packages whenno-buildis enabled (#21294)uv tool upgradewhen the tool receipt references the same index (#21275)uv sync(#21264).pyas local script paths (#21144)cache-keysentries (#21137)Other changes
v0.12.5Compare Source
Released on 2026-08-14.
Python
Enhancements
Preview features
--indexand--default-indexto select configured package indexes by name with theindex-by-namepreview feature (#17455)cache-physical-spaceon filesystems that do not support physical-space accounting (#21133)Bug fixes
v0.12.4Compare Source
Released on 2026-08-13.
Enhancements
Requires-Python: >= 3.5.*(#21012)Preview features
uv check --no-install-projectand respectUV_NO_INSTALL_PROJECTto install dependencies without building or installing the project (#21085)uv checkhonor uv's color and progress settings, including quiet mode (#21086)Performance
Bug fixes
pythonw.exelaunchers for virtual environments created from managed Python minor-version links (#19235)uv lockto proceed when.venvis an unusable project environment (#21068)fork-strategywhen ordering forks created fromenvironmentsor existing lockfileresolution-markers(#21000)!=3.11.*, !=3.12.*inuv.lock(#21045)uv addupdates it (#21008)PYTHONEXECUTABLEand__PYVENV_LAUNCHER__overrides (#21075)uv version --bumpvalues (#21076)v0.12.3Compare Source
Released on 2026-08-07.
Python
Preview features
--output-formatto select automatic, human-readable, or raw-byte output foruv cache size(#20992)uv workspace metadata --quietwhile suppressing diagnostics (#20991)uv workspace metadataJSON output (#20990)Performance
Documentation
--python-pinto--pin-pythonin theuv init --bareexample (#20876)v0.12.2Compare Source
Released on 2026-08-05.
Python
Enhancements
Preview features
uv tool audit(#20921)cache-physical-spacepreview feature (#20925)Configuration
UV_RUN_RLIMIT_NOFILEto set the open-file limit for commands launched byuv run(#20926)Performance
uv.lockparsing for wheel entries (#20881)uv.lockparsing for source distribution entries (#20882)Bug fixes
Documentation
v0.12.1Compare Source
Released on 2026-09-15.
This release fixes a regression in 0.12.14 that lead to rejecting valid installation commands such as using
uv pip install --systeminpython:*docker images or when usinguv pip install --target .. (#21699)Performance
Bug fixes
v0.12.0Compare Source
Released on 2026-07-28.
Since we released uv 0.11.0 in March, we've accumulated changes that improve correctness, safety, and compatibility with specifications, but could break some workflows. This release contains those changes; many have been marked as breaking out of an abundance of caution.
We expect most users to be able to upgrade without making changes.
There are no breaking changes to the configuration of the uv build backend. If your
[build-system]table includes an upper bound onuv_build, update it to allowuv_build0.12, e.g.,uv_build>=0.11.32,<0.13.Breaking changes
Define build systems by default with
uv init(#19197)Projects created with
uv initnow declare a build system and are packaged by default. This was the default project layout all the way back in v0.3, but we found that the use of thehatchlingbuild system was confusing to newcomers and consequently dropped use of a build system by default in v0.4. Since then, we've created our own build system (uv_build) with tight integration with uv and are excited to restore the default to a best-practice project layout.Previously,
uv init examplecreated an unpackaged layout containingmain.pyand apyproject.tomlwithout a build system. The project could declare dependencies but was not itself installed into its virtual environment.Now,
uv init exampledefines a[build-system]usinguv_build, places application source code insrc/example, and includes a[project.scripts]entry namedexample. Defining a build system allows the project to be imported from tests or other code, installed as a dependency, and run as a command:Existing projects are unaffected. Use
uv init --no-package exampleto create the previous unpackaged layout without a build system.See the project creation documentation for more details.
This stabilizes the
packaged-initpreview feature.Reject unsupported source distribution and wheel archive formats (#18927)
PEP 625 requires source distributions to use
.tar.gzarchives. Previously, uv also accepted legacy formats such as.tar.bz2and.tar.xz. Those formats are now rejected, including when referenced by an existing lockfile. Legacy.zipsource distributions remain supported for backwards compatibility.Wheels and other ZIP archives can no longer contain entries compressed with bzip2, LZMA, or XZ. Entries must use the stored, DEFLATE, or zstd compression methods.
Removing support for uncommon compression methods reduces uv's compression dependencies and the attack surface exposed when processing untrusted packages.
You cannot opt out of this behavior. If you depend on a legacy source distribution that uses an unsupported format, we recommend rebuilding it as a
.tar.gzarchive and regenerating any lockfile containing references to the legacy archive.Reject wheel files that could replace the Python interpreter (#20748, #20749)
uv already rejected wheel entry points named
python, but case variants such asPythonwere still accepted. On case-insensitive filesystems, including common macOS and Windows setups, these entry points could overwrite the virtual environment's interpreter.Wheels could also place interpreter files in their
.data/scriptsdirectory or in paths such as.data/data/bin/python, bypassing the entry-point check and replacing the interpreter during installation.uv now rejects case-insensitive variants of reserved interpreter names and wheel data files that would be installed over an interpreter. This includes names such as
Python,python.py, andPython.exe, along with other reserved interpreter names and their versioned variants.You cannot opt out of these checks. Rename conflicting entry points or wheel data files and rebuild the affected wheel.
Prefer stable releases before falling back to pre-releases (#19993)
A dependency can introduce a pre-release requirement after resolution starts. uv previously required each package's pre-release eligibility to be known before resolution began: the default
if-necessary-or-explicitmode allowed them for direct requirements that explicitly requested a pre-release, or for packages that only published pre-releases.This meant that a pre-release requirement discovered in a dependency's metadata, e.g.,
example>=2.0.0b1, would fail to resolve even when a compatible pre-release existed. To resolve it, you had to add that dependency as a direct requirement or allow pre-releases across your entire dependency graph.The default mode is now
if-necessary. uv tries stable candidates first and falls back to pre-releases when no stable candidate satisfies the active constraints. Like pip, uv now supports pre-release requirements discovered transitively, but can select different versions than previous uv releases when both stable and pre-release candidates are available.You can opt out of automatic pre-release selection with
--prerelease disallow. Alternatively,--prerelease allowconsiders pre-releases without first preferring stable releases, and--prerelease explicitonly allows them for direct requirements that mention a pre-release.The old
if-necessary-or-explicitmode distinguished between explicitly requested pre-releases and packages with no stable releases. That distinction is unnecessary now thatif-necessaryhandles both cases, including transitive requirements. The old name remains available as an alias but is deprecated and will be removed in a future release.Respect
--require-hashesdirectives inrequirements.txt(#19336)Previously,
uv pip installanduv pip syncwarned about--require-hashesinside arequirements.txtfile but still installed dependencies without checking their hashes. Now, the directive enables hash-checking mode, just as if--require-hasheshad been passed on the command line.For example, this requirements file is no longer accepted because the requirement is neither pinned nor hashed:
You cannot opt out while the directive is present. Pin every requirement with
==and provide its hash, or remove--require-hashesif hash checking is not intended.Reject MD5-only hashes in hash-checking mode (#20758)
Previously,
uv pip install --require-hashesanduv pip sync --require-hashesaccepted requirements whose only available digest used MD5. MD5 is not collision-resistant, so relying on it undermined installations that require hash verification and differed from pip's behavior.Hash-checking mode now requires at least one secure digest for every requirement. For example, the following requirement is rejected unless a secure hash, such as SHA-256, is also supplied:
A secure hash can be supplied directly on the requirement or in a matching constraints file. Ordinary hash verification without
--require-hashescontinues to support MD5.You cannot opt out while hash checking is required. Regenerate affected hashes with SHA-256 or another supported secure hash.
Reject invalid
pylock.tomlfiles and artifacts (#20402, #20440, #20443)uv now validates additional requirements from the
pylock.tomlspecification:packagesarray must be present. Previously, uv interpreted a missing array as an empty lockfile, souv pip synccould uninstall an environment instead of rejecting malformed input. An explicitly emptypackages = []array remains valid.pylock.tomlor a single-name variant such aspylock.dev.toml. Names such aspylock..tomlandpylock.foo.bar.tomlare rejected.size, the downloaded or cached artifact must match. Previously, an incorrect size was accepted when the hash was correct. Sizes reported by package indexes remain advisory.You cannot opt out of these checks. Regenerate malformed lockfiles, rename invalid filenames, and either correct or remove an incorrect optional
sizevalue.Honor explicit certificate overrides even when no certificates can be loaded (#20741, #20767)
Previously, uv ignored
SSL_CERT_FILEorSSL_CERT_DIRvalues that pointed to missing or inaccessible paths, empty files or directories, or sources without valid certificates. Instead, it fell back to its default trust roots, potentially allowing HTTPS connections that the configured override was intended to reject.Now, any non-empty
SSL_CERT_FILEorSSL_CERT_DIRvalue replaces uv's default certificate roots, even when no valid certificates can be loaded. In that case, HTTPS requests fail because no certificates are trusted. This applies to package downloads and remote scripts, including GitHub Gists.Fix or unset the certificate override. Unsetting it restores the default trust store; empty environment-variable values continue to be ignored.
Support pip-compatible
--certhandling inuv pip(#20418)The
uv pipinterface now accepts--cert <path>, e.g.:As in pip, the provided PEM bundle replaces all other certificate sources for that invocation, including system certificates and
SSL_CERT_FILEorSSL_CERT_DIR. This change has no effect unless you pass--cert. Include the necessary certificate authorities in the bundle.--certis only supported byuv pipcommands; other uv commands continue to use their existing certificate configuration.Discover projects relative to the script passed to
uv run(#20225)Previously,
uv run project/script.pydiscovered its project from the current directory, even when the script belonged to another project. uv now starts project and workspace discovery from the script's directory instead.For example, running
uv run other-project/script.pynow usesother-projectand its dependencies. This fixes scripts that previously failed because their own dependencies were not installed, but can select a different environment than before.You can opt out of script-relative discovery by selecting a project explicitly, e.g.,
uv run --project . other-project/script.py.This stabilizes the
target-workspace-discoverypreview feature.Require
--forcebefore clearing a directory that is not a virtual environment (#20225)uv venv --clearpreviously removed any existing target directory, even if it was not a virtual environment. uv emitted a warning but still deleted the directory and its contents. Now, uv refuses to clear directories that do not contain a virtual environment.You can opt out of this safety check by explicitly passing
--force, e.g.,uv venv --clear --force ./not-a-virtualenv.This stabilizes the
venv-safe-clearpreview feature.Reject
--projectwhen initializing a project (#20225)--projectselects an existing project, so it is not meaningful when initializing a new one. Previously,uv init --project examplewarned and initializedexampleanyway; if a positional path was also provided,--projectwas ignored.This usage is now an error. Use
uv init exampleto initialize a project at the requested path, oruv init --directory exampleto change the working directory first.This stabilizes the
init-project-flagpreview feature.Reject missing or invalid
--projectpaths (#20225)uv previously warned when
--projectreferred to a missing directory or a file other thanpyproject.toml, but then attempted to continue. This could produce confusing errors later or run against an unintended project.Now,
uv run --project missing pythonfails immediately instead of continuing. You cannot opt out of this behavior. Create the directory first or select an existing project. Passing--project path/to/pyproject.tomlremains supported and selects the file's parent directory.This stabilizes the
project-directory-must-existpreview feature.Skip distributions with non-normalized filenames when publishing (#20225)
Distribution filenames must use normalized package names and versions. For example, a wheel for version
1.01.0should be namedexample-1.1.0-py3-none-any.whl, notexample-1.01.0-py3-none-any.whl.Previously,
uv publishwarned about non-normalized filenames but still attempted to upload them. It now skips the affected wheels and source distributions instead.You cannot opt out of this behavior. Rebuild distributions with normalized filenames before publishing.
This stabilizes the
publish-require-normalizedpreview feature.Classify Conda environments named
baseandrootby their paths (#20225)Conda environments named
baseorrootwere previously assumed to be the base Conda environment, even when they were ordinary child environments. uv now recognizes child Conda environments namedbaseorrootbased on their paths, as it already does for other names.You can opt out of automatic interpreter selection by requesting an interpreter explicitly with
--python /path/to/python.This stabilizes the
special-conda-env-namespreview feature.Reject broken
.venvsymlinks during environment discovery (#20433)Previously, uv could ignore a broken
.venvsymlink and continue searching parent directories for another virtual environment. As a result, commands such asuv pip installcould unexpectedly modify an unrelated ancestor environment.uv now stops at a broken
.venvsymlink and reports its exact path. Errors encountered while reading virtual environment metadata, including permission failures, are also reported immediately instead of being ignored.You cannot opt out of this behavior. Repair or remove the broken
.venvsymlink and correct any permissions that prevent uv from inspecting the environment.Reinstall matching installed Python patch versions instead of upgrading implicitly (#20659)
Before Python upgrades were supported,
uv python install 3.12 --reinstalldoubled as a way to install the latest Python 3.12 patch release. Now that--upgradeis available,--reinstallreinstalls the matching patch releases that are already present.For example, if Python 3.12.6 and 3.12.7 are installed,
uv python install 3.12 --reinstallreinstalls both versions instead of installing the latest available 3.12 release.You can recover the previous upgrade behavior with
uv python install 3.12 --upgrade. Combine--upgrade --reinstallto reinstall only the latest patch.Require
--upgrade-groupto name an existing dependency group (#18957)Previously,
uv lock --upgrade-group docssilently succeeded even if nodocsdependency group existed. uv now validates the requested group against the project, its workspace members, and workspace-level dependency groups.You cannot opt out of this behavior. Correct the group name or add it to
[dependency-groups]. Legacytool.uv.dev-dependenciesstill satisfies--upgrade-group dev.Resolve relative indexes and find-links against
--directory(#20740)The
--directoryoption changes the directory in which uv operates. Previously, relative index and find-links paths supplied on the command line were still resolved against the original working directory.uv now resolves
--index,--default-index,--index-url,--extra-index-url, and--find-linksrelative to the directory selected by--directory. For example:This now uses
project/packagesinstead of./packagesin the original working directory. Absolute paths and indexes loaded from configuration files are unaffected.To preserve the previous target, pass an absolute path or adjust the relative path, e.g.,
--index ../packages.Preserve absolute paths provided to
uv add(#18402)uv addpreviously converted every local dependency into a project-relative path, even when the original request used an absolute path or a literalfile://URL. It now preserves the form of the request inpyproject.tomlanduv.lock:Absolute paths make a project less portable. Use a relative path to avoid recording an absolute path. URLs containing expanded variables retain their existing relative-path behavior.
Remove older PyPy distributions that are only available as bzip2 archives (#20423)
Older PyPy patch releases that are only distributed as
.tar.bz2archives are no longer available throughuv python install. These releases require unsupported bzip2 archives.The latest PyPy release for each supported Python minor version is available as a gzip-compressed archive and remains supported. For example,
uv python list 3.10 --all-versionsstill includes the latest PyPy 3.10 release, but older bzip2-only patch releases are omitted.You cannot opt out of this behavior. Request a newer PyPy patch release instead.
Omit excluded-package comments when annotations are disabled (#20085)
uv pip compile --no-annotatesuppresses comments describing the generated requirements file. Previously, a footer listing packages excluded with--unsafe-packagewas still included, even though annotations were disabled. That footer is now omitted.You can recover the footer by removing
--no-annotate.Stabilizations
TOML 1.0-compatible source distributions (#20225)
uv_buildnow writes a TOML 1.0-compatiblepyproject.tomlwhen building source distributions, allowing older Python build frontends to consume projects that use newer TOML syntax. The original project file remains available in the archive aspyproject.toml.orig.This stabilizes the
toml-backwards-compatibilitypreview feature.Automatic open-file limit adjustment on Unix (#20225)
On Linux and macOS, uv now attempts to raise the soft open-file limit at startup toward the hard limit, capped at 1,048,576 descriptors. The new limit also applies to subprocesses and reduces failures caused by running out of file descriptors. If the limit cannot be raised, uv continues running with the existing limit.
This stabilizes the
adjust-ulimitpreview feature.Preview features
uv upgradeto target multiple packages, upgrade all production dependencies, and exclude selected dependencies (#20338)Bug fixes
Configuration
📅 Schedule: (in timezone Europe/Warsaw)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.
This PR has been generated by Mend Renovate CLI.