# Ultracite
> Documentation for Ultracite.
# ultracite@5.6.2
Source: https://www.ultracite.ai/changelog/ultracite-5-6-2
### Patch Changes
- 7b515fe: Disable useAwait rule in next config files
- 7b515fe: Improve test coverage
- c3a9dad: Bump deps
- 3faa8c2: Add Roo Code editor rules support
---
# ultracite@5.6.3
Source: https://www.ultracite.ai/changelog/ultracite-5-6-3
### Patch Changes
- a167b1c: Update Biome to 2.2.6
---
# ultracite@5.6.4
Source: https://www.ultracite.ai/changelog/ultracite-5-6-4
### Patch Changes
- 679719b: Temporarily disable Qwik rules
---
# ultracite@6.0.0
Source: https://www.ultracite.ai/changelog/ultracite-6-0-0
### 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
---
# ultracite@6.0.1
Source: https://www.ultracite.ai/changelog/ultracite-6-0-1
### Patch Changes
- 5848800: Fix legacy ultracite config
---
# ultracite@6.0.2
Source: https://www.ultracite.ai/changelog/ultracite-6-0-2
### Patch Changes
- 9566f79: Upgrade to Biome 2.3.1
---
# ultracite@6.0.3
Source: https://www.ultracite.ai/changelog/ultracite-6-0-3
### Patch Changes
- 82e5353: Drop legacy ultracite preset
---
# ultracite@6.0.4
Source: https://www.ultracite.ai/changelog/ultracite-6-0-4
### Patch Changes
- b0a7281: setting cursor rule context to glob pattern instead of always apply
---
# ultracite@6.0.5
Source: https://www.ultracite.ai/changelog/ultracite-6-0-5
### Patch Changes
- 5f00bd3: Use overrides in presets
- 30f488e: Upgrade Biome to 2.3.2, add "noIncrementDecrement"
---
# ultracite@6.1.0
Source: https://www.ultracite.ai/changelog/ultracite-6-1-0
### 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
---
# ultracite@6.2.0
Source: https://www.ultracite.ai/changelog/ultracite-6-2-0
### 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
---
# ultracite@6.2.1
Source: https://www.ultracite.ai/changelog/ultracite-6-2-1
### 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
---
# ultracite@6.3.0
Source: https://www.ultracite.ai/changelog/ultracite-6-3-0
### 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
---
# ultracite@6.3.1
Source: https://www.ultracite.ai/changelog/ultracite-6-3-1
### Patch Changes
- 908ac57: Add missing hooks cli definition
---
# ultracite@6.3.10
Source: https://www.ultracite.ai/changelog/ultracite-6-3-10
### Patch Changes
- bc7d89f: Fix nested next.config.ts detection
- d292922: Replace hardcoded npx commands
---
# ultracite@6.3.12
Source: https://www.ultracite.ai/changelog/ultracite-6-3-12
### Patch Changes
- 635acd1: Fix "canceled" bug for realsies this time
---
# ultracite@6.3.2
Source: https://www.ultracite.ai/changelog/ultracite-6-3-2
### Patch Changes
- 7537f01: Improve CI support
---
# ultracite@6.3.3
Source: https://www.ultracite.ai/changelog/ultracite-6-3-3
### Patch Changes
- 9132af5: Upgrade to Biome 2.3.5
---
# ultracite@6.3.4
Source: https://www.ultracite.ai/changelog/ultracite-6-3-4
### Patch Changes
- 3edc530: Bump glob to resolve dependency vulnerability
- 30ac12c: Update Biome to 2.3.6
---
# ultracite@6.3.5
Source: https://www.ultracite.ai/changelog/ultracite-6-3-5
### Patch Changes
- 1bccc30: Upgrade Biome to 2.3.7
- 3837d19: Fix Zed config
- 06a8871: Use force-ignore pattern
---
# ultracite@6.3.6
Source: https://www.ultracite.ai/changelog/ultracite-6-3-6
### Patch Changes
- 99a417c: Fix docs on quotes
- 5fb7031: Add support for max diagnostics flag
- c66c232: Remove process.exit from CLI
---
# ultracite@6.3.7
Source: https://www.ultracite.ai/changelog/ultracite-6-3-7
### Patch Changes
- fec49ac: added cloudflare wrangler generated file to the ignore list
---
# ultracite@6.3.8
Source: https://www.ultracite.ai/changelog/ultracite-6-3-8
### Patch Changes
- e5e48db: Bump Biome to 2.3.8
- 0a525d9: Update docs
---
# ultracite@6.3.9
Source: https://www.ultracite.ai/changelog/ultracite-6-3-9
### Patch Changes
- a13eb72: Add support for Factory Droid AI assistant
---
# ultracite@6.4.0
Source: https://www.ultracite.ai/changelog/ultracite-6-4-0
### Minor Changes
- 6201822: Add custom reporter
---
# ultracite@6.4.1
Source: https://www.ultracite.ai/changelog/ultracite-6-4-1
### Patch Changes
- a8570b3: respect package manager in generated rules and commands
---
# ultracite@6.4.2
Source: https://www.ultracite.ai/changelog/ultracite-6-4-2
### 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
---
# ultracite@6.4.3
Source: https://www.ultracite.ai/changelog/ultracite-6-4-3
### 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
---
# ultracite@6.5.0
Source: https://www.ultracite.ai/changelog/ultracite-6-5-0
### Minor Changes
- 628a5c3: Disable nursery rules
### Patch Changes
- a942392: Use `interface` as consistent type definition
---
# ultracite@7.0.0
Source: https://www.ultracite.ai/changelog/ultracite-7-0-0
### 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
---
# ultracite@7.0.1
Source: https://www.ultracite.ai/changelog/ultracite-7-0-1
### Patch Changes
- a8408b6: Fix bundling issues
---
# ultracite@7.0.10
Source: https://www.ultracite.ai/changelog/ultracite-7-0-10
### Patch Changes
- a7b34ed: Add Vercel Agent support
- b6658ce: Add Claude Code hook integration to run `ultracite fix` after `Write`/`Edit` tool usage.
---
# ultracite@7.0.11
Source: https://www.ultracite.ai/changelog/ultracite-7-0-11
### 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
---
# ultracite@7.0.12
Source: https://www.ultracite.ai/changelog/ultracite-7-0-12
### 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
---
# ultracite@7.0.2
Source: https://www.ultracite.ai/changelog/ultracite-7-0-2
### Patch Changes
- 246c1fc: Update docs and README
Remove catalog dependencies
---
# ultracite@7.0.3
Source: https://www.ultracite.ai/changelog/ultracite-7-0-3
### Patch Changes
- 92eaa89: Cleanup dist files
---
# ultracite@7.0.4
Source: https://www.ultracite.ai/changelog/ultracite-7-0-4
### Patch Changes
- 7e9b76c: Fix legacy imports
---
# ultracite@7.0.5
Source: https://www.ultracite.ai/changelog/ultracite-7-0-5
### Patch Changes
- ab47642: add --type-aware and --type-check flags for oxlint
---
# ultracite@7.0.6
Source: https://www.ultracite.ai/changelog/ultracite-7-0-6
### Patch Changes
- 702f6b5: Upgrade Biome to 2.3.11
---
# ultracite@7.0.7
Source: https://www.ultracite.ai/changelog/ultracite-7-0-7
### 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
---
# ultracite@7.0.8
Source: https://www.ultracite.ai/changelog/ultracite-7-0-8
### Patch Changes
- a9efe80: Add Cursor CLI as agent
- 00fb477: Add support for Mistral Vibe
---
# ultracite@7.0.9
Source: https://www.ultracite.ai/changelog/ultracite-7-0-9
### Patch Changes
- 95dd898: Disable sort-imports in favor of oxfmt
- c72d2b3: Disable react/jsx-max-depth
- 2ae8976: Disable typescript/require-await
---
# ultracite@7.1.1
Source: https://www.ultracite.ai/changelog/ultracite-7-1-1
### Patch Changes
- 0e9af01: Automatically add scripts to root package.json
- 656f6d7: fix(oxlint-remix): ignore unicorn rules for generated routeTree.gen.ts
---
# ultracite@7.1.2
Source: https://www.ultracite.ai/changelog/ultracite-7-1-2
### 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
---
# ultracite@7.1.3
Source: https://www.ultracite.ai/changelog/ultracite-7-1-3
### Patch Changes
- c60533d: Fix oxlint import/consistent-type-specifier-style
---
# ultracite@7.1.4
Source: https://www.ultracite.ai/changelog/ultracite-7-1-4
### Patch Changes
- 34c79bb: Fix conflicting oxlint rules
---
# ultracite@7.1.5
Source: https://www.ultracite.ai/changelog/ultracite-7-1-5
### 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
---
# ultracite@7.10.0
Source: https://www.ultracite.ai/changelog/ultracite-7-10-0
### Minor Changes
- 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: Scope React Doctor's framework-specific rules to per-framework add-on presets (#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 `
`/`` 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)
---
# ultracite@7.10.1
Source: https://www.ultracite.ai/changelog/ultracite-7-10-1
### 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 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.
---
# ultracite@7.10.2
Source: https://www.ultracite.ai/changelog/ultracite-7-10-2
### Patch Changes
- 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`.
---
# ultracite@7.10.3
Source: https://www.ultracite.ai/changelog/ultracite-7-10-3
### Patch Changes
- 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.
---
# ultracite@7.10.4
Source: https://www.ultracite.ai/changelog/ultracite-7-10-4
### Patch Changes
- 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: 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.
---
# ultracite@7.10.5
Source: https://www.ultracite.ai/changelog/ultracite-7-10-5
### Patch Changes
- 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).
---
# ultracite@7.10.6
Source: https://www.ultracite.ai/changelog/ultracite-7-10-6
### Patch Changes
- 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
---
# ultracite@7.10.7
Source: https://www.ultracite.ai/changelog/ultracite-7-10-7
### Patch Changes
- 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.
---
# ultracite@7.10.8
Source: https://www.ultracite.ai/changelog/ultracite-7-10-8
### Patch Changes
- 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`, `no-unsafe-dictionary-type` allows generic constraints such as `T extends Record`, `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.
---
# ultracite@7.11.0
Source: https://www.ultracite.ai/changelog/ultracite-7-11-0
### Minor Changes
- 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: Update dependencies (`@clack/prompts`, `semver`, `zod`, ESLint plugins).
- 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.
---
# ultracite@7.11.1
Source: https://www.ultracite.ai/changelog/ultracite-7-11-1
### 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-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.
---
# ultracite@7.2.0
Source: https://www.ultracite.ai/changelog/ultracite-7-2-0
### Minor Changes
- fe9acf6: Use local binaries
### Patch Changes
- 357be7e: Store full package manager info from detectPackageManager()
- 8666788: Fix Husky precommit hook
---
# ultracite@7.2.1
Source: https://www.ultracite.ai/changelog/ultracite-7-2-1
### Patch Changes
- 0d21c46: Restore shell for windows
---
# ultracite@7.2.2
Source: https://www.ultracite.ai/changelog/ultracite-7-2-2
### Patch Changes
- 8db75d7: Only run shell: true on windows
---
# ultracite@7.2.3
Source: https://www.ultracite.ai/changelog/ultracite-7-2-3
### Patch Changes
- 3cd6e7b: Upgrade Biome to 2.4
---
# ultracite@7.2.4
Source: https://www.ultracite.ai/changelog/ultracite-7-2-4
### 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
---
# ultracite@7.2.5
Source: https://www.ultracite.ai/changelog/ultracite-7-2-5
### 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}
---
# ultracite@7.3.0
Source: https://www.ultracite.ai/changelog/ultracite-7-3-0
### 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
---
# ultracite@7.3.1
Source: https://www.ultracite.ai/changelog/ultracite-7-3-1
### Patch Changes
- f84edff: Fix --type-aware for Biome
- acf301c: Migrate from eslint-plugin-import to import-x
- 5749eb1: Create test frameworks
---
# ultracite@7.3.2
Source: https://www.ultracite.ai/changelog/ultracite-7-3-2
### Patch Changes
- 8ffeb33: Add support for .oxlintrc.mjs and oxlint.config.ts
---
# ultracite@7.4.0
Source: https://www.ultracite.ai/changelog/ultracite-7-4-0
### 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`, and `doctor` by routing CLI subprocesses through a shared `cross-spawn` runner with `shell: false`, while preserving Windows command resolution and direct file-path argument passing.
- 98cb8c2: Pin ESLint initialization to a peer-compatible dependency set so `ultracite init` no longer installs an incompatible `eslint@latest` with `eslint-plugin-github`
- fd7d05f: Disable conflicting `vitest/prefer-called-times` oxlint rule to resolve conflict with `vitest/prefer-called-once`
- 581ea40: Add typed `ultracite/oxlint` exports for use in `oxlint.config.ts`.
---
# ultracite@7.4.2
Source: https://www.ultracite.ai/changelog/ultracite-7-4-2
### Patch Changes
- 94e770e: Remove non-existent oxlint rules (`import/no-unresolved`, `vitest/no-done-callback`) for compatibility with oxlint 1.58.0+
---
# ultracite@7.4.3
Source: https://www.ultracite.ai/changelog/ultracite-7-4-3
### Patch Changes
- 42b3552: Update the bundled VS Code settings to use `js/ts.tsdk.path` and `js/ts.tsdk.promptToUseWorkspaceVersion` instead of the deprecated `typescript.tsdk` setting.
- a0a03c6: Allow `utf-8` values in the `unicorn/text-encoding-identifier-case` rule across the bundled ESLint and Oxlint configs.
---
# ultracite@7.4.4
Source: https://www.ultracite.ai/changelog/ultracite-7-4-4
### 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
---
# ultracite@7.5.0
Source: https://www.ultracite.ai/changelog/ultracite-7-5-0
### Minor Changes
- 7861cf7: Migrate oxlint and oxfmt configurations from JSON to TypeScript using `defineConfig`. The CLI now generates `oxlint.config.ts` and `oxfmt.config.ts` instead of `.oxlintrc.json` and `.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
---
# ultracite@7.5.1
Source: https://www.ultracite.ai/changelog/ultracite-7-5-1
### Patch Changes
- e96c55a: Switch oxlint.config.ts to js imports
---
# ultracite@7.5.2
Source: https://www.ultracite.ai/changelog/ultracite-7-5-2
### Patch Changes
- 22df7a5: Fix oxlint import issues
---
# ultracite@7.5.3
Source: https://www.ultracite.ai/changelog/ultracite-7-5-3
### Patch Changes
- 97c3938: Fix oxlint and oxfmt import paths
---
# ultracite@7.5.4
Source: https://www.ultracite.ai/changelog/ultracite-7-5-4
### Patch Changes
- 66999e0: Fix oxlint and oxfmt yet again
---
# ultracite@7.5.5
Source: https://www.ultracite.ai/changelog/ultracite-7-5-5
### Patch Changes
- 5437f81: Attempt to fix oxlint/oxfmt AGAIN
---
# ultracite@7.5.6
Source: https://www.ultracite.ai/changelog/ultracite-7-5-6
### 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
---
# ultracite@7.5.7
Source: https://www.ultracite.ai/changelog/ultracite-7-5-7
### Patch Changes
- a63d9c5: Fix cross-config leaking rules
- d18d0e7: Configure Prettier with frameworks context
- 1d6de0d: Add declaration files for `ultracite/oxlint/*` and `ultracite/oxfmt` so TypeScript config imports resolve without `ts(7016)` errors.
- 1073f34: Ensure init'ed JSON files have newlines
---
# ultracite@7.5.8
Source: https://www.ultracite.ai/changelog/ultracite-7-5-8
### 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()
---
# ultracite@7.5.9
Source: https://www.ultracite.ai/changelog/ultracite-7-5-9
### 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-next` in the Biome and ESLint core presets.
- 71aeca4: Remove remaining execSync calls
- e81a604: Add zod for safer json parsing
---
# ultracite@7.6.0
Source: https://www.ultracite.ai/changelog/ultracite-7-6-0
### 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.
---
# ultracite@7.6.1
Source: https://www.ultracite.ai/changelog/ultracite-7-6-1
### Patch Changes
- 2fbded9: Disable the `typescript/prefer-readonly-parameter-types` Oxlint rule. While the rule is useful for user-authored types, it fires on virtually every parameter that touches a third-party type (Express `Request`/`Response`, React events, Node `Buffer`, 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's `biome.jsonc` extends `ultracite/biome/core` and also defines its own `files.includes`. The globs moved into `config/shared/ignores.jsonc` in 7.5.9 were transitively extended through `biome/core`, and Biome's extend merge doesn't carry `files.includes` through a two-level chain when the middle config lacks its own entry. The patterns are now inlined directly in `biome/core`'s `files.includes` (still generated from `config/shared/ignores.mjs`), matching the pre-7.5.9 behavior.
- d681e08: Remove the nonexistent `import-x/enforce-node-protocol-usage` rule from the ESLint core config, which caused ESLint 9 to throw `Could not find "enforce-node-protocol-usage" in plugin "import-x"`. Node protocol enforcement is already covered by `unicorn/prefer-node-protocol`.
---
# ultracite@7.6.2
Source: https://www.ultracite.ai/changelog/ultracite-7-6-2
### Patch Changes
- 5be860c: Automatically detect frameworks during the `init` process.
- 10d9e95: Support `-v` as a short alias for `--version` on the CLI (previously only `-V` worked).
- 8ff1b96: Fix `update` command not migrating legacy `ultracite/` extends entries to `ultracite/biome/` (e.g. `ultracite/core`, `ultracite/react`, `ultracite/type-aware`, etc.).
- 5e055ce: Ignore Cloudflare Workers' generated `worker-configuration.d.ts` (produced by `wrangler types`), matching the existing handling of `next-env.d.ts`.
- 9cc7416: Add a `universal` editor target that creates `.vscode/settings.json` for every VS Code-based editor (VS Code, Cursor, Windsurf, CodeBuddy, Antigravity, IBM Bob, Kiro, Trae, Void) with a single selection. The `init` prompt now offers a "Universal" option, and `--editors universal` works as an alias on the CLI.
---
# ultracite@7.6.3
Source: https://www.ultracite.ai/changelog/ultracite-7-6-3
### Patch Changes
- f584d93: Disable `unicorn/number-literal-case` due to [oxc-project/oxc#21949](https://github.com/oxc-project/oxc/issues/21949).
- ef5c3ae: Fix `ultracite check` and `ultracite fix` short-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](https://github.com/haydenbleasel/ultracite/issues/690).
- 3ecb159: Fix the generated `oxfmt.config.ts` template, which used `extends: [ultracite]` — a key oxfmt does not recognize, so the preset was silently dropped and built-in options like `sortImports` never took effect. The template now spreads the preset (`...ultracite`) so its options are actually applied. Fixes [#689](https://github.com/haydenbleasel/ultracite/issues/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 `_internal` make this rule too noisy in practice.
- `typescript/explicit-member-accessibility` → `"off"` — forcing `public`/`private` on every class member is verbose and not idiomatic in modern TS.
- `jest/prefer-expect-assertions` → `"off"` and `vitest/prefer-expect-assertions` → `"off"` — requiring `expect.assertions(n)` in every test is too strict for general use; not all tests need explicit assertion counts.
- `vitest/max-expects` → `"error"` and `vitest/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 uses `beforeEach` for `mock.restore()`).
- `react/forbid-component-props` → `"off"` — parity with the ESLint config, which already disables this rule.
---
# ultracite@7.6.4
Source: https://www.ultracite.ai/changelog/ultracite-7-6-4
### 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 the `u` (or `v`) 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 existing `eslint/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; missing `return` silently breaks reactivity.
- `vue/no-deprecated-model-definition` → `"error"` — flags Vue 2 `model: { ... }` 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:test `mock.module()` must be called at top level).
- 522155e: Set `typescript/return-await` to `["error", "always"]` to resolve a circular conflict between `eslint/require-await`, `typescript/promise-function-async`, and `typescript/return-await` on Promise-returning functions outside try/catch. With the default `in-try-catch` mode, autofixers chase each other: `promise-function-async` adds `async`, `require-await` then demands an `await`, and `return-await` removes any `return await` outside a try/catch — leaving no resolvable state. The `"always"` mode keeps `return await` everywhere, breaking the cycle while preserving consistent stack traces.
---
# ultracite@7.6.5
Source: https://www.ultracite.ai/changelog/ultracite-7-6-5
### Patch Changes
- 3e08c25: Fix `ultracite init` failing with `npm error No workspaces found!` in npm monorepos. When `isMonorepo()` was true, nypm was passed `workspace: true`, which translates to `--workspaces` for 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.
---
# ultracite@7.7.0
Source: https://www.ultracite.ai/changelog/ultracite-7-7-0
### Minor Changes
- 24b0d27: Wire up the `nestjs` ESLint preset to actually enforce rules. Previously the preset exported an empty `const config = []`, meaning users who imported `ultracite/eslint/nestjs` got 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 across `dependencies` and `devDependencies`, in `package.json`.
- `suspicious/useDeprecatedDate` → `"off"` — GraphQL-only convention requiring a `deletionDate` argument on `@deprecated`; too opinionated for the default preset.
- 9a2b548: Pin `@angular-eslint/eslint-plugin` to `^21.3.1` in `packages/cli/package.json`. Previously declared as `"latest"`, which defeats lockfile reproducibility and means each `bun install` could 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.mjs` now enforces `complexity`, `no-unused-private-class-members`, `sort-keys`, `sort-vars`, and full `prefer-destructuring` (object + array). `typescript.mjs` now enforces `no-confusing-void-expression`, `no-misused-promises`, `prefer-readonly`, `strict-boolean-expressions`, and sets `return-await: ["error", "always"]`. `import.mjs` now sets `consistent-type-specifier-style: ["error", "prefer-top-level"]`.
**next** — added `next-env.d.ts` override that disables `import-x/no-unassigned-import` on the generated file.
**remix** — added `routeTree.gen.ts` override that disables `unicorn/filename-case` and `unicorn/no-abusive-eslint-disable` on the generated file.
**react** — disabled `react/jsx-boolean-value`, `react/no-unknown-property`, and `react/only-export-components` to match oxlint.
**jest** — broadened test globs to `**/*.{test,spec}.{ts,tsx,js,jsx}` + `**/__tests__/**/*.{ts,tsx,js,jsx}` (previously missed `*.spec.*` and `__tests__/`). Disabled `no-empty-function` and `promise/prefer-await-to-then` in test scope. Disabled `jest/require-hook`, `jest/no-conditional-in-test`, `jest/no-hooks`, `jest/prefer-expect-assertions` to mirror oxlint's bun:test/mocking accommodations.
**vitest** — same test-glob broadening; same `no-empty-function` / `promise/prefer-await-to-then` test-scope disables. Removed the `prefer-importing-vitest-globals` and `prefer-to-have-been-called-times` disables (oxlint enforces these). Added `prefer-lowercase-title: off` and `valid-title: off` to resolve the documented conflict with `prefer-describe-function-title` (#665).
- 63f6a18: Drop the redundant `react-hooks/exhaustive-deps: "error"` override in `config/eslint/react/rules/react-hooks.mjs`. The dynamic-enable pattern already sets every non-deprecated `react-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-plugin` v8.
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.
---
# ultracite@7.8.0
Source: https://www.ultracite.ai/changelog/ultracite-7-8-0
### Minor Changes
- 4e2fea0: Add a dedicated `tanstack` framework 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 for `routes/` directories and the generated `routeTree.gen.ts`. Framework detection now maps `@tanstack/react-query`, `@tanstack/react-router`, and `@tanstack/react-start` to the new `tanstack` preset.
Two behavior changes for existing consumers: TanStack Query rules now live in the `tanstack` preset instead of `react`, so projects that relied on Query rules must opt into `tanstack`; and TanStack Router projects now resolve to the `tanstack` preset rather than `remix`.
### Patch Changes
- 51a2af0: Recognize `.biome.json` and `.biome.jsonc` as valid Biome config files across the CLI. `detectLinter`, the `doctor` command, and the Biome config resolver now match the dot-prefixed names alongside `biome.json`/`biome.jsonc`, following Biome's [documented configuration file resolution order](https://biomejs.dev/guides/configure-biome/#configuration-file-resolution). 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 `ignorePatterns` to the generated oxlint config at the root level so they are actually applied. Oxlint does not merge `ignorePatterns` through `extends` (see oxc-project/oxc#10223), so patterns set in the core preset were silently ignored. The generated config now sets `ignorePatterns: core.ignorePatterns` at 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`, and `jsdoc/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`, and `react/no-unstable-nested-components`
- Vitest: `vitest/padding-around-after-all-blocks`
- 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 `--pm` values and detected `packageManager` metadata are now runtime-validated against the supported package managers before dependency installation, preventing malicious project metadata from selecting an arbitrary executable.
---
# ultracite@7.8.1
Source: https://www.ultracite.ai/changelog/ultracite-7-8-1
### Patch Changes
- 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.
---
# ultracite@7.8.2
Source: https://www.ultracite.ai/changelog/ultracite-7-8-2
### 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`, 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.
---
# ultracite@7.8.3
Source: https://www.ultracite.ai/changelog/ultracite-7-8-3
### Patch Changes
- 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.
---
# ultracite@7.8.4
Source: https://www.ultracite.ai/changelog/ultracite-7-8-4
### Patch Changes
- e4ddd22: Ignore `.yarn` directories by default
- a1d5c06: Configure Oxfmt to never wrap prose (`proseWrap: "never"`)
- df709a4: Ignore `.wrangler` and `.wrangler-dry-run` output directories by default
---
# ultracite@7.9.0
Source: https://www.ultracite.ai/changelog/ultracite-7-9-0
### 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` (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](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: 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: Sort `package.json` keys when using Biome
---
# ultracite@7.9.1
Source: https://www.ultracite.ai/changelog/ultracite-7-9-1
### Patch Changes
- 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.
---
# ultracite@7.9.2
Source: https://www.ultracite.ai/changelog/ultracite-7-9-2
### Patch Changes
- 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.
---
# ultracite@7.9.3
Source: https://www.ultracite.ai/changelog/ultracite-7-9-3
### Patch Changes
- 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.
---
# ultracite@7.9.4
Source: https://www.ultracite.ai/changelog/ultracite-7-9-4
### Patch Changes
- 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: 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: 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.
---
# v5.5.4
Source: https://www.ultracite.ai/changelog/v5-5-4
#### 🐛 Bug Fix
- Potential fix for code scanning alert no. 13: Workflow does not contain permissions [#297](https://github.com/haydenbleasel/ultracite/pull/297) ([@haydenbleasel](https://github.com/haydenbleasel))
- Potential fix for code scanning alert no. 12: Workflow does not contain permissions [#298](https://github.com/haydenbleasel/ultracite/pull/298) ([@haydenbleasel](https://github.com/haydenbleasel))
#### Authors: 1
- Hayden Bleasel ([@haydenbleasel](https://github.com/haydenbleasel))
---
# v5.5.5
Source: https://www.ultracite.ai/changelog/v5-5-5
#### ⚠️ Pushed to `main`
- Remove unused deps ([@haydenbleasel](https://github.com/haydenbleasel))
#### Authors: 1
- Hayden Bleasel ([@haydenbleasel](https://github.com/haydenbleasel))
---
# Introduction
Source: https://www.ultracite.ai/docs
Ultracite is a highly opinionated, zero-configuration preset for JavaScript and TypeScript linting and formatting. It supports three major toolchains:
- **[Oxlint](https://oxc.rs/docs/guide/usage/linter.html) + [Oxfmt](https://oxc.rs/docs/guide/usage/formatter.html)** — The fastest linter available, 50-100x faster than ESLint (recommended)
- **[Biome](https://biomejs.dev/)** — The modern, all-in-one toolchain written in Rust
- **[ESLint](https://eslint.org/) + [Prettier](https://prettier.io/) + [Stylelint](https://stylelint.io/)** — The most mature and comprehensive linting ecosystem
Install Ultracite quickly by running:
```package-install
npx ultracite init
```
Then follow the [Usage](/docs/usage) guide to get started, or check out [Setup](/docs/setup) for more granular control.
Coming from an existing setup? There are step-by-step guides for migrating from [ESLint](/docs/migrate/eslint), [Prettier](/docs/migrate/prettier), [Stylelint](/docs/migrate/stylelint), [Biome](/docs/migrate/biome), and [Oxlint](/docs/migrate/oxlint).
## How does Ultracite work?
Once set up, Ultracite runs mostly in the background — automatically formatting your code and applying fixes every time you save your files. Because the underlying tools are highly optimized (especially the Rust-based Biome and Oxlint), running Ultracite's checks is extremely fast and can comfortably run on every save without lag. This means you can focus on building and shipping instead of manually correcting style issues or debugging runtime errors.
## Goals
Ultracite's goals from a development perspective are:
### Lightning-fast performance
Ultracite benefits from the performance of Rust-based tools like [Biome](https://biomejs.dev/) and [Oxlint](https://oxc.rs/), enabling instant feedback even on large codebases.
### Zero-config by design
Ultracite is designed to be zero-config by default. This allows new users to get started quickly without needing to configure their linter or formatter, saving teams time when onboarding new developers.
The goal is to provide a default configuration that works for most projects, while still allowing customization for those who need it.
### Intuitive and simple
Ultracite should be as invisible as possible. Preferably, it should not require any configuration or action from the user. When feedback is needed, it should be easy to understand and act on.
### Maximum type safety
Ultracite is designed to be as type-safe as possible. It uses TypeScript's strict mode and additional lint rules to catch errors and provide suggestions for improvements.
### Plays nice with others
Ultracite works alongside other tools and libraries without conflict. You can choose the toolchain that best fits your project's needs.
## Next steps
- Run checks from the command line and your editor with the [Usage](/docs/usage) guide.
- Enforce clean commits with [Git hooks](/docs/git-hooks), or set Ultracite up across a [monorepo](/docs/monorepos).
- Wire up your AI tooling with editor [rules](/docs/ai/rules), [hooks](/docs/ai/hooks), and [skills](/docs/ai/skills).
- Upgrading from an older major? Follow the guides for [v5](/docs/upgrade/v5), [v6](/docs/upgrade/v6), and [v7](/docs/upgrade/v7).
- Stuck on something? Check the [FAQ](/docs/faq) and [Troubleshooting](/docs/troubleshooting) pages.
- Keep up with new releases on the [changelog](/changelog).
---
# Agent Hooks
Source: https://www.ultracite.ai/docs/ai/hooks
Ultracite can automatically format and fix code after AI coding assistants make edits through hooks. This ensures all AI-generated code adheres to your project's standards without manual intervention.
The hooks work alongside your linter's formatting. After an AI coding assistant edits a file, the hook automatically runs your project's `fix` script (which runs `ultracite fix`) to format and fix auto-fixable linting issues. This dual approach ensures both intelligent code generation (through AI rules) and automated code quality (through hooks).
> **Note:** Hooks are separate from AI coding rules. The `--agents` flag configures AI coding rules, while the `--hooks` flag sets up automatic formatting after file edits.
## Setup
Some tools like Cursor, Windsurf, CodeBuddy, Claude Code, and GitHub Copilot support hooks that run after AI agents edit files. Ultracite can configure these hooks automatically.
### Automatic Setup
When you run `npx ultracite init`, you'll be prompted to select which editor hooks you want to enable:
```bash
? Which agent hooks do you want to enable (optional)?
◯ Cursor
◯ Windsurf
◯ CodeBuddy
◯ Claude Code
◯ GitHub Copilot
```
This will create the relevant hook configuration file in your project directory.
Ultracite writes the following files:
- Cursor: `.cursor/hooks.json`
- Windsurf: `.windsurf/hooks.json`
- CodeBuddy: `.codebuddy/settings.json`
- Claude Code: `.claude/settings.json`
- GitHub Copilot: `.github/hooks/ultracite.json`
### Manual Setup
If you want to manually set things up or add hooks after initialization, run:
```bash
npx ultracite init --hooks cursor windsurf codebuddy claude copilot
```
Alternatively, you can manually create or edit the hook configuration files in your project directory and add the appropriate hook command.
## How It Works
1. **Automatic Execution**: After the AI agent edits a file, the hook automatically runs your project's `fix` script (added to `package.json` during init). On Biome projects, the hook passes `--skip=correctness/noUnusedImports` to avoid removing imports mid-edit.
2. **Code Formatting**: Ultracite formats the edited code according to your linter configuration
3. **Linting Fixes**: Auto-fixable linting issues are resolved automatically
4. **Seamless Integration**: The process happens transparently without interrupting your workflow
## Benefits
Using Ultracite editor hooks provides several advantages:
- **Consistency**: All AI-generated code is automatically formatted to match your style
- **Quality**: Linting issues are fixed immediately after code generation
- **Efficiency**: No need to manually run formatters or linters after AI edits
- **Standards**: Ensures AI-generated code always adheres to project standards
- **Clean Commits**: Code is properly formatted before you even review it
## Customization
Ultracite intelligently merges with existing hook configurations:
- **Preserves existing hooks**: All existing hooks and their commands remain intact
- **Avoids duplicates**: If Ultracite is already configured, it won't be added again
- **Non-destructive**: Your existing hook configuration structure is maintained
You can also customize the hook behavior by modifying the hook configuration files directly if you need different formatting commands or additional post-edit actions.
---
# Agent Rules
Source: https://www.ultracite.ai/docs/ai/rules
Ultracite provides seamless integration with AI coding assistants by automatically generating editor-specific rule files. These rules help guide AI assistants to write better, more consistent code that follows best practices.
The editor rules work alongside your linter's formatting and linting. While your linter handles code formatting and catches errors, the editor rules guide AI assistants to write better code from the start, reducing the need for fixes later.
The generated rules intentionally focus on code quality and implementation guidance instead of hardcoding formatter-specific settings like line width, quote style, or trailing commas. That keeps the rules portable across repositories while still letting each project's configured formatter stay in charge.
This dual approach ensures both automated code quality (through linting) and intelligent code generation (through AI coding rules).
## Setup
### Automatic Setup
When you run `npx ultracite init`, you'll be prompted to select which agent files you want to add:
```bash
? Which agent files do you want to add (optional)?
◯ Universal (creates AGENTS.md for Codex, Jules, Devin, and more)
◯ Claude (creates .claude/CLAUDE.md)
◯ Replit (creates replit.md)
# ... and more
```
This will create the relevant rule file(s) in your project directory.
### Manual Setup
If you want to manually set things up, create the relevant file in your project directory. You can find the rule file location for each agent on their respective pages. Then, copy and paste [this content](https://github.com/haydenbleasel/ultracite/blob/main/packages/cli/src/data/rules.ts) into the file.
## Supported Agents
Ultracite supports a wide range of AI coding assistants. Check the **Agents** section in the navigation bar for the full list of supported agents, including setup instructions and configuration details for each one.
## Reusable Skills
If your AI tool supports installable reusable skills, see the [Agent Skills](/docs/ai/skills) guide. The global Ultracite skill gives you the same baseline guidance across repositories while leaving formatting decisions to each repo's configured linter and formatter.
## Benefits
Using Ultracite editor rules provides several advantages:
- **Consistency**: All AI-generated code follows the same conventions
- **Quality**: Rules enforce best practices and prevent common mistakes
- **Accessibility**: Built-in accessibility guidelines ensure inclusive code
- **Performance**: Rules promote efficient patterns and avoid anti-patterns
- **Security**: Guidelines help prevent common security vulnerabilities
## Customization
While the default rules are comprehensive, you can customize them for your specific needs:
1. **Modify existing rules**: Edit the rule files directly
2. **Add project-specific rules**: Append additional guidelines
3. **Disable rules**: Remove or comment out rules that don't apply to your project
---
# Agent Skills
Source: https://www.ultracite.ai/docs/ai/skills
Ultracite supports two different AI guidance layers:
1. Repo-local agent rules generated by `npx ultracite init --agents ...`
2. A reusable Ultracite skill you can install once and carry across repositories
Use the global skill when your AI tool understands `SKILL.md`-style skills and you want a shared Ultracite baseline without copying the same instructions into every repo by hand.
## Install the skill
If you already run `npx ultracite init`, the interactive setup can offer to install the skill for you. For non-interactive flows, you can also pass:
```bash
npx ultracite init --install-skill
```
If your AI tool supports installable skills, you can always add Ultracite directly with:
```bash
npx skills add haydenbleasel/ultracite
```
This installs the reusable skill bundle from the repository so compatible tools can load it as a shared capability.
## What the skill includes
The installable skill ships with:
- `skills/ultracite/SKILL.md` for the main workflow and guidance
- `skills/ultracite/references/code-standards.md` for the detailed standards reference
The skill is designed to help an agent:
- detect when Ultracite is present in a project
- choose the active linter stack
- use the right `ultracite check`, `fix`, and `doctor` commands
- follow Ultracite's code quality, accessibility, performance, and testing standards
## Formatting stays project-local
The global skill intentionally does not hardcode formatter-specific settings such as line width, quote style, semicolons, or trailing commas.
Those details should come from the repository's configured linter and formatter instead:
- Biome projects should follow `biome.jsonc`
- ESLint projects should follow ESLint plus Prettier and Stylelint
- Oxlint projects should follow Oxlint plus Oxfmt
That keeps one global skill portable across multiple repositories without forcing every repo to share the same formatting choices.
## How it fits with repo instructions
The global skill is a baseline, not a replacement for repo-specific instructions.
Use repo-local files such as `AGENTS.md`, `CLAUDE.md`, `replit.md`, or other agent-specific config when you need to add:
- architecture decisions for a single codebase
- framework or deployment details
- project-specific naming or file layout rules
- workflow notes that only apply to one repository
In practice, the best setup is usually:
1. Install the global Ultracite skill once
2. Add repo-local Ultracite agent rules where your tool supports them
3. Let the repository's formatter config control formatting details
## When to use which option
Choose repo-local agent rules when you want committed instructions inside a specific repository and need every collaborator or cloud task to inherit the same contract.
Choose the global skill when you want Ultracite available everywhere by default and prefer to keep formatting and project specifics in each repository's own configuration.
---
# Configuration
Source: https://www.ultracite.ai/docs/configuration
One of Ultracite's best features is that it's zero-config out of the box — you can just extend the base preset and get going. However, every project is different, and you might want to customize certain rules or adapt Ultracite for different frameworks.
## Framework Presets
Ultracite provides framework-specific configurations that you can extend in addition to the base `core` configuration. This allows you to add framework-specific linting rules without bloating the base config or dealing with irrelevant rules.
The concept is the same across all supported linters — pull in the `core` preset, then layer on any framework presets you need — though the exact syntax differs per linter (Biome uses an `extends` array, while ESLint and Oxlint use imports; see the [provider pages](/docs/provider/biome) for each linter's syntax). For example, if you're using Biome with React and Next.js, you can pull in the following presets:
```jsonc title="biome.jsonc"
{
"extends": [
"ultracite/biome/core",
"ultracite/biome/react",
"ultracite/biome/next",
],
}
```
## Default Configuration
When you include the `core` preset, you're pulling in Ultracite's base configuration. This preset includes framework-agnostic rules and settings. Some notable aspects:
- **TypeScript strictness**: Enables strict checks and lint rules requiring robust typing. Discourages use of `any`, requires handling of `null/undefined`, and prefers explicit types where needed.
- **Best practices**: Common rules like no unused vars, no explicit eval, no prototype pollution, etc.
- **Accessibility**: ARIA attributes, semantic HTML, keyboard navigation, and other a11y rules are enabled by default.
- **Formatting conventions**: 2-space indentation, 80-character line width, semicolons, trailing commas, and double quotes.
All these defaults aim to enforce consistent style and prevent common errors without manual configuration.
## Type-Aware Rules
Ultracite ships an optional `type-aware` preset for Biome that enables project-graph rules — `noPrivateImports`, `noUndeclaredDependencies`, `noUnresolvedImports`, `noImportCycles`, and `noDeprecatedImports`. These rules require Biome's scanner, so they're slower and shipped as a separate layer:
```jsonc title="biome.jsonc"
{
"extends": ["ultracite/biome/core", "ultracite/biome/type-aware"],
}
```
You can also enable this at setup time with `npx ultracite init --type-aware`. For Oxlint, the same flag installs `oxlint-tsgolint` for type-aware linting instead.
## Safe Fixes
Most Ultracite rules only report errors — they don't automatically modify your code. However, a few rules are configured with `"fix": "safe"`, meaning they will auto-fix when you run `ultracite fix`. These fixes are non-breaking and safe to apply automatically:
| Rule | Description |
| -------------------- | ----------------------------------------------------- |
| `noUnusedImports` | Removes unused import statements |
| `useBlockStatements` | Wraps single-line control flow bodies in curly braces |
| `useSortedClasses` | Sorts Tailwind CSS classes into a consistent order |
If you want to disable auto-fixing for any of these, override the rule in your config and remove the `fix` property.
## Overriding Rules
Each linter has its own way to disable or modify rules. For example, to disable the `useButtonType` rule for Biome, you can do the following:
```jsonc title="biome.jsonc"
{
"extends": ["ultracite/biome/core"],
"linter": {
"rules": {
"a11y": {
"useButtonType": "off",
},
},
},
}
```
---
# FAQ
Source: https://www.ultracite.ai/docs/faq
## Q: What exactly is Ultracite – how is it different from Biome or ESLint?
Ultracite is essentially a preset configuration built on top of an existing toolchain. Think of Ultracite as a curated bundle of rules and settings, whereas the underlying engine — [Biome](/docs/provider/biome), [ESLint + Prettier + Stylelint](/docs/provider/eslint), or [Oxlint + Oxfmt](/docs/provider/oxlint) — is what actually formats / lints code. You can use any of those tools by themselves, but you’d have to decide which rules to enable and configure their options manually. Ultracite saves you that effort by providing a ready-to-go setup that uses best practices from across the ecosystem.
Compared to ESLint + Prettier, Biome and Oxlint are faster thanks to their Rust implementations, and Biome is unified (one tool instead of two or three). If you already love tweaking every ESLint rule, Ultracite might feel restrictive; but it aims to eliminate the need for that and adopt sensible defaults.
In short: Biome / ESLint / Oxlint is the engine (linter / formatter), Ultracite is the configuration.
## Q: Do I still need ESLint or Prettier if I use Ultracite?
It depends on which provider you choose. With the default Oxlint + Oxfmt provider (or the Biome provider), Ultracite replaces the functionality of ESLint and Prettier for your Javascript / Typescript code — you do not need to run them at all, and it’s recommended to remove those configs to avoid conflicts (init does this automatically). Ultracite’s output will cover most of the formatting and linting that those tools did, usually with equivalent or stricter rules.
If you prefer to stay in the ESLint ecosystem — for example, because you rely on a specialized ESLint plugin — you can choose Ultracite’s [ESLint + Prettier + Stylelint provider](/docs/provider/eslint) instead, which gives you the same curated preset on top of those tools.
## Q: What about my non-JS/TS files? Does Ultracite handle those?
Ultracite, via Biome, provides various levels of linting and formatting support for JavaScript, TypeScript, JSX, JSON, CSS and GraphQL. See the [Languages](/docs/languages) page for a full breakdown per provider.
## Q: How often is Ultracite updated?
Ultracite is updated as needed, often following Biome’s release cycle. Since Biome is still evolving, you might see frequent minor releases to Ultracite. These updates can bring new rules, bug fixes, or adjustments to defaults. Given it’s pinned via `-E`, you won’t get surprise updates unless you choose to upgrade.
It’s a good idea to watch the Ultracite repo for releases or check the [Releases](https://github.com/haydenbleasel/ultracite/releases) page. When updating Ultracite, read release notes – occasionally a new rule might be enabled that could surface new warnings in your project (which is a good thing for catching issues, but should be aware of it).
Each release is verified against specific linter versions, and release notes state the minimum version required whenever that floor moves. To update Ultracite and your linter together, run `npx ultracite upgrade` — see [Upgrading](/docs/usage#upgrading). `npx ultracite doctor` tells you if the two have drifted apart.
## Q: If I disagree with a rule Ultracite enforces, what should I do?
You have a few options:
- Configure it off or to a different level in your `biome.jsonc` (quick fix for your project).
- Open a [discussion](https://github.com/haydenbleasel/ultracite/discussions/) on GitHub repo if the rule should be adjusted for everyone. Perhaps the maintainers might agree it’s too strict or could be optional.
- If it’s a stylistic thing, remember the goal of Ultracite is to have convention over configuration – sometimes it’s worth adapting to the tool’s style for consistency across projects. But of course, your project’s needs come first.
Ultimately, you control your project’s lint config. Ultracite is a starting point; feel free to mold it, but ideally in minor ways. If you find yourself turning off a majority of rules, then Ultracite might not be the right preset for your team’s preferences (though that would be uncommon).
In that case, you could build your own Biome config from scratch, but you’d lose a lot of the convenience. Usually, a few tweaks is all that’s needed to make Ultracite fit nicely.
## Q: Can I use Ultracite without VS Code / Cursor / Windsurf?
Yes — we focus on VS Code and its forks as they're the most popular IDEs for modern web development, but Biome can be used purely via CLI or with other IDEs.
Check out Biome's [first-party](https://biomejs.dev/guides/editors/first-party-extensions/) and [third-party](https://biomejs.dev/guides/editors/third-party-extensions/) editor integrations to learn more.
## Q: How do I know what rules Ultracite is enforcing? Is there a list?
Yes, check the [Biome configs](https://github.com/haydenbleasel/ultracite/tree/main/packages/cli/config/biome), [Oxlint configs](https://github.com/haydenbleasel/ultracite/tree/main/packages/cli/config/oxlint), and [ESLint configs](https://github.com/haydenbleasel/ultracite/tree/main/packages/cli/config/eslint) in the GitHub repo for the rules that are enabled. Each framework (core, React, Next.js, etc.) has its own config file that extends the core ruleset.
## Q: Can Ultracite fix all issues it finds?
Not all, but many. Ultracite will auto-fix issues that are safe and deterministic to fix. These include formatting issues and many lint errors (particularly stylistic or simple code transformations like removing unused imports, adding missing parentheses, changing `==` to `===`, etc.).
Some fixes are available but intentionally require `--unsafe` because they may change behavior. For example, Ultracite enables Biome's `noSubstr` rule, but rewriting `substring()` or `substr()` to `slice()` only happens when you run `ultracite fix --unsafe`.
More complex issues (business logic or things that require developer intention) are left for you to fix. For example, it won’t magically rename variables to follow a naming convention or add missing error handling code – it will just warn you.
The philosophy is similar to ESLint’s: provide fixes where possible, but don’t risk altering code behavior. Always review the Problems panel or CLI output for any remaining warnings after auto-fix.
## Q: Where can I learn more about Biome (the tool Ultracite uses)?
[Biome](https://biomejs.dev/) has its own website with documentation, and you can find more technical details there. If you’re curious about how it formats code or the philosophy behind certain choices, the Biome docs are the best resource.
Additionally, there are blog posts and community articles about Biome’s rise as a successor to Rome. Understanding Biome can help you better understand Ultracite’s capabilities. However, you don’t need to learn Biome in-depth to use Ultracite effectively – Ultracite’s goal is to abstract those details away for most users.
## Q: How do I disable Ultracite for a specific project or file?
If you have a project where you temporarily don't want Ultracite, you can simply not include the `extends: ["ultracite/biome/core"]` in `biome.jsonc` (or remove the config file). If the VS Code extension is installed, it may still try to format on save using Biome's defaults.
To fully disable, you could turn off `formatOnSave` or uninstall the Biome extension for that workspace. For a specific file, as mentioned, use ignore comments or patterns. Essentially, Ultracite is opt-in per project via the config. If it's not configured, it won't run (Biome itself might still run formatting if triggered, but not linting rules).
## Q: I'm getting a corepack error during installation – what should I do?
Some users have encountered signature verification errors when running `pnpm dlx ultracite init` with corepack, particularly on Node.js v22 with older corepack versions. The error typically looks like "Cannot find matching keyid" during package installation.
Here are the recommended solutions:
- **Update corepack**: Upgrade to corepack version 0.34.0 or later. You can do this with `corepack prepare pnpm@latest --activate` or by following the [pnpm corepack setup guide](https://pnpm.io/installation#using-corepack).
- **Update Node.js**: If you're on Node.js v20.x, consider upgrading to v22 or later, which includes a more recent corepack version.
- **Use npx instead**: If corepack continues to cause issues, you can use `npx ultracite init` instead of `pnpm dlx ultracite init`.
If none of these work, please open an issue on the [Ultracite GitHub repo](https://github.com/haydenbleasel/ultracite/issues) with details about your Node.js and corepack versions.
---
We hope these FAQs clear up common points of confusion. If you have a question that isn't answered here, feel free to reach out on the project's GitHub or community channels. Ultracite is here to make your developer life easier – so feedback and questions are always welcome to help improve it!
---
# Git Hooks
Source: https://www.ultracite.ai/docs/git-hooks
Ultracite integrates with popular Git hook tools to automatically format and lint your code before every commit. This ensures all committed code follows your project's standards without manual intervention.
## Setup
During initialization, you can select which Git hook tool to use:
```bash
npx ultracite init --integrations husky lint-staged
```
Or select them interactively when prompted.
## Supported Tools
### Husky
[Husky](https://typicode.github.io/husky/) is a popular tool for managing Git hooks. Ultracite adds a marker-wrapped section to your `.husky/pre-commit` file that runs `ultracite fix` on your staged files, re-stages them, and fails the commit if any issues couldn't be auto-fixed:
```bash title=".husky/pre-commit"
# ultracite
#!/bin/sh
# Check if there are any staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)
if [ -z "$STAGED_FILES" ]; then
echo "No staged files to format"
exit 0
fi
# Run formatter, capturing the exit code so we can still re-stage and report
FORMAT_EXIT_CODE=0
npx ultracite fix || FORMAT_EXIT_CODE=$?
# Re-stage files that were already staged
echo "$STAGED_FILES" | while IFS= read -r file; do
if [ -f "$file" ]; then
git add -- "$file"
fi
done
if [ $FORMAT_EXIT_CODE -ne 0 ]; then
echo "Ultracite found issues that could not be auto-fixed."
exit $FORMAT_EXIT_CODE
fi
echo "✨ Files formatted by Ultracite"
# ultracite end
```
Anything you've added to the hook outside the `# ultracite` markers is preserved when Ultracite updates it. If you also select lint-staged, the hook runs lint-staged instead of the script above.
### lefthook
[lefthook](https://lefthook.dev/) is a fast Git hooks manager written in Go. Ultracite creates a `lefthook.yml` configuration:
```yaml title="lefthook.yml"
pre-commit:
jobs:
- run: npx ultracite fix
glob:
- "**/*.js"
- "**/*.jsx"
- "**/*.ts"
- "**/*.tsx"
- "**/*.json"
- "**/*.jsonc"
- "**/*.css"
stage_fixed: true
```
### lint-staged
[lint-staged](https://github.com/okonet/lint-staged) runs linters only on staged files. Ultracite adds configuration to your existing lint-staged config (or `package.json`), or creates a `.lintstagedrc.json` file:
```json title="package.json"
{
"lint-staged": {
"*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": ["npx ultracite fix"]
}
}
```
Note: lint-staged is typically used alongside Husky or lefthook to trigger the pre-commit hook.
### pre-commit
[pre-commit](https://pre-commit.com/) is a Python-based framework for managing Git hooks. Ultracite creates a `.pre-commit-config.yaml`:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: local
hooks:
- id: ultracite
name: ultracite
entry: npx ultracite fix
language: system
types_or: [javascript, jsx, ts, tsx, json, css]
pass_filenames: false
```
After setup, run `pre-commit install` to activate the hooks.
## How It Works
1. You make changes and stage files with `git add`
2. You run `git commit`
3. The pre-commit hook runs `npx ultracite fix`
4. Code is formatted and auto-fixable issues are resolved
5. The commit proceeds with properly formatted code
## Benefits
- **Consistency**: All committed code follows the same standards
- **Automation**: No need to remember to format code manually
- **Clean History**: Formatting issues never enter your repository
- **Team Collaboration**: Everyone follows the same rules automatically
## Bypassing Hooks
In rare cases where you need to skip the pre-commit hook:
```bash
git commit --no-verify
```
Use this sparingly, as it bypasses the automated formatting.
---
# Language Support
Source: https://www.ultracite.ai/docs/languages
Each of the tools Ultracite wraps has a different coverage story. Biome and Oxlint/Oxfmt are Rust-based and lean on what their own parsers natively support. ESLint and Prettier lean heavily on their plugin ecosystems, which means wider coverage but more moving parts. Stylelint is CSS-focused by design.
This page summarises what each tool supports natively today so you can choose a toolchain that fits the languages your project actually uses.
## Legend
| Symbol | Meaning |
| ------ | ----------------------------------------------------- |
| ✅ | Full, stable native support |
| 🟡 | Experimental or partial (e.g. `