Skip to content

Web Development · Tooling

Biome in 2026: One Tool to Replace ESLint and Prettier

Biome is a Rust-based toolchain that replaces ESLint and Prettier with one fast binary for linting, formatting, and imports. Here is what migrating looks like.

Anurag Verma

Anurag Verma

7 min read

Biome in 2026: One Tool to Replace ESLint and Prettier

Sponsored

Share

JavaScript toolchain overhead is a well-documented frustration. ESLint has hundreds of rules, plugins that conflict with each other, configs that need to stay in sync between ESLint and Prettier, and startup times that make pre-commit hooks feel sluggish on large projects. Every team maintains their own version of the same eslint.config.js + .prettierrc setup, copied from a previous project and tweaked slightly.

Biome is a single binary written in Rust that does linting, formatting, and import organization. No plugins. No peer dependencies. No config file synchronization between two tools. On most projects, it’s 10-20x faster than ESLint + Prettier for equivalent checks.

We’ve been using it on client projects since late 2025. This is what the switch looks like.

What Biome Covers

Biome covers linting with 200+ rules across JavaScript, TypeScript, JSX, TSX, CSS, and JSON, formatting that matches Prettier’s output on about 97% of its own test suite, and import sorting that replaces eslint-plugin-import for most projects. It also separates safe, semantically equivalent auto-fixes from unsafe ones that could change behavior, so you choose which category to apply automatically.

  • Linting: 200+ rules across JavaScript, TypeScript, JSX, TSX, CSS, and JSON. Equivalent to ESLint recommended + a TypeScript plugin.
  • Formatting: Prettier-compatible output. Files Biome formats should look identical to Prettier output (it passes ~97% of Prettier’s test suite).
  • Import organization: Sorts and groups imports; replaces eslint-plugin-import for most use cases.
  • Safe fixes: Many lint errors have an auto-fix. Biome distinguishes “safe fixes” (semantically equivalent changes) from “unsafe fixes” (may change behavior) and lets you choose which to apply.

What it doesn’t cover yet: complex ESLint plugins like eslint-plugin-react-hooks, custom rules for your business logic, or deep TypeScript type-aware lint rules (those require type information Biome doesn’t currently use).

Installation

npm install --save-dev --save-exact @biomejs/biome
npx biome init

biome init creates a biome.json config file. For most projects, the defaults need minimal adjustment:

{
  "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "trailingCommas": "all",
      "semicolons": "always"
    }
  },
  "organizeImports": {
    "enabled": true
  }
}

Biome reads .gitignore for file exclusions (useIgnoreFile: true), so you don’t need to duplicate ignore patterns.

Basic Usage

# Check everything (lint + format check)
npx biome check .

# Check with auto-fix
npx biome check --write .

# Format only
npx biome format --write .

# Lint only
npx biome lint .

# Check a specific file
npx biome check src/components/Button.tsx

Output is clear and fast:

src/api/users.ts:23:5 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ! Unexpected any. Specify a different type.

  21 │   async function fetchUser(id: string) {
  22 │     const response = await fetch(`/api/users/${id}`);
> 23 │     const data: any = await response.json();
     │                  ^^^
  24 │     return data;
  25 │   }

  ℹ Avoid the any type, which bypasses the type checker.

Found 1 error(s) in 1 file(s) in 42ms

On a mid-size React + TypeScript project (300 files), Biome runs in under 500ms on first run, under 200ms on subsequent runs. ESLint + Prettier on the same project takes 8-12 seconds.

Performance Comparison

Tool300-file TypeScript project1000-file project
ESLint + Prettier~10s~35s
Biome~400ms~1.2s
Biome (cached)~180ms~500ms

Times vary by machine and rule set, but the difference is consistent. The gap matters most for pre-commit hooks and CI: a 10-second lint step in a commit hook creates friction that gets disabled. A 400ms check doesn’t.

Migrating From ESLint and Prettier

Biome includes a migration command:

npx biome migrate eslint --write
npx biome migrate prettier --write

These read your existing configs, including ones set up following our ESLint 9 flat config migration guide, and convert what they can to biome.json. Not every ESLint rule has a Biome equivalent, so you’ll get a report of rules that couldn’t be migrated.

