Biome
Fast, unified linting, formatting, and import organization for JavaScript, TypeScript, JSX, CSS, and GraphQL. Biome 2.4 provides type-aware linting without the TypeScript compiler, GritQL plugins for custom rules, and domain-based rule grouping. Single binary, zero config by default, 97% Prettier compatibility.
Critical Rules
files.ignore DOES NOT EXIST - use files.includes with negation
Biome 2.x only supports files.includes (with an s). There is NO files.ignore, NO files.include (without s), NO files.exclude. Using any of these will throw Found an unknown key errors.
The only valid keys under files are: includes, maxSize, ignoreUnknown. (experimentalScannerIgnores exists but is now marked deprecated in upstream docs and may be removed.)
To exclude files (generated code, vendored files, etc.), use negation patterns in files.includes:
{
"files": {
"includes": ["**", "!**/routeTree.gen.ts", "!**/generated/**"]
}
}
For paths the scanner must skip even when other tools or assists would otherwise touch them, use the !! force-ignore syntax inside files.includes (replaces experimentalScannerIgnores):
{
"files": {
"includes": ["**", "!!**/legacy-vendor/**"]
}
}
Do NOT use overrides with linter/formatter/assists: { enabled: false } to skip generated files - that approach is fragile (easy to miss a subsystem like assists/import organizer) and unnecessarily complex. Just exclude via files.includes.
Always use biome check, not separate lint + format
biome check runs formatter, linter, and import organizer in one pass. Never call biome lint and biome format separately in CI - use biome check (or biome ci for CI mode).
biome.json lives at project root
Every project needs one biome.json at the root. Monorepo packages use nested configs with "extends": "//" to inherit from root. Never use relative paths like "extends": ["../../biome.json"].
Use --write to apply fixes
biome check --write . # Apply safe fixes only
biome check --write --unsafe . # Apply all fixes including unsafe (review changes)
--fix exists as an alias for --write on biome lint and biome format, but biome check is the canonical entry point and --write is the documented flag. Stick with --write.
Safe vs unsafe fixes. Removing unused imports, parameters, and variables is classified as unsafe (an external caller could still reference the symbol). Plain --write will leave them in place and report the diagnostic. Use --write --unsafe (and review the diff) or delete them by hand.
Pin exact versions and migrate after upgrades
pnpm add --save-dev --save-exact @biomejs/biome@latest
pnpm biome migrate --write
The $schema URL in biome.json is version-pinned (e.g. "$schema": "https://biomejs.dev/schemas/2.4.13/schema.json"). After bumping @biomejs/biome, the CLI errors with The configuration schema version does not match the CLI version until you run biome migrate --write. Run it as part of the upgrade, not later.
Quick Start
pnpm add --save-dev --save-exact @biomejs/biome
pnpm biome init # Creates default biome.json with recommended rules
IDE Setup
VS Code - Install biomejs.biome extension:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
source.fixAll.biome applies safe lint fixes on save; source.organizeImports.biome runs the assist. Both are needed for parity with the CLI's biome check --write.
Zed - Biome extension available natively. The inline-config feature (v2.4) lets editors override rules without affecting biome.json. Note the spelling: Zed uses inline_config (snake_case); the VS Code extension uses inlineConfig (camelCase).
{
"formatter": { "language_server": { "name": "biome" } },
"lsp": {
"biome": {
"settings": {
"inline_config": {
"linter": { "rules": { "suspicious": { "noConsole": "off" } } }
}
}
}
}
}
CI Integration
pnpm biome ci . # No writes, non-zero exit on errors
pnpm biome ci --reporter=default --reporter=github . # GitHub Actions annotations
Configuration (biome.json)
Recommended config for React/TypeScript projects
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": [
"src/**/*.ts", "src/**/*.tsx",
"tests/**/*.ts", "**/*.config.ts", "**/*.json",
"!**/generated", "!**/components/ui"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 120
},
"linter": {
"enabled": true,
"rules": { "recommended": true },
"domains": { "react": "recommended" }
},
"javascript": {
"formatter": { "quoteStyle": "double" }
},
"assist": {
"enabled": true,
"actions": {
"source": { "organizeImports": "on" }
}
}
}
Formatter options
Key options: indentStyle ("space"/"tab"), indentWidth, lineWidth, lineEnding ("lf"/"crlf"), trailingNewline. JS-specific: quoteStyle, trailingCommas, semicolons, arrowParentheses, bracketSpacing.
Linter rule configuration
Rules use severity levels "error", "warn", "info", or "off". Some accept options:
{
"linter": {
"rules": {
"recommended": true,
"style": {
"noRestrictedGlobals": {
"level": "error",
"options": {
"deniedGlobals": {
"Buffer": "Use Uint8Array for browser compatibility."
}
}
},
"useComponentExportOnlyModules": "off"
}
}
}
}
Import organizer
The import organizer (Biome Assist) merges duplicates, sorts by distance, and supports custom grouping. As of v2.4.13 it also sorts imports inside TypeScript modules (module "x" { ... }) and .d.ts declaration files.
{
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": {
"level": "on",
"options": {
"groups": [
{ "source": "builtin" },
{ "source": "external" },
{ "source": "internal", "match": "@company/*" },
{ "source": "relative" }
]
}
}
}
}
}
}
Per-subsystem includes
Each subsystem (linter, formatter, assist) has its own includes for fine-grained scoping. Applied after files.includes - can only narrow, not widen.
{
"files": {
"includes": ["**", "!**/dist"]
},
"linter": {
"includes": ["**", "!**/components/ui"]
},
"formatter": {
"includes": ["**", "!**/components/ui"]
}
}
This lints and formats everything except dist/ and components/ui, while assists (import organizer) still run on components/ui.
Overrides
Overrides apply different settings to specific file patterns. Use for per-file rule tweaks (e.g., relaxing rules for vendored/shadcn components). The field is includes (with s).
{
"overrides": [
{
"includes": ["**/components/ui/**"],
"linter": {
"rules": {
"suspicious": { "noDocumentCookie": "off" },
"style": { "useComponentExportOnlyModules": "off" }
}
}
},
{
"includes": ["**/*.test.ts"],
"linter": {
"rules": {
"suspicious": { "noConsole": "off" }
}
}
}
]
}
Monorepo configuration
Root biome.json holds shared config. Package configs inherit with "extends": "//":
{
"$schema": "../../node_modules/@bi