Biome
Biome is a fast, all-in-one toolchain for web projects written in Rust. It formats and lints JavaScript, TypeScript, JSX, TSX, JSON, and CSS files. A single Biome run is 25x faster than Prettier and replaces both ESLint and Prettier with zero configuration to start.
Installation
# npm
npm install --save-dev --save-exact @biomejs/biome
# pnpm
pnpm add --save-dev --save-exact @biomejs/biome
# yarn
yarn add --dev --exact @biomejs/biome
# Bun
bun add --dev --exact @biomejs/biome
# Initialize a config file
npx @biomejs/biome init
# Or via the Biome CLI (if installed globally)
npm install -g @biomejs/biome
biome init
# Check version
biome --version
VS Code Extension
Install the Biome extension from the VS Code Marketplace for format-on-save and inline diagnostics. Then add to .vscode/settings.json:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[json]": { "editor.defaultFormatter": "biomejs.biome" }
}
Configuration
Biome is configured via biome.json (or biome.jsonc for comments):
{
"$schema": "https://biomejs.dev/schemas/1.8.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "main"
},
"files": {
"include": ["src/**", "tests/**"],
"ignore": ["dist/**", "node_modules/**", "*.min.js"],
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf",
"attributePosition": "auto"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"recommended": true
},
"complexity": {
"noForEach": "error",
"useLiteralKeys": "error"
},
"correctness": {
"noUnusedVariables": "warn",
"noUnusedImports": "warn"
},
"style": {
"useConst": "error",
"useTemplate": "warn",
"noVar": "error"
},
"suspicious": {
"noConsoleLog": "warn",
"noDebugger": "error"
},
"performance": {
"noAccumulatingSpread": "warn"
},
"security": {
"noDangerouslySetInnerHtml": "warn"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"jsxQuoteStyle": "double"
},
"globals": ["React", "__dirname", "__filename"]
},
"json": {
"formatter": {
"trailingCommas": "none"
},
"linter": {
"rules": {
"recommended": true
}
}
},
"css": {
"formatter": {
"enabled": true
},
"linter": {
"enabled": true
}
}
}
Per-File Overrides
{
"overrides": [
{
"include": ["**/*.test.ts", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
},
{
"include": ["scripts/**/*.js"],
"javascript": {
"globals": ["require", "process"]
}
}
]
}
Core Commands
| Command | Description |
|---|---|
biome check . | Lint, format check, and organize imports |
biome check --write . | Fix all auto-fixable issues |
biome check --unsafe . | Apply unsafe fixes too |
biome format . | Format files (show diff) |
biome format --write . | Format files in place |
biome lint . | Lint files (show diagnostics) |
biome lint --write . | Fix auto-fixable lint issues |
biome lint --apply-unsafe . | Apply unsafe lint fixes |
biome ci . | Run in CI mode (non-zero exit on any issue) |
biome check --stdin-file-path=file.ts | Lint/format from stdin |
biome format --stdin-file-path=file.ts | Format from stdin |
biome migrate | Migrate from ESLint/Prettier config |
biome migrate eslint --write | Migrate ESLint rules to Biome |
biome migrate prettier --write | Migrate Prettier config to Biome |
biome rage | Print debug info for bug reports |
biome version | Show version information |
biome explain noUnusedVariables | Explain a specific rule |
biome search "pattern" . | Search code with GritQL patterns |
Advanced Usage
Migrating from ESLint + Prettier
# Automated migration
biome migrate eslint --write
biome migrate prettier --write
# After migration, remove old tools
npm uninstall eslint prettier \
eslint-config-prettier \
eslint-plugin-prettier \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser
# Update scripts in package.json
Inline Suppression
// biome-ignore lint/style/useConst: this must be reassigned
let count = 0;
// biome-ignore lint/suspicious/noConsoleLog: debugging
console.log("value:", count);
// biome-ignore format: manually formatted table
const matrix = [
1, 0, 0,
0, 1, 0,
0, 0, 1,
];
// biome-ignore lint/all: legacy code
function oldFunction() { /* ... */ }
Rule Categories
| Category | Description |
|---|---|
a11y | Accessibility rules (ARIA, roles, labels) |
complexity | Code complexity and simplification |
correctness | Catches likely bugs and mistakes |
nursery | New rules under development |
performance | Performance anti-patterns |
security | Security vulnerabilities |
style | Stylistic preferences |
suspicious | Suspicious patterns (console.log, debugger) |
Using with Git Hooks (lint-staged)
// package.json
{
"lint-staged": {
"*.{js,ts,jsx,tsx,json,css}": [
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
]
}
}
# Install husky and lint-staged
npm install --save-dev husky lint-staged
npx husky init
echo "npx lint-staged" > .husky/pre-commit
GritQL Code Search
# Search for console.log calls
biome search 'console.log($args)' src/
# Search for specific patterns
biome search 'var $name = $value' src/
# Works with JS, TS, JSX, TSX
Formatting via stdin (Editor Integration)
# Format a file piped through stdin
cat src/index.ts | biome format --stdin-file-path=index.ts
# Lint from stdin
cat src/index.ts | biome check --stdin-file-path=index.ts
Common Workflows
Initial Project Setup
# Install and init
pnpm add --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init
# Add scripts to package.json
{
"scripts": {
"check": "biome check .",
"check:fix": "biome check --write .",
"format": "biome format --write .",
"lint": "biome lint .",
"lint:fix": "biome lint --write ."
}
}
CI Integration
# GitHub Actions
name: Code Quality
on: [push, pull_request]
jobs:
biome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx @biomejs/biome ci .
Checking a Single File
# Check specific file
biome check src/components/Button.tsx
# Format specific directory
biome format --write src/utils/
# Lint with verbose output
biome lint --verbose src/
Tips and Best Practices
Pin the exact version — Biome formats deterministically, but different versions may produce different output. Always pin with --save-exact and commit biome.json to version control.
Use biome check not separate commands — biome check runs formatting, linting, and import organization in one pass. It’s faster than running each separately and the correct command for most workflows.
Use biome ci in CI pipelines — biome ci is stricter than biome check: it exits with a non-zero status on any issue (including formatting differences) and never modifies files.
Enable VCS integration — Set "vcs": { "enabled": true, "useIgnoreFile": true } to respect your .gitignore. This prevents Biome from processing build artifacts and vendored files.
Prefer biome migrate — If switching from ESLint + Prettier, the migration command maps known ESLint rules to their Biome equivalents and sets up the biome.json. It’s faster than manual configuration.
Use biome explain to understand rules — biome explain noUnusedVariables prints the rule documentation with examples. Much faster than searching the docs.
Configure overrides for test files — Relax rules like noConsoleLog in test files using overrides. This avoids false positives in test utilities without disabling the rule globally.
Biome doesn’t need a cache — Unlike ESLint, Biome is fast enough that it doesn’t need a file-level cache. A full lint of 1,000 files takes milliseconds. Don’t add unnecessary complexity caching Biome results.