Skills shared-tooling-biome
Biome v2 unified linter, formatter, and import organizer — single Rust-powered tool replacing ESLint + Prettier with 97% Prettier compatibility and 20x faster performance
git clone https://github.com/agents-inc/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/agents-inc/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/dist/plugins/shared-tooling-biome/skills/shared-tooling-biome" ~/.claude/skills/agents-inc-skills-shared-tooling-biome && rm -rf "$T"
dist/plugins/shared-tooling-biome/skills/shared-tooling-biome/SKILL.mdBiome
Quick Guide: Biome is a unified linter, formatter, and import organizer for JavaScript, TypeScript, JSX, TSX, JSON, CSS, and GraphQL. Single Rust binary replaces ESLint + Prettier with 97% Prettier compatibility. Use
for all configuration. Runbiome.jsonto lint, format, and organize imports in one pass. Usebiome check --writein pipelines.biome ciCurrent stable version: Biome v2.4.x (March 2026). Biome v2 introduced type-aware linting, nested configs, and a revamped import organizer.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST use
or biome.json
for ALL configuration — Biome does not use JavaScript config files)biome.jsonc
(You MUST pin Biome to an exact version with
— Biome formatting can change between versions)--save-exact
(You MUST use
in CI pipelines, NOT biome ci
— biome check
is read-only with no ci
flag)--write
(You MUST use
for local development — runs linter, formatter, and import organizer in one pass)biome check --write
(You MUST include
in biome.json for editor autocompletion and validation)$schema
</critical_requirements>
Auto-detection: Biome, biome.json, biome.jsonc, @biomejs/biome, biome check, biome lint, biome format, biome ci, biome-ignore, organizeImports, biome migrate
When to use:
- Setting up a unified linter + formatter for JavaScript/TypeScript projects
- Replacing ESLint + Prettier with a single, faster tool
- Greenfield projects wanting zero-config or minimal-config setup
- Large codebases where linting/formatting speed matters
- Configuring import organizing with custom group ordering
- Migrating from ESLint and/or Prettier to Biome
- Setting up CI pipelines with
biome ci - Configuring pre-commit hooks with Biome's
flag--staged
When NOT to use:
- Projects requiring ESLint plugins with no Biome equivalent (e.g., custom framework-specific plugins)
- Projects heavily invested in custom ESLint rules that cannot be replicated
- Projects needing Markdown, YAML, or TOML formatting (Biome does not support these yet)
- Runtime code (this is build-time tooling only)
- Git hooks framework setup (Husky/Lefthook configuration is a separate concern)
- TypeScript compiler configuration (
is a separate concern)tsconfig.json
Key patterns covered:
- biome.json configuration with formatter, linter, and assist settings
- Linter rule groups (recommended, all, nursery) and severity levels
- Formatter configuration (indent style, line width, quotes, semicolons)
- Import organizer with custom group ordering
- CLI commands: check, format, lint, ci, migrate
- Migration from ESLint + Prettier
- Git hooks integration (Husky, Lefthook,
flag)--staged - CI integration with GitHub Actions and GitLab CI
- Editor integration (VS Code, JetBrains)
- Suppression comments (
,biome-ignore
, range suppressions)biome-ignore-all - Nested configuration for monorepos
- Overrides for file-specific settings
Examples
- Setup & Configuration — Installation, biome.json, VS Code, monorepos, framework configs
- Linting Rules — Rule groups, domains, suppressions, overrides, import ordering
- Formatting — Formatter options, Prettier compatibility, option mapping
- CI & Git Hooks — GitHub Actions, GitLab CI, Husky, Lefthook, staged files
- Migrating from ESLint/Prettier — Automated migration, rule mapping, package cleanup
Other resources:
- CLI Quick Reference — All CLI commands, flags, and configuration option tables
<philosophy>
Philosophy
Biome unifies linting, formatting, and import organizing into a single tool with a single configuration file. Built in Rust, it delivers 20x faster performance than ESLint + Prettier while maintaining 97% Prettier compatibility.
Core principles:
- One tool, one config — biome.json replaces .eslintrc, prettier.config, and import sorting plugins
- Sensible defaults — Biome works out of the box with recommended rules enabled; zero-config is a valid setup
- Speed as a feature — Rust-powered binary processes large codebases in milliseconds, not seconds
- Unified commands —
runs everything in one pass (lint + format + organize imports)biome check --write - Safe by default — Safe fixes apply automatically; unsafe fixes require explicit
flag--unsafe
<patterns>
Core Patterns
Pattern 1: Basic biome.json Configuration
Every Biome project starts with a
biome.json at the project root. Use biome init to scaffold one, then customize.
# Install Biome (always pin exact version) npm install --save-dev --save-exact @biomejs/biome # Create default biome.json npx @biomejs/biome init
// biome.json — minimal recommended setup { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100 }, "linter": { "rules": { "recommended": true } }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on" } }, }, }
Why good:
$schema enables editor autocompletion, VCS integration respects .gitignore, explicit indentStyle: "space" avoids Biome's tab default, recommended rules provide a strong baseline
// BAD: No schema, no VCS, relying on defaults that differ from Prettier { "linter": { "enabled": true } }
Why bad: Missing
$schema loses autocompletion, no VCS means linting node_modules, Biome defaults to tabs which surprises Prettier migrants
Full example: See examples/core.md for a production-ready biome.json with overrides, framework configs, and monorepo setup.
Pattern 2: Linter Rules Configuration
Biome provides 459+ rules across 8 groups (
accessibility, complexity, correctness, nursery, performance, security, style, suspicious). Rules default to recommended — a curated subset of safe, stable rules. Severity levels: "off", "on", "info", "warn", "error". See reference.md for the full rule groups and severity tables.
Domains (Technology-Specific Rules)
Biome v2 introduces domains that group rules by technology. Domains auto-detect from
package.json dependencies.
{ "linter": { "domains": { "react": "recommended", "test": "recommended" } } }
Full examples: See examples/linting.md for rule configuration, suppressions, overrides, and import ordering.
Pattern 3: Formatter Configuration
Biome's formatter achieves 97% Prettier compatibility. Global settings apply to all languages; language-specific settings override globals. Biome defaults to tabs — set
indentStyle: "space" explicitly when migrating from Prettier.
{ "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100 }, "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always" }, }, "json": { "formatter": { "trailingCommas": "none" } }, "css": { "formatter": { "enabled": true } }, }
Full reference: See examples/formatting.md for all options, Prettier mapping, and language-specific settings.
Pattern 4: Import Organizer
Biome v2 revamped the import organizer with custom group ordering. Configure under
assist.actions.source.organizeImports.
{ "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ [":BUN:", ":NODE:"], ":PACKAGE:", ":BLANK_LINE:", ["@company/**"], ":BLANK_LINE:", ":ALIAS:", ":PATH:", ":BLANK_LINE:", { "type": true }, ], "identifierOrder": "natural", }, }, }, }, }, }
Key options:
identifierOrder controls named import sorting — "natural" (default, e.g. var1, var2, var11) or "lexicographic" (strict alphabetical). Groups accept predefined matchers, glob patterns ("@my/lib/**"), object matchers ({ "type": true, "source": ["@my/lib"] }), or arrays combining any of these.
Predefined Groups
| Group | Matches |
|---|---|
| Node.js built-ins and protocol |
| Bun-specific modules |
| Scoped and bare npm packages |
| Packages with a protocol prefix |
| Aliased imports (, , , , ) |
| Absolute and relative path imports |
| HTTP/HTTPS imports |
| Visual separator between groups |
Full examples: See examples/linting.md for import ordering with results.
Pattern 5: CLI Commands
Use
check locally, ci in pipelines. Key commands:
npx biome check --write . # Lint + format + organize imports (auto-fix) npx biome ci . # CI mode (read-only, optimized for pipelines) npx biome check --staged --write . # Pre-commit hooks (only staged files) npx biome check --changed --since=main . # Changed files only
Full reference: See examples/ci.md for complete CLI usage, filtering, and reporting options.
Pattern 6: Suppression Comments
Biome uses
biome-ignore comments with required explanations.
// biome-ignore lint/suspicious/noDebugger: needed for local debugging debugger; // biome-ignore-all lint/style/noDefaultExport: framework requires default export (top of file only) // biome-ignore-start lint/suspicious/noDoubleEquals: legacy section // biome-ignore-end lint/suspicious/noDoubleEquals: legacy section
See reference.md for the full suppression syntax table and specifier levels. See examples/linting.md for inline, file-level, and range suppression examples.
Pattern 7: Nested Configuration (Monorepos)
Biome v2 supports nested
biome.json files. Each subdirectory can override the root config.
// packages/my-app/biome.json — inherits from root { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "extends": "//" }
// packages/legacy-lib/biome.json — relaxes rules { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "root": false, "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } }, }
Why good:
"extends": "//" shorthand inherits root config, "root": false marks as child, each package can relax or tighten rules independently
Full examples: See examples/core.md for root + child config patterns.
Pattern 8: Overrides (File-Specific Rules)
Use
overrides for file-pattern-specific configuration without nested config files.
{ "overrides": [ { "includes": ["**/*.test.ts", "**/*.test.tsx"], "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } }, }, { "includes": ["**/app/**/page.tsx", "**/app/**/layout.tsx"], "linter": { "rules": { "style": { "noDefaultExport": "off" } } }, }, ], }
Why good: Overrides eliminate suppression comments in every file, test files get relaxed rules, framework conventions handled declaratively
</patterns>Full examples: See examples/linting.md for test, config, and generated file overrides.
<performance>
Performance
Biome is written in Rust and processes files in parallel, making it significantly faster than JavaScript-based alternatives.
| Tool | Format Time (1000 files) | Lint Time (1000 files) |
|---|---|---|
| Biome | ~100ms | ~200ms |
| Prettier | ~2000ms | N/A |
| ESLint | N/A | ~3000ms |
| ESLint + Prettier | ~5000ms | ~5000ms |
Approximate benchmarks. Actual performance varies by project size and rule configuration.
Performance Tips:
- Use
instead of runningbiome check
andbiome format
separately — single pass is fasterbiome lint - Enable VCS integration to automatically skip ignored files (
).gitignore - Use
or--staged
in hooks and CI to process only affected files--changed - Be selective with nursery rules — some experimental rules may impact performance
- Use
(v2.4+) to identify slow lint rules in your configuration--profile-rules
Type-Aware Linting Performance:
Biome v2 introduced type-aware linting without the TypeScript compiler. Enable selectively:
- Default scan discovers nested configs only (fast)
- Project domain scan indexes the full module graph (slower, but still faster than tsc)
- Types domain scan adds type inference (most comprehensive, most expensive)
<decision_framework>
Decision Framework
Biome vs ESLint + Prettier
Need linting and formatting? |-- Greenfield project? | |-- Want simplest possible setup? -> Biome (one tool, one config) | |-- Need niche ESLint plugins? -> ESLint + Prettier | +-- Speed is important? -> Biome (20x faster) |-- Existing ESLint + Prettier project? | |-- Happy with current setup? -> Stay with ESLint + Prettier | |-- Config complexity is a pain? -> Migrate to Biome | |-- Need ESLint plugins without Biome equivalents? -> Stay | +-- Want faster CI/pre-commit hooks? -> Biome (or hybrid) +-- Monorepo? |-- Need per-package lint configs? -> Biome v2 nested configs or ESLint 10 +-- Speed bottleneck in CI? -> Biome
Configuration Complexity
How to configure Biome? |-- Just starting out? -> Run `biome init`, use defaults with recommended: true |-- Migrating from ESLint? -> Run `biome migrate eslint --write` |-- Migrating from Prettier? -> Run `biome migrate prettier --write` |-- Need per-file rules? | |-- Different rules for test files? -> Use `overrides` in biome.json | +-- Different rules per package? -> Use nested biome.json with "root": false +-- Need custom import ordering? -> Configure organizeImports.options.groups
Full migration decision tree: See examples/migration.md.
</decision_framework>
<integration>
Integration Guide
Works with:
- JSX/TSX: Full support with
domain for React-specific lint rulesreact - TypeScript: Type-aware linting without tsc dependency (Biome v2+)
- CSS: Linting enabled by default, formatting opt-in
- JSON/JSONC: Full support including tsconfig.json, package.json
- GraphQL: Linting enabled by default, formatting opt-in
- Vue/Svelte/Astro: Experimental support via
(v2.4+)html.experimentalFullSupportEnabled
Replaces / Conflicts with:
- ESLint: Biome replaces ESLint for linting (or use hybrid approach)
- Prettier: Biome replaces Prettier for formatting
- eslint-plugin-import: Biome's import organizer replaces import sorting plugins
- eslint-config-prettier: Not needed — Biome has no formatter/linter conflicts
</integration>CI/editor integration: See examples/ci.md and examples/core.md.
<red_flags>
RED FLAGS
High Priority Issues:
- Using
in CI instead ofbiome check
(biome ci
allowscheck
which is dangerous in pipelines;--write
is read-only)ci - Not pinning Biome version with
(formatting can change between minor versions, causing diff noise)--save-exact - Missing
in biome.json (loses editor autocompletion, validation, and discoverability)$schema - Using JavaScript config files instead of biome.json (Biome only supports JSON/JSONC configuration)
- Running
andbiome format
separately whenbiome lint
does both (wastes time, parses files twice)biome check
Medium Priority Issues:
- Forgetting to set
when migrating from Prettier (Biome defaults to tabs)indentStyle: "space" - Not enabling VCS integration (without it, Biome may process node_modules and dist)
- Using
without reviewing changes (unsafe fixes can alter program behavior)--unsafe - Not including
in git hooks (causes failures when no matching files are staged)--no-errors-on-unmatched - Enabling all nursery rules (they are experimental and may have bugs or performance issues)
Common Mistakes:
- Using
in a nested config (this is the default; use"root": true
for child configs)"root": false - Expecting Markdown/YAML formatting support (Biome does not support these languages yet)
- Not running
when upgrading major versions (config schema changes between v1 and v2)biome migrate --write - Suppression comments without explanations (
requires text after the colon)biome-ignore lint:
Gotchas & Edge Cases:
- Biome defaults to tabs, not spaces — always set
explicitly when migrating from PrettierindentStyle - CSS and GraphQL formatting is disabled by default — must opt in with
"formatter": { "enabled": true }
must be at the top of the file — placing it mid-file triggers an unused suppression warningbiome-ignore-all- Import organizer is part of
, notassist
— configure underlinterassist.actions.source.organizeImports - The
flag makes lint-staged unnecessary for Biome-only setups (since Biome v1.7.0+)--staged - Type-aware linting (project/types domains) triggers file scanning which can slow down first runs on large projects
does not migrate inspired rules by default — usebiome migrate eslint --write
to include them--include-inspired- Range suppressions (
/biome-ignore-start
) must have matching rule specifiersbiome-ignore-end - Biome treats all JS/TS/JSX/TSX under the
config key — there is no separatejavascript
sectiontypescript - Configuration files named
(with leading dot) are also discovered (v2.4+).biome.json
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST use
or biome.json
for ALL configuration — Biome does not use JavaScript config files)biome.jsonc
(You MUST pin Biome to an exact version with
— Biome formatting can change between versions)--save-exact
(You MUST use
in CI pipelines, NOT biome ci
— biome check
is read-only with no ci
flag)--write
(You MUST use
for local development — runs linter, formatter, and import organizer in one pass)biome check --write
(You MUST include
in biome.json for editor autocompletion and validation)$schema
Failure to follow these rules will cause inconsistent formatting, broken CI pipelines, and missed lint errors.
</critical_reminders>