Changelog
August 15, 2026
Patch Changes
- 8df6ad0: Offer the vendored
anti-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 the
oxlint-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 — notably
only-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 new
selectJsPluginsexport 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 vendored
anti-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).
August 14, 2026
Patch Changes
- 417a85a: Add an opt-in
ultracite/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: Move
suspicious/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.
August 12, 2026
Patch Changes
- a1fa9c4: Replace the hand-rolled package
exportsmap 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 in
findNearestFileanddetectLinterwith 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 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
timeoutandforceKillAfterDelayoptions, 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.
August 8, 2026
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.
August 5, 2026
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: Fix
ultracite 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: Fix
ultracite 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: Fix
ultracite 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 when
jobs: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: Fix
ultracite 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-running
ultracite 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 removing
storybookfrom 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 generic
TESTenvironment 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.
August 2, 2026
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-plugins
ultracite 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)
July 14, 2026
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 resolve
ultracite/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’s
noUnknownAttributerule 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.
July 8, 2026
Patch Changes
- dc6d760: Disable the
n/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: Fix
ultracite 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-in
ultracite/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 for
ultracite 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.
July 6, 2026
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.
July 6, 2026
Patch Changes
-
ecd10cc: Disable
sonarjs/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: Disable
sonarjs/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 standalone
ultracite/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.
July 5, 2026
Minor Changes
- aea7fc0: Update Biome to 2.5.2 and enable the newly-stabilized rules. This adds coverage for the rules promoted out of nursery in Biome 2.5.0, including
noShadow,noUnnecessaryConditions,noUnusedInstantiation(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 (notably
eslint-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: Add
eslint-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 (the
oxlint --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. Running
ultracite initnow removes config files and dependencies for unselected Biome, ESLint/Prettier/Stylelint, or Oxlint/Oxfmt setups before writing the selected toolchain config. - e24068b: Sort
package.jsonkeys when using Biome
July 2, 2026
Patch Changes
- e4ddd22: Ignore
.yarndirectories by default - a1d5c06: Configure Oxfmt to never wrap prose (
proseWrap: "never") - df709a4: Ignore
.wranglerand.wrangler-dry-runoutput directories by default
June 10, 2026
Patch Changes
-
c863d09: Fix automatic editor extension installation during
ultracite init.The whole command line (e.g.
code --install-extension) was passed tospawnSyncas the executable name, which always failed withENOENTand 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-looprule 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 -eand 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 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 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.jsonwas always treated as the lint-staged config because the file exists in every project, soultracite 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.jsonis created).Re-running
ultracite initalso appended anothernpx ultracite fixentry 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--skipflag itself instead of forwarding it to the script — so agent hooks ran a plainultracite fix, including the unused-import removal the flag exists to prevent mid-edit. The generated command is nownpm run fix -- --skip=correctness/noUnusedImports, matching the documented form. -
ecb0d5b: Scope the Stylelint step of
ultracite 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 and failed withCssSyntaxError. 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-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 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.
June 7, 2026
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.
May 31, 2026
Patch Changes
- 8335be7: Build the CLI with
bun buildand atsgotype-check gate instead of tsup. - f747449: Fix the Oxlint TanStack preset so route files under
routes/andapp/routes/are exempt fromunicorn/filename-case, matching the documented 7.8.0 behavior. - 092597e: Fix generated
oxlint.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.
May 26, 2026
Minor Changes
-
4e2fea0: Add a dedicated
tanstackframework preset for Biome, ESLint, and Oxlint. The ESLint preset layers@tanstack/eslint-plugin-query,@tanstack/eslint-plugin-router, and@tanstack/eslint-plugin-start, while the Biome and Oxlint presets relax file-naming conventions forroutes/directories and the generatedrouteTree.gen.ts. Framework detection now maps@tanstack/react-query,@tanstack/react-router, and@tanstack/react-startto the newtanstackpreset.Two behavior changes for existing consumers: TanStack Query rules now live in the
tanstackpreset instead ofreact, so projects that relied on Query rules must opt intotanstack; and TanStack Router projects now resolve to thetanstackpreset rather thanremix.
Patch Changes
-
51a2af0: Recognize
.biome.jsonand.biome.jsoncas valid Biome config files across the CLI.detectLinter, thedoctorcommand, and the Biome config resolver now match the dot-prefixed names alongsidebiome.json/biome.jsonc, following Biome’s documented configuration file resolution order. Closes #700. -
14b557c: Harden the generated standalone Husky hook by using
git add -- "$file"when restaging formatted files. This prevents option-shaped filenames from being interpreted as Git options during the hook. -
baa3dd0: Add
ignorePatternsto the generated oxlint config at the root level so they are actually applied. Oxlint does not mergeignorePatternsthroughextends(see oxc-project/oxc#10223), so patterns set in the core preset were silently ignored. The generated config now setsignorePatterns: core.ignorePatternsat the top level, reusing the patterns from the imported core preset. -
bd27fd4: Add newly supported Oxlint rules from the latest release to the core, React, and Vitest presets:
- Core:
id-match,no-implicit-globals,no-implied-eval,prefer-arrow-callback,prefer-regex-literals,import/newline-after-import,jsdoc/require-throws-description,jsdoc/require-throws-type, andjsdoc/require-yields-type - React:
jsx-a11y/control-has-associated-label,jsx-a11y/no-interactive-element-to-noninteractive-role,jsx-a11y/no-noninteractive-element-interactions,jsx-a11y/no-noninteractive-element-to-interactive-role,react/no-object-type-as-default-prop, andreact/no-unstable-nested-components - Vitest:
vitest/padding-around-after-all-blocks
- Core:
-
14b557c: Reject symlinked generated config targets before writing project files. CLI config writers now route through a shared project-file write guard that checks for symlinks and project-root escapes before mutating files.
-
14b557c: Validate package-manager names before generating agent and editor hook commands. Hook configuration now only uses supported package-manager prefixes, preventing unsafe values from being persisted into later-executed hook commands.
-
14b557c: Reject unsupported package-manager names during
ultracite init. Explicit--pmvalues and detectedpackageManagermetadata are now runtime-validated against the supported package managers before dependency installation, preventing malicious project metadata from selecting an arbitrary executable.
May 10, 2026
Minor Changes
-
24b0d27: Wire up the
nestjsESLint preset to actually enforce rules. Previously the preset exported an emptyconst config = [], meaning users who importedultracite/eslint/nestjsgot nothing. It now layers@darraghor/eslint-plugin-nestjs-typed(22 rules covering NestJS conventions, dependency injection correctness, and class-validator/Swagger usage) using the same dynamic-enable pattern as the other framework presets.Consumers who already had the empty preset in their config may see new violations on first run.
Patch Changes
-
161418a: Add missing Biome stable rules to the core config:
suspicious/noDuplicateDependencies→"error"— flags a dependency listed multiple times in the same group, or acrossdependenciesanddevDependencies, inpackage.json.suspicious/useDeprecatedDate→"off"— GraphQL-only convention requiring adeletionDateargument on@deprecated; too opinionated for the default preset.
-
9a2b548: Pin
@angular-eslint/eslint-pluginto^21.3.1inpackages/cli/package.json. Previously declared as"latest", which defeats lockfile reproducibility and means eachbun installcould pull a newer version than what was tested at publish time. The current resolved version (21.3.1) is unchanged. -
44f6d7f: Align ESLint presets with the oxlint configs (the maintained source of truth). Mostly tightens ESLint where oxlint was stricter; a few documented behavioural exceptions oxlint carries (rule conflicts, bun:test compat) are mirrored back.
core —
eslint.mjsnow enforcescomplexity,no-unused-private-class-members,sort-keys,sort-vars, and fullprefer-destructuring(object + array).typescript.mjsnow enforcesno-confusing-void-expression,no-misused-promises,prefer-readonly,strict-boolean-expressions, and setsreturn-await: ["error", "always"].import.mjsnow setsconsistent-type-specifier-style: ["error", "prefer-top-level"].next — added
next-env.d.tsoverride that disablesimport-x/no-unassigned-importon the generated file.remix — added
routeTree.gen.tsoverride that disablesunicorn/filename-caseandunicorn/no-abusive-eslint-disableon the generated file.react — disabled
react/jsx-boolean-value,react/no-unknown-property, andreact/only-export-componentsto match oxlint.jest — broadened test globs to
**/*.{test,spec}.{ts,tsx,js,jsx}+**/__tests__/**/*.{ts,tsx,js,jsx}(previously missed*.spec.*and__tests__/). Disabledno-empty-functionandpromise/prefer-await-to-thenin test scope. Disabledjest/require-hook,jest/no-conditional-in-test,jest/no-hooks,jest/prefer-expect-assertionsto mirror oxlint’s bun:test/mocking accommodations.vitest — same test-glob broadening; same
no-empty-function/promise/prefer-await-to-thentest-scope disables. Removed theprefer-importing-vitest-globalsandprefer-to-have-been-called-timesdisables (oxlint enforces these). Addedprefer-lowercase-title: offandvalid-title: offto resolve the documented conflict withprefer-describe-function-title(#665). -
63f6a18: Drop the redundant
react-hooks/exhaustive-deps: "error"override inconfig/eslint/react/rules/react-hooks.mjs. The dynamic-enable pattern already sets every non-deprecatedreact-hooks/*rule to"error", so the override was dead code. No behavior change. -
5a0ce67: Refresh the misleading header comment in
config/eslint/core/rules/eslint-typescript.mjs. The disables for the formatting rules (brace-style,comma-dangle,indent, etc.) used to defer to@typescript-eslint’s typed equivalents, but those rules were removed in v8. They’re now disabled because Prettier/Oxfmt owns formatting. Updated the comment to reflect the actual rationale. -
d681f70: Clean up
config/eslint/core/rules/typescript.mjs: remove 22 stale overrides that referenced rules no longer present in@typescript-eslint/eslint-pluginv8.Most were formatting rules moved out to
@stylistic(block-spacing,brace-style,comma-dangle,comma-spacing,func-call-spacing,indent,key-spacing,keyword-spacing,lines-around-comment,lines-between-class-members,member-delimiter-style,no-extra-parens,object-curly-spacing,padding-line-between-statements,quotes,semi,space-before-blocks,space-before-function-paren,space-infix-ops,type-annotation-spacing). The remaining two (no-type-alias,sort-type-union-intersection-members) were removed/deprecated upstream. All were dead no-ops — no behavior change.
May 8, 2026
Patch Changes
- 3e08c25: Fix
ultracite initfailing withnpm error No workspaces found!in npm monorepos. WhenisMonorepo()was true, nypm was passedworkspace: true, which translates to--workspacesfor npm — that installs in every workspace package and errors when patterns match nothing. We now skip the workspace flag for npm (the default root install is what we want) while preserving the flag for pnpm (--workspace-root) and yarn classic (-W). Applies to ultracite, husky, lefthook, and lint-staged installs.
May 8, 2026
Patch Changes
-
aba89bb: Add new oxlint 1.63.0 rules:
eslint/logical-assignment-operators→"error"— prefer||=,&&=,??=over their longhand equivalents; aligns with the modern-JS baseline.eslint/require-unicode-regexp→"error"— require theu(orv) flag on regex literals for correct Unicode handling.eslint/no-restricted-properties→"off"— purely a project-specific allowlist; no useful default to enforce.unicorn/no-negated-condition→"error"— newly split from the eslint version; the unicorn variant additionally covers ternary expressions and complements the existingeslint/no-negated-condition.jsx-a11y/interactive-supports-focus→"error"— interactive elements (click handlers,role="button", etc.) must be keyboard-focusable; matches the rest of the a11y baseline.vue/return-in-computed-property→"error"— computed properties must return a value; missingreturnsilently breaks reactivity.vue/no-deprecated-model-definition→"error"— flags Vue 2model: { ... }usage; Vue 3 is the supported target.vitest/prefer-mock-return-shorthand→"error",vitest/no-unneeded-async-expect-function→"error",vitest/prefer-to-have-been-called-times→"error",vitest/prefer-snapshot-hint→"error"— newly split out from the jest plugin; mirrors the existing jest config which has all four enabled.vitest/require-hook→"off"— newly split out from jest; disabled to mirror jest config (bun:testmock.module()must be called at top level).
-
522155e: Set
typescript/return-awaitto["error", "always"]to resolve a circular conflict betweeneslint/require-await,typescript/promise-function-async, andtypescript/return-awaiton Promise-returning functions outside try/catch. With the defaultin-try-catchmode, autofixers chase each other:promise-function-asyncaddsasync,require-awaitthen demands anawait, andreturn-awaitremoves anyreturn awaitoutside a try/catch — leaving no resolvable state. The"always"mode keepsreturn awaiteverywhere, breaking the cycle while preserving consistent stack traces.
May 3, 2026
Patch Changes
-
f584d93: Disable
unicorn/number-literal-casedue to oxc-project/oxc#21949. -
ef5c3ae: Fix
ultracite checkandultracite fixshort-circuiting after the formatter step. Previously, when the formatter (oxfmt or Prettier) exited non-zero, the linter (oxlint, ESLint, Stylelint) was never invoked, hiding lint errors until formatting was clean. The commands now run every step, accumulate failures, and exit with the first failing tool’s status. Fixes #690. -
3ecb159: Fix the generated
oxfmt.config.tstemplate, which usedextends: [ultracite]— a key oxfmt does not recognize, so the preset was silently dropped and built-in options likesortImportsnever took effect. The template now spreads the preset (...ultracite) so its options are actually applied. Fixes #689. -
5a18ec8: Add new oxlint 1.61.0 and 1.62.0 rules:
eslint/func-name-matching→"error"— function names should match the variable they’re assigned to; matches the project’s strict baseline.eslint/no-underscore-dangle→"off"— common patterns like_id(Mongo) and_internalmake this rule too noisy in practice.typescript/explicit-member-accessibility→"off"— forcingpublic/privateon every class member is verbose and not idiomatic in modern TS.jest/prefer-expect-assertions→"off"andvitest/prefer-expect-assertions→"off"— requiringexpect.assertions(n)in every test is too strict for general use; not all tests need explicit assertion counts.vitest/max-expects→"error"andvitest/max-nested-describe→"error"— newly split out from the jest plugin; mirrors the existing jest config which has both enabled.vitest/no-conditional-in-test→"off"— newly split out from jest; disabled to mirror jest config (mock factories use conditionals for path-based routing).vitest/no-hooks→"off"— newly split out from jest; disabled to mirror jest config (bun:test usesbeforeEachformock.restore()).react/forbid-component-props→"off"— parity with the ESLint config, which already disables this rule.
April 26, 2026
Patch Changes
- 5be860c: Automatically detect frameworks during the
initprocess. - 10d9e95: Support
-vas a short alias for--versionon the CLI (previously only-Vworked). - 8ff1b96: Fix
updatecommand not migrating legacyultracite/<name>extends entries toultracite/biome/<name>(e.g.ultracite/core,ultracite/react,ultracite/type-aware, etc.). - 5e055ce: Ignore Cloudflare Workers’ generated
worker-configuration.d.ts(produced bywrangler types), matching the existing handling ofnext-env.d.ts. - 9cc7416: Add a
universaleditor target that creates.vscode/settings.jsonfor every VS Code-based editor (VS Code, Cursor, Windsurf, CodeBuddy, Antigravity, IBM Bob, Kiro, Trae, Void) with a single selection. Theinitprompt now offers a “Universal” option, and--editors universalworks as an alias on the CLI.
April 22, 2026
Patch Changes
- 2fbded9: Disable the
typescript/prefer-readonly-parameter-typesOxlint rule. While the rule is useful for user-authored types, it fires on virtually every parameter that touches a third-party type (ExpressRequest/Response, React events, NodeBuffer, ORM models, DOM APIs) because those types aren’t deeply readonly internally — leaving users with unfixable violations. Matches the existing ESLint config, which already has this rule off. - 617affd: Fix
dist/,.next/,**/*.gen.*, and other strong-negation (!!) ignore globs being dropped when a consumer’sbiome.jsoncextendsultracite/biome/coreand also defines its ownfiles.includes. The globs moved intoconfig/shared/ignores.jsoncin 7.5.9 were transitively extended throughbiome/core, and Biome’s extend merge doesn’t carryfiles.includesthrough a two-level chain when the middle config lacks its own entry. The patterns are now inlined directly inbiome/core’sfiles.includes(still generated fromconfig/shared/ignores.mjs), matching the pre-7.5.9 behavior. - d681e08: Remove the nonexistent
import-x/enforce-node-protocol-usagerule from the ESLint core config, which caused ESLint 9 to throwCould not find "enforce-node-protocol-usage" in plugin "import-x". Node protocol enforcement is already covered byunicorn/prefer-node-protocol.
April 16, 2026
Minor Changes
- 67227c9: Add new Biome rules
- f506624: Add new oxlint 1.160.0 rules
Patch Changes
- a684c4a: Fix Tanstack Query ESLint plugin import
- 4983eaa: Skip the init skill-install prompt when the Ultracite skill is already installed in the current project or globally.
April 15, 2026
Patch Changes
- 77e9b41: Aggregate all ignore patterns
- 73fc21c: Code reliability improvements
- 63f7426: Migrate remaining json parsing to jsonc-parser
- aa199d1: fix conflicting prefer-describe-function-title / valid-title rules in vitest
- 402908e: Replace custom yaml parser with dependency
- 3dbfe5c: Validate framework name to prevent injection
- a2cdc0f: Warn if the file looks like it has ultracite config but we couldn’t parse it
- 95718bb: Use cross-spawn for cross-platform spawn compatibility
- d09174b: Ignore
.open-nextin the Biome and ESLint core presets. - 71aeca4: Remove remaining execSync calls
- e81a604: Add zod for safer json parsing
April 14, 2026
Patch Changes
- c35a1b3: Performance improvements - doctor
- 56e4c00: Remove process.exit() - swap with typed Error
- d35d03c: Performance optimizations - mkdir(), readFile()
- ee224a6: Use Commander.js args properly
- a2b7a46: Rework doctor command
- cf4a044: Fix angular eslint plugin typo
- 25eb24f: Optimize dev dep install
- b46537a: Performance optimizations - exists()
April 14, 2026
Patch Changes
- a63d9c5: Fix cross-config leaking rules
- d18d0e7: Configure Prettier with frameworks context
- 1d6de0d: Add declaration files for
ultracite/oxlint/*andultracite/oxfmtso TypeScript config imports resolve withoutts(7016)errors. - 1073f34: Ensure init’ed JSON files have newlines
April 11, 2026
Patch Changes
- acf4a97: Update oxlint jest rules
- 6905932: Fix vitest/no-importing-vitest-globals conflict
- 4e4dc03: Update oxlint vitest rules
- 6a583d1: Fix oxfmt setup config
April 11, 2026
Patch Changes
- 5437f81: Attempt to fix oxlint/oxfmt AGAIN
April 11, 2026
Patch Changes
- 66999e0: Fix oxlint and oxfmt yet again
April 11, 2026
Patch Changes
- 97c3938: Fix oxlint and oxfmt import paths
April 11, 2026
Patch Changes
- 22df7a5: Fix oxlint import issues
April 11, 2026
Patch Changes
- e96c55a: Switch oxlint.config.ts to js imports
April 11, 2026
Minor Changes
- 7861cf7: Migrate oxlint and oxfmt configurations from JSON to TypeScript using
defineConfig. The CLI now generatesoxlint.config.tsandoxfmt.config.tsinstead of.oxlintrc.jsonand.oxfmtrc.jsonc, and all internal framework presets have been converted to TypeScript.
Patch Changes
- fdb1493: Exclude package manager lock files (bun.lock, bun.lockb, package-lock.json, yarn.lock, pnpm-lock.yaml) from Biome linting and formatting
April 9, 2026
Patch Changes
- e9db6f1: Add IBM Bob agent, editor, and logo
- 5341bcc: Disable vitest/prefer-strict-boolean-matchers to resolve conflict with prefer-to-be-truthy and prefer-to-be-falsy
April 3, 2026
Patch Changes
- 42b3552: Update the bundled VS Code settings to use
js/ts.tsdk.pathandjs/ts.tsdk.promptToUseWorkspaceVersioninstead of the deprecatedtypescript.tsdksetting. - a0a03c6: Allow
utf-8values in theunicorn/text-encoding-identifier-caserule across the bundled ESLint and Oxlint configs.
March 31, 2026
Patch Changes
- 94e770e: Remove non-existent oxlint rules (
import/no-unresolved,vitest/no-done-callback) for compatibility with oxlint 1.58.0+
March 29, 2026
Minor Changes
- c189cf1: Add support for new agent integrations including Zencoder, Ona, OpenClaw, Continue, Snowflake Cortex, Deepagents, Qoder, Kimi CLI, Kode, MCPJam, Mux, Pi, Neovate, Pochi, and AdaL, plus add CodeBuddy as a supported editor.
Patch Changes
- 04d8455: Add no-void rule with allowAsStatement to complement no-floating-promises
- e38d579: Fix DEP0190 deprecation warnings in
check,fix, anddoctorby routing CLI subprocesses through a sharedcross-spawnrunner withshell: false, while preserving Windows command resolution and direct file-path argument passing. - 98cb8c2: Pin ESLint initialization to a peer-compatible dependency set so
ultracite initno longer installs an incompatibleeslint@latestwitheslint-plugin-github - fd7d05f: Disable conflicting
vitest/prefer-called-timesoxlint rule to resolve conflict withvitest/prefer-called-once - 581ea40: Add typed
ultracite/oxlintexports for use inoxlint.config.ts.
March 17, 2026
Patch Changes
- 8ffeb33: Add support for .oxlintrc.mjs and oxlint.config.ts
March 14, 2026
Patch Changes
- f84edff: Fix –type-aware for Biome
- acf301c: Migrate from eslint-plugin-import to import-x
- 5749eb1: Create test frameworks
March 12, 2026
Minor Changes
- 0d27e68: fix noUnusedImports removing new imports in agent hooks
Patch Changes
- 668fe62: Add –type-aware flag for biome
- 4280484: Disable max-statements in Oxlint
- d37b046: Disable jsdoc/require-param-type and jsdoc/require-returns-type for TS files
March 5, 2026
Patch Changes
- 83bafe4: Disable useValidLang rule for SvelteKit app.html to prevent false positives from %lang% placeholder
- 4df6da9: Disable noUndeclaredVariables for Svelte files to fix false positives with template block variables like {#each}
February 26, 2026
Patch Changes
- cfaa912: Remove Jest and Vitest rules from non-test files
- f72f2dc: Add support for copilot hooks
- 66d51fd: Disable import/no-nodejs-modules for Chris Consent
- d1e8490: Create skill
February 16, 2026
Patch Changes
- 3cd6e7b: Upgrade Biome to 2.4
February 16, 2026
Patch Changes
- 8db75d7: Only run shell: true on windows
February 14, 2026
Patch Changes
- 0d21c46: Restore shell for windows
February 13, 2026
Minor Changes
- fe9acf6: Use local binaries
Patch Changes
- 357be7e: Store full package manager info from detectPackageManager()
- 8666788: Fix Husky precommit hook
February 7, 2026
Patch Changes
- c8fdacf: fix: detectLinter() doesn’t walk up directory tree, Breaks monorepo subdirectory usage
- c79c3b0: Fix lefthook file configuration
- 4b9d206: Make useBlockStatements fix safe
- 8e9e728: Add support for NestJS
- d0ae8f3: Fix: Biome removes all imports in Svelte files on save instead of organizing them
February 3, 2026
Patch Changes
- 34c79bb: Fix conflicting oxlint rules
February 1, 2026
Patch Changes
- c60533d: Fix oxlint import/consistent-type-specifier-style
February 1, 2026
Patch Changes
- 9d443b6: Fix func-style config in oxlint
- 3d9b488: Fix: argument –unsafe cannot be used multiple times in this context
- f06808f: Don’t pass options to formatters, only linters
January 27, 2026
Patch Changes
- 0e9af01: Automatically add scripts to root package.json
- 656f6d7: fix(oxlint-remix): ignore unicorn rules for generated routeTree.gen.ts
January 20, 2026
Patch Changes
- f328fc6: Update nypm to remove dependency on corepack
- 6f638fa: Fix error message when exiting with code 1
- f328fc6: Fix eslint dependencies during initialization
- f328fc6: Allow comments in json files
January 10, 2026
Patch Changes
- 79d2756: fix: exit with code 1 when check/fix finds errors
- c032612: Fix: Parser Errors on .jsonc Files Due to Comments
- a556651: Move oxlint to optionalDependencies or peerDependencies
January 8, 2026
Patch Changes
- a7b34ed: Add Vercel Agent support
- b6658ce: Add Claude Code hook integration to run
ultracite fixafterWrite/Edittool usage.
January 7, 2026
Patch Changes
- 95dd898: Disable sort-imports in favor of oxfmt
- c72d2b3: Disable react/jsx-max-depth
- 2ae8976: Disable typescript/require-await
January 5, 2026
Patch Changes
- a9efe80: Add Cursor CLI as agent
- 00fb477: Add support for Mistral Vibe
January 4, 2026
Patch Changes
- ea7a6dc: Fix oxlint import path
- a6e43a0: Add more CLI options for oxlint, oxfmt and biome
- ad52a16: Fix linter provider mention in agent rules
January 3, 2026
Patch Changes
- 702f6b5: Upgrade Biome to 2.3.11
January 2, 2026
Patch Changes
- ab47642: add –type-aware and –type-check flags for oxlint
January 1, 2026
Patch Changes
- 7e9b76c: Fix legacy imports
January 1, 2026
Patch Changes
- 92eaa89: Cleanup dist files
January 1, 2026
Patch Changes
- 246c1fc: Update docs and README Remove catalog dependencies
January 1, 2026
Patch Changes
- a8408b6: Fix bundling issues
January 1, 2026
Major Changes
- c4a205f: Remove i18n docs
- c4a205f: Remove custom reporter
- c4a205f: Scaffold support for ESLint and Oxlint
- c4a205f: Add support for Amazon Q, Crush, Firebender, OpenCode, Qwen and Trae
- c4a205f: Move biome config under
biome
Patch Changes
- 5538022: Increase max allowed complexity
- 5508d47: Remove GraphQL override that disables formatter/linter
- e1b6be6: Fix undefined input to fix command
- 618ae17: Fix changesets
- Updated dependencies [c4a205f]
- @repo/data@2.0.0
December 21, 2025
Minor Changes
- 628a5c3: Disable nursery rules
Patch Changes
- a942392: Use
interfaceas consistent type definition
December 21, 2025
Patch Changes
- 393a0d1: Explicitly enable css
- 127c1c6: Fix reporter bug for –unsafe flag
- 41a73ba: Fix file-based metadata
- 43b07be: Fix tsconfig patching
- 9d1d374: Add support for pre-commit (python)
- f9256db: Add support for Antigravity
December 18, 2025
Patch Changes
- 42fc700: Disable scanner rules
- aff09df: Fix plugin install logging
- 0f57252: Upgrade to Biome 2.3.9
- c15b770: Fix reporter
- 99dda79: Fix extension install logging
- d759789: Bump Biome to 2.3.10
December 15, 2025
Patch Changes
- a8570b3: respect package manager in generated rules and commands
December 12, 2025
Minor Changes
- 6201822: Add custom reporter
December 12, 2025
Patch Changes
- 635acd1: Fix “canceled” bug for realsies this time
December 7, 2025
Patch Changes
- bc7d89f: Fix nested next.config.ts detection
- d292922: Replace hardcoded npx commands
December 4, 2025
Patch Changes
- a13eb72: Add support for Factory Droid AI assistant
November 28, 2025
Patch Changes
- e5e48db: Bump Biome to 2.3.8
- 0a525d9: Update docs
November 27, 2025
Patch Changes
- fec49ac: added cloudflare wrangler generated file to the ignore list
November 22, 2025
Patch Changes
- 99a417c: Fix docs on quotes
- 5fb7031: Add support for max diagnostics flag
- c66c232: Remove process.exit from CLI
November 22, 2025
Patch Changes
- 1bccc30: Upgrade Biome to 2.3.7
- 3837d19: Fix Zed config
- 06a8871: Use force-ignore pattern
November 18, 2025
Patch Changes
- 3edc530: Bump glob to resolve dependency vulnerability
- 30ac12c: Update Biome to 2.3.6
November 14, 2025
Patch Changes
- 9132af5: Upgrade to Biome 2.3.5
November 6, 2025
Patch Changes
- 7537f01: Improve CI support
November 6, 2025
Patch Changes
- 908ac57: Add missing hooks cli definition
November 5, 2025
Minor Changes
- a5a1510: Add new hooks flag, add Claude hooks support
Patch Changes
- 0fed52b: Upgrade Biome to 2.3.4
- a9347c8: Disable noMagicNumbers and noConsole
- aa7f769: Updated tsconfig, package.json selector
November 4, 2025
Patch Changes
- 527e737: Update to Biome 2.3.3
- d5f9d64: Disable useAwait on page.tsx and layout.tsx files in Next.js
- eb77e3f: add allowForLoopAfterthoughts to noIncrementDecrement
November 3, 2025
Minor Changes
- 4035389: add cursor hooks functionality
- 18ed1f3: Refactor rules based on hooks and feedback from Cursor team
Patch Changes
- 7aa5fd8: pass diagnostic-level filter option (stop-gap)
- f9e2141: Update existing tsconfig files instead of creating a new root one
October 30, 2025
Minor Changes
- b6bdc8e: Introduce Warp agentic terminal support
Patch Changes
- ba72503: Fix husky initialization
- b038a60: Fix overrides in Astro, Svelte, Vue presets having no effect
- b7451ee: Improve core glob
- f7ebeb8: Improve test coverage for agents
October 28, 2025
Patch Changes
- 5f00bd3: Use overrides in presets
- 30f488e: Upgrade Biome to 2.3.2, add “noIncrementDecrement”
October 27, 2025
Patch Changes
- b0a7281: setting cursor rule context to glob pattern instead of always apply
October 26, 2025
Patch Changes
- 82e5353: Drop legacy ultracite preset
October 26, 2025
Patch Changes
- 9566f79: Upgrade to Biome 2.3.1
October 25, 2025
Patch Changes
- 5848800: Fix legacy ultracite config
October 24, 2025
Major Changes
- 86ee61e: Add specific Ultracite configurations
Minor Changes
- d704b5c: Add first-class support for Astro
Patch Changes
- c5c7ca1: Disable project rules
- ff83b52: Compress Ultracite agent rules
- 8987c58: Upgrade to Biome 2.3.0
- acd8c42: Brand and docs update
- ed1bcb6: Docs updates and bump deps
- d0ba90b: Tie framework selection to agent context
October 14, 2025
Patch Changes
- 679719b: Temporarily disable Qwik rules
October 14, 2025
Patch Changes
- a167b1c: Update Biome to 2.2.6
October 11, 2025
Patch Changes
- 7b515fe: Disable useAwait rule in next config files
- 7b515fe: Improve test coverage
- c3a9dad: Bump deps
- 3faa8c2: Add Roo Code editor rules support
October 7, 2025
Patch Changes
- 44917fd: Fix package readme, move vitest to devDeps
Minor Changes
- 762ef70: Workflow improvements
Patch Changes
- f3ec41b: Backport changelog
October 7, 2025
October 7, 2025
October 7, 2025
🐛 Bug Fix
- Potential fix for code scanning alert no. 13: Workflow does not contain permissions #297 (@haydenbleasel)
- Potential fix for code scanning alert no. 12: Workflow does not contain permissions #298 (@haydenbleasel)
Authors: 1
- Hayden Bleasel (@haydenbleasel)
October 7, 2025
⚠️ Pushed to main
- Increase branch test coverage from 89.21% → 91.02% (@haydenbleasel)
- Update package.json (@haydenbleasel)
- Fix unit tests (@haydenbleasel)
- Add Videos section to homepage (@haydenbleasel)
- Merge branch ‘main’ of https://github.com/haydenbleasel/ultracite (@haydenbleasel)
- Resolves #280 (@haydenbleasel)
- Make migration dep parsing lazier (@haydenbleasel)
- Resolves #287 (@haydenbleasel)
- Resolves #290 (@haydenbleasel)
- Resolves #294 (@haydenbleasel)
Authors: 1
- Hayden Bleasel (@haydenbleasel)
October 7, 2025
October 6, 2025
⚠️ Pushed to main
- Upgrade Biome to 2.2.5 (@haydenbleasel)
Authors: 1
- Hayden Bleasel (@haydenbleasel)