Biome: One Toolchain to Replace ESLint and Prettier

If you followed the Rome project at all, you know the story was bumpy. Sebastian McKenzie (creator of Babel and Yarn) started Rome in 2020 with an ambitious vision: one tool to lint, format, bundle, compile, and test JavaScript. The company raised $4.5 million, hired a team, then laid everyone off in late 2022 when funding dried up. The project looked dead.
Then in August 2023, the community forked it and rebranded as Biome. The core maintainers who had been contributing to Rome picked it up, moved it to a new GitHub org, and kept shipping. Within months, Biome had more active development than Rome ever did under the company. Open source wins again.
What Biome Actually Does
Biome is a single Rust binary that handles both linting and formatting for JavaScript, TypeScript, JSX, TSX, JSON, and CSS. That's it. No bundling, no compiling, no test runner. The team deliberately narrowed the scope from Rome's original everything-tool ambition, and that focus has made the tool far more practical.
The key insight is that linting and formatting are deeply related. ESLint and Prettier have always fought each other. You need eslint-config-prettier to disable ESLint rules that conflict with Prettier's formatting. You need eslint-plugin-prettier or separate commands to run both. With Biome, one tool understands both concerns natively. No conflicts, no glue config.
Speed: It's Not Even Close
Biome is written in Rust, and the performance difference over ESLint plus Prettier is staggering. On a mid-size project (around 1,500 files), ESLint takes about 30 seconds to lint everything. Prettier takes another 10 seconds to format. Biome does both in under 2 seconds. That's roughly 20x faster.
This isn't just a nice-to-have. In CI pipelines, those seconds add up across hundreds of daily runs. In local development, instant feedback changes how you work. You stop batching lint fixes and start fixing them as they appear.
Configuration
Biome uses a single `biome.json` file. Here's a minimal setup:
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "warn"
},
"suspicious": {
"noExplicitAny": "error"
}
}
},
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always"
}
}
}
Compare that to the typical ESLint plus Prettier setup: `.eslintrc.js`, `.prettierrc`, `.eslintignore`, `.prettierignore`, and a handful of npm packages. Biome collapses all of that into one file and zero npm dependencies.
CLI Commands
The CLI is simple. Three commands cover 95% of what you need:
# Check everything (lint + format) and report issues
npx @biomejs/biome check .
# Format files in place
npx @biomejs/biome format --write .
# Lint and apply safe fixes
npx @biomejs/biome lint --write .
The `check` command is the workhorse. It runs both the linter and formatter in one pass, which is what you want in CI. The `--write` flag on format and lint applies auto-fixes directly. You can also run `biome check --write` to do both at once.
Migrating from ESLint and Prettier
Biome ships a migration command that reads your existing ESLint config and generates the equivalent `biome.json`:
npx @biomejs/biome migrate eslint --write
It maps ESLint rules to their Biome equivalents where they exist. Not every rule has a 1:1 match, so you'll get a report of rules that couldn't be migrated. In my experience, about 70% to 80% of common ESLint rules have Biome equivalents.
The practical migration path I'd recommend:
- Run the migration command to generate your initial `biome.json`.
- Run `biome check .` and review the output. Expect some new warnings that ESLint wasn't catching.
- Decide which unmigrated rules you actually care about. Many ESLint rules people enable are either redundant with TypeScript or rarely triggered.
- Run `biome check --write .` to auto-fix what it can.
- Remove your ESLint and Prettier configs, plugins, and dependencies.
Rule Coverage: What's There and What's Missing
As of late 2023, Biome covers over 200 lint rules. It implements most of the essential ESLint core rules, plus equivalents from popular plugins like typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-import.
What is still missing? A few things to keep in mind:
- No custom rule API yet. With ESLint, you can write your own rules as plugins. Biome doesn't support this. If your team relies on custom internal lint rules, that's a blocker.
- Some niche plugin rules (eslint-plugin-jsx-a11y coverage is partial, eslint-plugin-testing-library isn't there yet).
- The ecosystem of community plugins that exists for ESLint simply doesn't exist for Biome.
For most teams, the built-in rules cover what they need. But if you're deep into a custom ESLint plugin ecosystem, evaluate carefully before switching.
CI Integration
In CI, the setup is trivial. Here's a GitHub Actions step:
- name: Lint and Format Check
run: npx @biomejs/biome check --max-diagnostics=50 .
That's it. One command, one step, finishes in seconds. Compare that to the typical CI setup with separate lint and format steps, each pulling in their own dependencies.
For monorepos, Biome respects `biome.json` at the workspace root and supports per-package overrides. You can also use the `--files-ignore-unknown` flag to skip file types Biome doesn't handle yet.
Editor Support
VS Code has an official Biome extension that provides format-on-save and inline lint diagnostics. It's fast because it talks directly to the Biome daemon process rather than spawning a new Node process for each file (which is what the ESLint extension does). IntelliJ support is available through a community plugin, and Neovim users can configure Biome through the LSP.
Should You Switch?
If you're starting a new project today, I'd default to Biome. The speed alone justifies it, and the single-config simplicity is a genuine quality-of-life improvement. You eliminate an entire category of "why are ESLint and Prettier fighting" issues.
For existing projects, the calculus depends on how deep your ESLint investment is. Light ESLint usage with recommended configs? Easy migration, do it. Heavy custom plugin usage? Wait until Biome's custom rule API ships, or keep ESLint for those specific rules and use Biome just for formatting.
The broader trend here matters. Rust-based JavaScript tooling (Biome, oxlint, Turbopack, SWC) is eating the ecosystem. The JavaScript tools we've relied on for a decade are being replaced by tools that are orders of magnitude faster. Biome is one of the most mature examples of that shift, and it's only getting better.