For most projects, the migration leaves you with Biome covering 80-90% of your previous rules. The remaining rules fall into three categories:

  1. Rules Biome already has under a different name: check the rules documentation.
  2. Plugin rules with no equivalent: evaluate if they’re actually catching bugs or just style preferences. Many plugin rules can be dropped without real impact.
  3. Custom rules: these need to stay in ESLint for now, or be rewritten as Biome plugins (the plugin API is still maturing).

For the transition period, you can run Biome and ESLint side by side: Biome for formatting and fast checks, ESLint only for the rules Biome doesn’t cover. This is less overhead than it sounds because ESLint’s startup time dominates, and running it over a smaller rule set is proportionally faster.

CI Integration

# .github/workflows/ci.yml
- name: Biome check
  run: npx biome ci .

biome ci is the CI-specific command: it doesn’t write files, exits with a non-zero code on any error, and produces output suited for CI logs. It also skips the terminal color codes that CI systems sometimes mangle.

VSCode Extension

Install the Biome VSCode extension for inline diagnostics and format-on-save:

// .vscode/settings.json
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.formatOnSave": true,
  "[javascript][typescript][javascriptreact][typescriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "editor.codeActionsOnSave": {
    "quickfix.biome": "explicit",
    "source.organizeImports.biome": "explicit"
  }
}

This replaces the Prettier and ESLint extensions for the file types Biome handles. For file types Biome doesn’t cover (Python, Markdown), the other extensions still work fine.

What We Kept in ESLint

After migrating four projects to Biome, we still run ESLint for two things:

eslint-plugin-react-hooks: The rules-of-hooks and exhaustive-deps rules catch a real class of React bugs. Biome doesn’t have these yet. We run this as a separate, focused ESLint check over React files only.

Type-aware rules: If you rely heavily on TypeScript-aware ESLint rules (like @typescript-eslint/no-floating-promises), those require type information that Biome currently doesn’t use. These rules are slower in ESLint too, so running them separately keeps your main check fast.

For non-React TypeScript projects with a standard ESLint config, Biome can replace the entire setup without gaps.

The Practical Case For Switching Now

Biome is not a prototype. Version 1.0 shipped in mid-2024, and the 1.x releases have been stable. The project is backed by a company (Biome Software) and has enough adoption that regression risks are caught quickly by the community.

The main reason to switch is developer experience. Fast lint checks are checks that run. Pre-commit hooks that take 10 seconds get disabled; hooks that take half a second stay on. The same principle applies to the CI step where a failing lint check is the fastest feedback loop you have.

For new projects, the question is whether to start with ESLint + Prettier or start with Biome. Given the current rule coverage and stability, Biome is the reasonable default unless you need React hooks rules or heavy TypeScript type-aware linting from day one. Even then, starting with Biome and adding a minimal ESLint config for those specific rules keeps the overhead low.

The configuration is simpler, the speed is genuinely better, and the migration path exists for when you want to move existing projects over.

Frequently asked questions

Can Biome fully replace ESLint and Prettier?
For most non-React TypeScript projects with a standard config, yes. Projects that rely on eslint-plugin-react-hooks or type-aware TypeScript rules still need a small, focused ESLint config running alongside Biome, since Biome does not implement those checks yet.
How much faster is Biome than ESLint and Prettier?
On a 300-file TypeScript project, Biome runs in about 400ms on a cold run and 180ms cached, compared to roughly 10 seconds for ESLint and Prettier combined. On a 1000-file project the gap widens to about 1.2 seconds versus 35 seconds.
Is Biome's formatter output identical to Prettier's?
Close but not perfect. Biome's formatter passes about 97% of Prettier's own test suite, so most files come out identical, though a small percentage of edge cases format slightly differently.
How do I migrate an existing project from ESLint and Prettier to Biome?
Run npx biome migrate eslint --write and npx biome migrate prettier --write. These read your existing configs and convert what they can into biome.json, typically covering 80-90% of your previous rules, and Biome reports which rules could not be migrated automatically.
What does Biome not cover yet?
Biome does not currently support complex ESLint plugins like eslint-plugin-react-hooks, custom business-logic rules, or type-aware TypeScript lint rules that need full type information. Those need to stay in a separate, smaller ESLint config for now.

Sponsored

Sponsored

Discussion

Join the conversation.

Comments are powered by GitHub Discussions. Sign in with your GitHub account to leave a comment.

Sponsored