The strict Biome config, in one line of extends
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": [
"ultracite/biome/core",331 rules
"ultracite/biome/react",12 rules
"ultracite/biome/next"7 rules
]
}- lineWidth
- 80
- semicolons
- "always"
- trailingCommas
- "es5"
- formatWithErrors
- true
- organizeImports
- "on"
- useSortedClasses
- "error"
Terminal
$ npx ultracite fix
src/component.tsx:42:27 lint/performance/noJsxPropsBind
× This function will be recreated on every render. Pass stable function references as props to avoid unnecessary rerenders.
> 42 │ onChange={() => onToggle(task.id)} │ ^^^^^^^^^^^^^^^^^^^^^^^
src/utils.ts:62:14 lint/performance/noAwaitInLoops
Checked 7 files in 7ms. Fixed 6 files.
Found 2 errors.
215 rules by default. 331 with Ultracite.
Ultracite keeps all but two of Biome’s recommended rules, then turns on most of the style, complexity and performance rules Biome leaves off. They catch what agents get wrong: barrel files, nested ternaries, awaits inside loops and forEach where for…of would do.
- Rules in Biome 2.5
- 565
- On by default, from Biome’s recommended set
- 215
- On in Ultracite’s core preset, before any framework rules
- 331
SuspiciousCode that’s likely wrong or useless
101 / 121
CorrectnessCode that’s guaranteed to be wrong or useless
59 / 100
StyleOne consistent, idiomatic way to write it
72 / 100
ComplexityCode that could be simpler
45 / 51
A11yAccessibility problems in JSX and HTML
37 / 39
PerformanceCode that could run faster
11 / 16
SecurityPotential security flaws
5 / 7
NurseryRules still in development
1 / 131
- safe fix, applied by fix
- 72
- unsafe fix, with --unsafe
- 73
- no fix, for the agent
- 186
- type-aware, opt-in
- 6
Errors, never warnings
All 331 are set to error, including the recommended rules Ultracite keeps, because an agent takes a zero exit code as done and a warning doesn’t change it.
6 rules that read your project
The type-aware preset adds rules like noImportCycles, noUnresolvedImports and noDeprecatedImports. They need Biome to scan your whole project first, so they’re opt-in: init --type-aware adds the preset.
biome rage --linter. Groups are drawn to one scale. Biome also turns on a framework’s recommended rules when it finds that framework in your dependencies; Ultracite’s framework presets set those rules explicitly.Lint, format and sort in one process
On Biome, ultracite check is one command that lints, checks formatting and checks sorting, spread across every core. The ESLint toolchain runs ESLint, Prettier and Stylelint one after another, in Node.
42 files
Biome
ESLint + Prettier + Stylelint
420 files
Biome
ESLint + Prettier + Stylelint
- Faster than the ESLint toolchain on 420 files
- 41×
- Added on Biome going from 42 to 420 files
- +122ms
- Added on ESLint for the same growth
- +11.6s
ultracite check on an Apple M1 Pro, through each toolchain’s core preset: Biome 2.5.15 against ESLint 10.12.0, Prettier 3.9.10 and Stylelint 17.16.0, on the repo’s benchmark fixture copied to 42 and 420 files. Times include starting Node and the CLI. How Oxlint compares.Formatting and sorting from the same binary
Biome’s formatter is built to match Prettier’s output, and its assist actions sort code instead of just reporting it. Ultracite turns on nine of them, so the import order, class order and key order an agent writes never come up in review.
As written
import { cn } from '@/lib/utils'
import { Slot } from '@radix-ui/react-slot'
import type { ReactNode } from 'react'
export function Button({ asChild, children }: { asChild?: boolean, children: ReactNode }) {
const Comp = asChild ? Slot : 'button'
return <Comp className={cn('text-sm px-4 bg-primary hover:bg-primary/90 rounded-md h-10 font-medium')}>{children}</Comp>
}After ultracite fix
import { Slot } from "@radix-ui/react-slot";
import type { ReactNode } from "react";
import { cn } from "@/lib/utils";
export function Button({
asChild,
children,
}: {
asChild?: boolean;
children: ReactNode;
}) {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(
"h-10 rounded-md bg-primary px-4 font-medium text-sm hover:bg-primary/90"
)}
>
{children}
</Comp>
);
}- organizeImports
- Imports by distance: packages first, then your
@/aliases, then relative paths, A–Z within each. - useSortedClasses
- Tailwind classes sorted in
class,classNameandcn,clsx,cva,tw,twMerge,twJoinandtvcalls. Biome’s order puts variants likehover:last. - useSortedKeys
- Object keys, JSX attributes, interface members, CSS properties and package.json fields, in order.
checkfails on any that aren’t. - formatWithErrors
- On, so a file with a syntax error still gets formatted. Biome leaves it off by default.
Safe fixes, tuned for agents that edit in steps
Biome applies only its safe fixes unless you pass --unsafe. Ultracite makes three more safe so they run on save, and its agent hook holds one of them back.
Unsafe in Biome, safe in Ultracite
Applied by fixnoUnusedImportsDeletes imports nothing in the file usesuseBlockStatementsAdds braces to a one-line if, else, for or while bodyuseSortedClassesSorts Tailwind classes in class names and cn() calls
Skipped by the agent hook
Since 7.3.0An agent adds an import in one edit and the code that uses it in the next. A hook that ran fix between them deleted the import as unused, and the next edit broke. On Biome, the hook init writes now runs:
$ npx ultracite fix --skip=correctness/noUnusedImports --hookWhere it came from. A Claude Code user reported the race in January 2026 (#483). Unused imports are still removed when you save or run ultracite fix yourself, and check still fails on them.
The same rules in your editor, your agent and CI
init points your editor at Biome and tells your agents how to run it, so a file passes or fails the same way wherever it’s checked.
{ "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, "editor.codeActionsOnSave": { "source.fixAll.biome": "explicit", "source.organizeImports.biome": "explicit" }, "editor.formatOnSave": true }VS Code, Cursor, Devin Desktop
Fix and format on save
initmakes Biome the formatter for 14 languages, from TypeScript and CSS to GraphQL and Vue, and applies its safe fixes and import sorting when you save."TSX": { "code_actions_on_format": { "source.fixAll.biome": true, "source.organizeImports.biome": true }, "formatter": { "language_server": { "name": "biome" } } }Zed
Fix as you format
Zed formats JavaScript, TypeScript and TSX through Biome’s language server, applying fixes and sorting imports as it goes.
Terminal
$ npx ultracite check
src/api.ts:1:1 assist/source/organizeImports FIXABLE
src/component.tsx:42:27 lint/performance/noJsxPropsBind
src/utils.ts:5:56 assist/source/useSortedKeys FIXABLE
…
Found 10 errors.
Coding agents
Every problem names its fix
Biome marks what it can fix
FIXABLE, so an agent can tell whatultracite fixwill settle from what’s left for it.initwrites the rules intoAGENTS.md, which all 40 agents read.
Watch the switch from ESLint
Two community walkthroughs of replacing ESLint and Prettier with Ultracite’s Biome preset in a real project.
The EASIEST Way To Switch From ESLint & Prettier to Biome — UltraciteBetter Stack
This New Tool Made Me Delete ESLint Without RegretOrcDev
Biome questions, answered
- What does Ultracite add on top of Biome’s defaults?
- Biome turns on 215 rules from its recommended set. Ultracite’s core preset turns on 331: it keeps every default except
noAutofocusandnoImportantStyles, sets each rule it touches toerror, and turns on nine assist actions that sort imports, object keys, JSX attributes and more. The React preset adds 12 rules and Next.js 7.initalso writes editor settings for VS Code and Zed,AGENTS.mdfor coding agents, and optional post-edit hooks. - How do I turn off a rule?
- Set it in
linter.rulesin yourbiome.jsonc, under its group:"style": { "noNestedTernary": "off" }. Your own settings apply after the presets inextends, so they win. For one line, add// biome-ignore lint/style/noNestedTernary: <reason>above it; Biome requires the reason. - Do I still need Prettier?
- No. Biome formats JavaScript, TypeScript, JSX, JSON, CSS and GraphQL itself, and Ultracite sets it to Prettier’s style: 80 columns, double quotes, semicolons and ES5 trailing commas. Biome doesn’t run Prettier plugins, so if you depend on one, pick Ultracite’s ESLint provider, which uses Prettier.
- Should I use Biome or Oxlint?
- Both are native and fast. In our benchmark, Biome checked 42 files in 257 ms to Oxlint’s 340 ms, because it lints and formats in one process; at 420 files Oxlint was slightly ahead, 344 ms to 379 ms. Pick Biome for one tool and one config file with sorting built in. Pick Oxlint for more rules (474 in its core preset to Biome’s 331), ESLint’s rule names and plugins, and type-aware rules on typescript-go.
- Does it lint Vue, Svelte and Astro files?
- Yes. The Vue, Svelte and Astro presets turn on Biome’s
html.experimentalFullSupportEnabled, which Biome describes as full support for those files, and adjust rules for how each framework works: Svelte and Astro imports used only in markup aren’t reported as unused, for instance. Biome marks that support experimental; for mature template linting, the ESLint provider uses each framework’s own ESLint plugin. - How do I switch from ESLint and Prettier?
- Run
npx ultracite init --linter biome. It removes the ESLint, Prettier and Stylelint packages and config files it would have installed for those tools, writesbiome.jsonc, and merges into your.vscode/settings.jsonrather than replacing it. To carry custom ESLint rules across, Biome’s ownbiome migrate eslint --writemaps them to Biome’s names. - Does it support type-aware rules?
- Biome reads types itself, without the TypeScript compiler. Install with
npx ultracite init --linter biome --type-awareto add thetype-awarepreset, whose 6 rules need Biome to scan the whole project first:noPrivateImports,noUnresolvedImports,noImportCycles,noDeprecatedImports,useJsonImportAttributesanduseArraySortCompare. - How do I exclude files?
- Add negated globs to
files.includesin yourbiome.jsonc, after"**":["**", "!components/ui/**", "!public"]. Keep"**"first. Biome needs a positive glob to start from, so a list of only negated patterns matches no files at all. The core preset already leaves out build output, caches and generated files.
Keep going
- ReferenceConfigurationFramework presets, type-aware rules, safe fixes and overriding rules.
- GuideMigrate to UltraciteMove your own config onto Ultracite with your agent, all at once or progressively.
- GuideAgent hooksRun
ultracite fixafter every edit your agent makes, in 8 agents and editors. - ProvidersCompare the enginesOxlint, Biome and ESLint side by side: rules, speed, tradeoffs.
Ship less slop
One command sets up your linter, formatter, editor and agents. Works with Oxlint, Biome and ESLint.