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
Install
npx skills add https://github.com/agents-inc/skills/tree/main/dist/plugins/shared-tooling-biome/skills/shared-tooling-biome
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install agents-inc-skills@llmmart
git clone https://github.com/agents-inc/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole agents-inc/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Biome
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
biome.jsonfor all configuration. Runbiome check --writeto lint, format, and organize imports in one pass. Usebiome ciin pipelines.Current 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,
import type, named constants)
(You MUST use biome.json or biome.jsonc for ALL configuration — Biome does not use JavaScript config files)
(You MUST pin Biome to an exact version with --save-exact — Biome formatting can change between versions)
(You MUST use biome ci in CI pipelines, NOT biome check — ci is read-only with no --write flag)
(You MUST use biome check --write for local development — runs linter, formatter, and import organizer in one pass)
(You MUST include $schema in biome.json for editor autocompletion and validation)
</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
--stagedflag
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 (
tsconfig.jsonis a separate concern)
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,
--stagedflag) - CI integration with GitHub Actions and GitLab CI
- Editor integration (VS Code, JetBrains)
- Suppression comments (
biome-ignore,biome-ignore-all, range suppressions) - 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
<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>
<red_flags>
RED FLAGS
High Priority Issues:
- Using
biome checkin CI instead ofbiome ci(checkallows--writewhich is dangerous in pipelines;ciis read-only) - Not pinning Biome version with
--save-exact(formatting can change between minor versions, causing diff noise) - Missing
$schemain biome.json (loses editor autocompletion, validation, and discoverability) - Using JavaScript config files instead of biome.json (Biome only supports JSON/JSONC configuration)
- Running
biome formatandbiome lintseparately whenbiome checkdoes both (wastes time, parses files twice)
Medium Priority Issues:
- Forgetting to set
indentStyle: "space"when migrating from Prettier (Biome defaults to tabs) - Not enabling VCS integration (without it, Biome may process node_modules and dist)
- Using
--unsafewithout reviewing changes (unsafe fixes can alter program behavior) - Not including
--no-errors-on-unmatchedin git hooks (causes failures when no matching files are staged) - Enabling all nursery rules (they are experimental and may have bugs or performance issues)
Common Mistakes:
- Using
"root": truein a nested config (this is the default; use"root": falsefor child configs) - Expecting Markdown/YAML formatting support (Biome does not support these languages yet)
- Not running
biome migrate --writewhen upgrading major versions (config schema changes between v1 and v2) - Suppression comments without explanations (
biome-ignore lint:requires text after the colon)
Gotchas & Edge Cases:
- Biome defaults to tabs, not spaces — always set
indentStyleexplicitly when migrating from Prettier - CSS and GraphQL formatting is disabled by default — must opt in with
"formatter": { "enabled": true } biome-ignore-allmust be at the top of the file — placing it mid-file triggers an unused suppression warning- Import organizer is part of
assist, notlinter— configure underassist.actions.source.organizeImports - The
--stagedflag makes lint-staged unnecessary for Biome-only setups (since Biome v1.7.0+) - Type-aware linting (project/types domains) triggers file scanning which can slow down first runs on large projects
biome migrate eslint --writedoes not migrate inspired rules by default — use--include-inspiredto include them- Range suppressions (
biome-ignore-start/biome-ignore-end) must have matching rule specifiers - Biome treats all JS/TS/JSX/TSX under the
javascriptconfig key — there is no separatetypescriptsection - Configuration files named
.biome.json(with leading dot) are also discovered (v2.4+)
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use biome.json or biome.jsonc for ALL configuration — Biome does not use JavaScript config files)
(You MUST pin Biome to an exact version with --save-exact — Biome formatting can change between versions)
(You MUST use biome ci in CI pipelines, NOT biome check — ci is read-only with no --write flag)
(You MUST use biome check --write for local development — runs linter, formatter, and import organizer in one pass)
(You MUST include $schema in biome.json for editor autocompletion and validation)
Failure to follow these rules will cause inconsistent formatting, broken CI pipelines, and missed lint errors.
</critical_reminders>
Files (skills)
-
examples
-
biome.md 15.9 KB
# Biome Configuration Examples > Practical examples for Biome configuration, migration, CI integration, and custom rules. See [SKILL.md](../SKILL.md) for core patterns and [reference.md](../reference.md) for CLI quick reference. --- ## Standard Project Setup ### Step-by-Step Initialization ```bash # 1. Install Biome (always pin exact version) npm install --save-dev --save-exact @biomejs/biome # 2. Create default biome.json npx @biomejs/biome init # 3. Add scripts to package.json ``` ```jsonc // package.json { "scripts": { "check": "biome check .", "check:fix": "biome check --write .", "format": "biome format --write .", "lint": "biome lint .", "lint:fix": "biome lint --write .", "ci": "biome ci .", }, "devDependencies": { "@biomejs/biome": "2.4.7", }, } ``` ### Production-Ready biome.json ```jsonc // biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true, "defaultBranch": "main", }, "files": { "ignoreUnknown": true, "includes": ["**"], }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf", }, "linter": { "enabled": true, "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "noUnusedVariables": "warn", }, "style": { "noDefaultExport": "warn", "useImportType": "error", }, "suspicious": { "noExplicitAny": "warn", }, }, }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on", }, }, }, "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always", "trailingCommas": "all", "arrowParentheses": "always", "bracketSameLine": false, }, }, "json": { "formatter": { "trailingCommas": "none", }, }, "css": { "formatter": { "enabled": true, }, }, "overrides": [ { "includes": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"], "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, }, }, }, ], } ``` **Why good:** `$schema` enables editor autocompletion, VCS integration skips `.gitignore`d files, explicit formatter settings prevent tab/space surprises, `noUnusedImports` catches dead imports, `useImportType` enforces `import type`, `noDefaultExport` encourages named exports, test file overrides relax strict rules where needed, CSS formatting explicitly enabled --- ## Migration from ESLint + Prettier ### Automated Migration ```bash # Step 1: Migrate Prettier settings (indent, quotes, line width) npx @biomejs/biome migrate prettier --write # Step 2: Migrate ESLint rules (maps to Biome equivalents) npx @biomejs/biome migrate eslint --write # Step 3: Include rules that are "inspired by" ESLint (not exact matches) npx @biomejs/biome migrate eslint --write --include-inspired # Step 4: Enable VCS integration (ESLint respects .gitignore by default) # Add to biome.json manually: # "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true } # Step 5: Verify migration npx @biomejs/biome check . # Step 6: Remove old tooling npm uninstall eslint prettier eslint-config-prettier eslint-plugin-only-warn \ @eslint/js typescript-eslint eslint-plugin-react eslint-plugin-jsx-a11y # Step 7: Remove old config files rm -f .eslintrc* eslint.config.* .prettierrc* prettier.config.* .eslintignore .prettierignore ``` ### Manual Migration Checklist | ESLint + Prettier | Biome Equivalent | | -------------------------------------------- | --------------------------------------------- | | `.eslintrc.json` / `eslint.config.ts` | `biome.json` | | `.prettierrc` / `prettier.config.mjs` | `biome.json` (formatter section) | | `.eslintignore` | `biome.json` files.includes with `!` patterns | | `.prettierignore` | `biome.json` files.includes with `!` patterns | | `eslint-config-prettier` | Not needed (no formatter/linter conflicts) | | `eslint-plugin-only-warn` | Set rule severity to `"warn"` | | `eslint-plugin-import` | `assist.actions.source.organizeImports` | | `@typescript-eslint/parser` | Built-in TypeScript support | | `@typescript-eslint/consistent-type-imports` | `style/useImportType` | | `@typescript-eslint/no-unused-vars` | `correctness/noUnusedVariables` | | `import/no-default-export` | `style/noDefaultExport` | | `no-console` | `nursery/noConsole` | ### Removing Unnecessary Packages After migration, these packages are no longer needed: ```bash # Core tools (replaced by Biome) npm uninstall eslint prettier # ESLint plugins (handled by Biome rules) npm uninstall @eslint/js typescript-eslint eslint-config-prettier npm uninstall eslint-plugin-only-warn eslint-plugin-react npm uninstall eslint-plugin-jsx-a11y eslint-plugin-unicorn npm uninstall eslint-plugin-import eslint-plugin-simple-import-sort # Prettier plugins npm uninstall @prettier/sync prettier-plugin-tailwindcss ``` --- ## Custom Import Ordering ### React Project with Company Packages ```jsonc { "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ ":NODE:", ":PACKAGE:", ":BLANK_LINE:", ["@company/**"], ":BLANK_LINE:", ":ALIAS:", ["../**", "./**"], ], }, }, }, }, }, } ``` **Result:** ```typescript import { readFileSync } from "node:fs"; import { z } from "zod"; import { useQuery } from "@tanstack/react-query"; import { apiClient } from "@company/api-client"; import { Button } from "@company/ui"; import { useAuth } from "@/hooks/use-auth"; import { formatDate } from "../utils/date"; import { UserCard } from "./user-card"; ``` ### Separating Type Imports ```jsonc { "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [{ "type": false }, ":BLANK_LINE:", { "type": true }], }, }, }, }, }, } ``` **Result:** ```typescript import { z } from "zod"; import { useQuery } from "@tanstack/react-query"; import { Button } from "./button"; import type { User } from "../types/user"; import type { ApiResponse } from "@company/api-client"; ``` --- ## Monorepo Nested Configuration ### Root Configuration ```jsonc // biome.json (project root) { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true, }, "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf", }, "linter": { "rules": { "recommended": true, "style": { "noDefaultExport": "warn", "useImportType": "error", }, }, }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on", }, }, }, "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always", "trailingCommas": "all", }, }, } ``` ### Next.js App Override ```jsonc // apps/web/biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "extends": "//", "linter": { "rules": { "style": { // Next.js requires default exports for pages and layouts "noDefaultExport": "off", }, }, "domains": { "react": "recommended", }, }, "overrides": [ { "includes": [ "**/app/**/page.tsx", "**/app/**/layout.tsx", "**/app/**/loading.tsx", ], "linter": { "rules": { "style": { "noDefaultExport": "off", }, }, }, }, ], } ``` ### Legacy Package Override ```jsonc // packages/legacy-lib/biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "root": false, "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, "correctness": { "noUnusedVariables": "off", }, }, }, } ``` **Why good:** Root config establishes team-wide standards, `"extends": "//"` shorthand inherits root config, Next.js app relaxes default export rule where framework requires it, legacy package can disable strict rules while the rest of the monorepo stays strict --- ## CI Integration Examples ### GitHub Actions (Minimal) ```yaml # .github/workflows/lint.yml name: Lint & Format on: [push, pull_request] jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: biomejs/setup-biome@v2 - run: biome ci . ``` ### GitHub Actions (Full Pipeline) ```yaml # .github/workflows/quality.yml name: Code Quality on: push: branches: [main] pull_request: jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # Option A: Use setup-biome (no Node.js needed) - uses: biomejs/setup-biome@v2 with: version: latest # Run Biome CI with strict mode - run: biome ci --error-on-warnings --max-diagnostics=100 . # If using Biome with other Node.js tools biome-with-node: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci - run: npx biome ci . ``` ### GitHub Actions (Changed Files Only) ```yaml # .github/workflows/lint-changed.yml name: Lint Changed Files on: pull_request jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: biomejs/setup-biome@v2 - run: biome ci --changed --since=origin/main . ``` ### GitLab CI ```yaml # .gitlab-ci.yml biome: image: name: ghcr.io/biomejs/biome:latest entrypoint: [""] stage: lint script: - biome ci --reporter=gitlab --colors=off > /tmp/code-quality.json artifacts: reports: codequality: - code-quality.json rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' ``` --- ## Git Hooks Configuration ### Husky with --staged (Simplest) ```bash # Install and configure Husky npm install --save-dev husky npx husky init ``` ```bash # .husky/pre-commit npx biome check --write --staged --files-ignore-unknown=true --no-errors-on-unmatched ``` **Why good:** The `--staged` flag (Biome v1.7.0+) eliminates the need for lint-staged entirely — Biome handles staged file filtering natively ### Lefthook ```yaml # lefthook.yml pre-commit: commands: biome-check: glob: "*.{js,ts,cjs,mjs,jsx,tsx,json,jsonc,css}" run: > npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files} stage_fixed: true ``` ### pre-commit Framework ```yaml # .pre-commit-config.yaml repos: - repo: https://github.com/biomejs/pre-commit rev: "v2.0.6" hooks: - id: biome-check additional_dependencies: ["@biomejs/biome@2.4.7"] ``` --- ## Framework-Specific Configurations ### React/Next.js ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "linter": { "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "useExhaustiveDependencies": "warn", }, "style": { "useImportType": "error", }, }, "domains": { "react": "recommended", }, }, "javascript": { "jsxRuntime": "transparent", }, } ``` ### Node.js/Server ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "linter": { "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "noUnusedVariables": "warn", }, "style": { "noDefaultExport": "error", "useImportType": "error", "useNodejsImportProtocol": "error", }, "suspicious": { "noExplicitAny": "error", }, }, }, } ``` ### Project with CSS Support ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "css": { "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, }, "linter": { "enabled": true, }, "parser": { "cssModules": true, }, }, } ``` --- ## Suppression Examples ### Inline Suppressions ```typescript // Suppress a specific rule // biome-ignore lint/suspicious/noDebugger: needed during local development debugger; // Suppress formatter for a complex expression // biome-ignore format: manual alignment is clearer here const matrix = [ [1, 0, 0], [0, 1, 0], [0, 0, 1], ]; // Suppress an entire group // biome-ignore lint/style: legacy code, will refactor later var x = 1; ``` ### File-Level Suppressions ```typescript // biome-ignore-all lint/style/noDefaultExport: Next.js page requires default export // biome-ignore-all lint/correctness/noUnusedVariables: template file with example vars export default function Page() { const example = "placeholder"; return <div>{example}</div>; } ``` ### Range Suppressions ```typescript // biome-ignore-start lint/suspicious/noDoubleEquals: legacy null checks function processLegacyData(input: unknown) { if (input == null) return; if (input == undefined) return; } // biome-ignore-end lint/suspicious/noDoubleEquals: legacy null checks // Modern code below uses strict equality function processData(input: unknown) { if (input === null || input === undefined) return; } ``` --- ## Overrides for Mixed Projects ### Test Files, Config Files, and Generated Code ```jsonc { "linter": { "rules": { "recommended": true, "style": { "noDefaultExport": "warn", "useImportType": "error", }, }, }, "overrides": [ { // Test files: relax strictness "includes": [ "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/__tests__/**", ], "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, "style": { "noDefaultExport": "off", }, }, "domains": { "test": "recommended", }, }, }, { // Config files: allow default exports (Vite, etc.) "includes": ["*.config.ts", "*.config.mjs", "*.config.js"], "linter": { "rules": { "style": { "noDefaultExport": "off", }, }, }, }, { // Generated files: disable linting and formatting "includes": ["**/generated/**", "**/*.generated.ts"], "linter": { "enabled": false, }, "formatter": { "enabled": false, }, }, ], } ``` **Why good:** Production code stays strict, test files get appropriate relaxations, config files allow framework-required default exports, generated code is completely excluded from processing --- ## See Also - [reference.md](../reference.md) for CLI quick reference and configuration options - [SKILL.md](../SKILL.md) for core patterns and philosophy **Official Documentation:** - [Biome Getting Started](https://biomejs.dev/guides/getting-started/) - [Biome Configuration](https://biomejs.dev/guides/configure-biome/) - [Biome Migration Guide](https://biomejs.dev/guides/migrate-eslint-prettier/) - [Biome Git Hooks](https://biomejs.dev/recipes/git-hooks/) - [Biome CI Integration](https://biomejs.dev/recipes/continuous-integration/) -
ci.md 5.2 KB
# Biome -- CI & Git Hooks Examples > CI pipeline integration, pre-commit hooks, and staged file processing. Reference from [SKILL.md](../SKILL.md). **Related examples:** - [core.md](core.md) -- Installation, biome.json config, editor integration - [linting.md](linting.md) -- Lint rules, domains, suppressions, overrides - [formatting.md](formatting.md) -- Formatter config, Prettier compatibility - [migration.md](migration.md) -- Migrating from ESLint + Prettier --- ## GitHub Actions (Minimal) ```yaml # .github/workflows/lint.yml name: Lint & Format on: [push, pull_request] jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: biomejs/setup-biome@v2 - run: biome ci . ``` **Key:** The `biomejs/setup-biome` action installs the Biome binary directly -- no Node.js or npm required. --- ## GitHub Actions (Full Pipeline) ```yaml # .github/workflows/quality.yml name: Code Quality on: push: branches: [main] pull_request: jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # Option A: Use setup-biome (no Node.js needed) - uses: biomejs/setup-biome@v2 with: version: latest # Run Biome CI with strict mode - run: biome ci --error-on-warnings --max-diagnostics=100 . # If using Biome with other Node.js tools biome-with-node: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci - run: npx biome ci . ``` --- ## GitHub Actions (Changed Files Only) ```yaml # .github/workflows/lint-changed.yml name: Lint Changed Files on: pull_request jobs: biome: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: biomejs/setup-biome@v2 - run: biome ci --changed --since=origin/main . ``` --- ## GitLab CI ```yaml # .gitlab-ci.yml biome: image: name: ghcr.io/biomejs/biome:latest entrypoint: [""] stage: lint script: - biome ci --reporter=gitlab --colors=off > /tmp/code-quality.json artifacts: reports: codequality: - code-quality.json rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' ``` --- ## CLI Commands for CI vs Local ```bash # Run everything: lint + format + organize imports (read-only) npx biome check . # Run everything with auto-fix npx biome check --write . # Format only npx biome format --write . # Lint only npx biome lint --write . # CI mode (read-only, optimized for pipelines) npx biome ci . ``` ### Filtering and Targeting ```bash # Run only specific rule groups npx biome lint --only=correctness . # Skip specific rules npx biome lint --skip=style/useNamingConvention . # Check only staged files (pre-commit hooks) npx biome check --staged --write . # Check only changed files (compared to main branch) npx biome check --changed --since=main . # Apply unsafe fixes (requires review) npx biome check --write --unsafe . ``` ### Output and Reporting ```bash # Verbose output npx biome check --verbose . # JSON reporter npx biome ci --reporter=json . # GitHub annotations (auto-detected in GitHub Actions) npx biome ci --reporter=github . # GitLab code quality report npx biome ci --reporter=gitlab --colors=off > code-quality.json # Error on warnings (strict mode) npx biome ci --error-on-warnings . # Limit diagnostics output npx biome check --max-diagnostics=50 . ``` **Why good:** `check --write` handles everything in one command, `ci` is purpose-built for pipelines (no `--write` flag, better runner integration), `--staged` eliminates the need for lint-staged, `--changed` enables incremental CI checks --- ## Git Hooks ### Husky with --staged (Simplest) ```bash # Install and configure Husky npm install --save-dev husky npx husky init ``` ```bash # .husky/pre-commit npx biome check --write --staged --files-ignore-unknown=true --no-errors-on-unmatched ``` **Why good:** The `--staged` flag (Biome v1.7.0+) eliminates the need for lint-staged entirely -- Biome handles staged file filtering natively ### Husky + lint-staged If using lint-staged for multiple tools: ```jsonc // package.json { "lint-staged": { "*.{js,ts,jsx,tsx,json,jsonc,css}": [ "biome check --write --no-errors-on-unmatched", ], }, } ``` ### Lefthook ```yaml # lefthook.yml pre-commit: commands: biome-check: glob: "*.{js,ts,cjs,mjs,jsx,tsx,json,jsonc,css}" run: > npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files} stage_fixed: true ``` ### pre-commit Framework ```yaml # .pre-commit-config.yaml repos: - repo: https://github.com/biomejs/pre-commit rev: "v2.0.6" hooks: - id: biome-check additional_dependencies: ["@biomejs/biome@2.4.7"] ``` --- ## See Also - [SKILL.md](../SKILL.md) for core patterns and philosophy - [reference.md](../reference.md) for complete CLI flags reference **Official Documentation:** - [Biome CI Integration](https://biomejs.dev/recipes/continuous-integration/) - [Biome Git Hooks](https://biomejs.dev/recipes/git-hooks/) - [Biome CLI Reference](https://biomejs.dev/reference/cli/) -
core.md 7.7 KB
# Biome -- Setup & Configuration Examples > Installation, biome.json configuration, editor integration, and package.json scripts. Reference from [SKILL.md](../SKILL.md). **Related examples:** - [linting.md](linting.md) -- Lint rules, domains, suppressions, overrides - [formatting.md](formatting.md) -- Formatter config, Prettier compatibility - [ci.md](ci.md) -- CI pipelines, git hooks, staged files - [migration.md](migration.md) -- Migrating from ESLint + Prettier --- ## Step-by-Step Initialization ```bash # 1. Install Biome (always pin exact version) npm install --save-dev --save-exact @biomejs/biome # 2. Create default biome.json npx @biomejs/biome init # 3. Add scripts to package.json ``` ```jsonc // package.json { "scripts": { "check": "biome check .", "check:fix": "biome check --write .", "format": "biome format --write .", "lint": "biome lint .", "lint:fix": "biome lint --write .", "ci": "biome ci .", }, "devDependencies": { "@biomejs/biome": "2.4.7", }, } ``` --- ## Production-Ready biome.json ```jsonc // biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true, "defaultBranch": "main", }, "files": { "ignoreUnknown": true, "includes": ["**"], }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf", }, "linter": { "enabled": true, "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "noUnusedVariables": "warn", }, "style": { "noDefaultExport": "warn", "useImportType": "error", }, "suspicious": { "noExplicitAny": "warn", }, }, }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on", }, }, }, "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always", "trailingCommas": "all", "arrowParentheses": "always", "bracketSameLine": false, }, }, "json": { "formatter": { "trailingCommas": "none", }, }, "css": { "formatter": { "enabled": true, }, }, "overrides": [ { "includes": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"], "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, }, }, }, ], } ``` **Why good:** `$schema` enables editor autocompletion, VCS integration skips `.gitignore`d files, explicit formatter settings prevent tab/space surprises, `noUnusedImports` catches dead imports, `useImportType` enforces `import type`, `noDefaultExport` encourages named exports, test file overrides relax strict rules where needed, CSS formatting explicitly enabled --- ## VS Code Integration Install the [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) from the VS Code Marketplace. ```jsonc // .vscode/settings.json { // Set Biome as default formatter "editor.defaultFormatter": "biomejs.biome", // Format on save "editor.formatOnSave": true, // Organize imports on save "editor.codeActionsOnSave": { "source.organizeImports.biome": "explicit", }, // Language-specific overrides (if needed) "[javascript]": { "editor.defaultFormatter": "biomejs.biome", }, "[typescript]": { "editor.defaultFormatter": "biomejs.biome", }, "[json]": { "editor.defaultFormatter": "biomejs.biome", }, } ``` **VS Code Extension v3 features:** - Multi-root workspace support (each folder runs its own Biome instance) - Single-file mode for files outside projects - Automatic `biome.json` discovery --- ## JetBrains (IntelliJ, WebStorm) Install the [Biome plugin](https://plugins.jetbrains.com/plugin/22761-biome) from the JetBrains Marketplace. The plugin auto-discovers Biome from `node_modules/.bin/biome`. Add Biome as a project dependency to ensure the plugin and CLI use the same version. --- ## Framework-Specific Configurations ### React / Next.js ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "linter": { "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "useExhaustiveDependencies": "warn", }, "style": { "useImportType": "error", }, }, "domains": { "react": "recommended", }, }, "javascript": { "jsxRuntime": "transparent", }, } ``` ### Node.js / Server ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "linter": { "rules": { "recommended": true, "correctness": { "noUnusedImports": "error", "noUnusedVariables": "warn", }, "style": { "noDefaultExport": "error", "useImportType": "error", "useNodejsImportProtocol": "error", }, "suspicious": { "noExplicitAny": "error", }, }, }, } ``` ### CSS Support ```jsonc { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "css": { "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, }, "linter": { "enabled": true, }, "parser": { "cssModules": true, }, }, } ``` --- ## Monorepo Nested Configuration ### Root Configuration ```jsonc // biome.json (project root) { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true, }, "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf", }, "linter": { "rules": { "recommended": true, "style": { "noDefaultExport": "warn", "useImportType": "error", }, }, }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on", }, }, }, "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always", "trailingCommas": "all", }, }, } ``` ### Next.js App Override ```jsonc // apps/web/biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "extends": "//", "linter": { "rules": { "style": { // Next.js requires default exports for pages and layouts "noDefaultExport": "off", }, }, "domains": { "react": "recommended", }, }, "overrides": [ { "includes": [ "**/app/**/page.tsx", "**/app/**/layout.tsx", "**/app/**/loading.tsx", ], "linter": { "rules": { "style": { "noDefaultExport": "off", }, }, }, }, ], } ``` ### Legacy Package Override ```jsonc // packages/legacy-lib/biome.json { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "root": false, "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, "correctness": { "noUnusedVariables": "off", }, }, }, } ``` **Why good:** Root config establishes team-wide standards, `"extends": "//"` shorthand inherits root config, Next.js app relaxes default export rule where framework requires it, legacy package can disable strict rules while the rest of the monorepo stays strict --- ## See Also - [SKILL.md](../SKILL.md) for core patterns and philosophy - [reference.md](../reference.md) for CLI quick reference and configuration options **Official Documentation:** - [Biome Getting Started](https://biomejs.dev/guides/getting-started/) - [Biome Configuration](https://biomejs.dev/guides/configure-biome/) - [Biome VS Code Extension](https://biomejs.dev/reference/vscode/) -
formatting.md 2.7 KB
# Biome -- Formatting Examples > Formatter configuration, language-specific settings, and Prettier compatibility. Reference from [SKILL.md](../SKILL.md). **Related examples:** - [core.md](core.md) -- Installation, biome.json config, editor integration - [linting.md](linting.md) -- Lint rules, domains, suppressions, overrides - [ci.md](ci.md) -- CI pipelines, git hooks, staged files - [migration.md](migration.md) -- Migrating from ESLint + Prettier --- ## Global vs Language-Specific Settings ```jsonc { // Global formatter settings (all languages) "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf", "bracketSpacing": true, }, // JavaScript/TypeScript-specific overrides "javascript": { "formatter": { "quoteStyle": "double", "jsxQuoteStyle": "double", "semicolons": "always", "trailingCommas": "all", "arrowParentheses": "always", "bracketSameLine": false, }, }, // JSON-specific settings "json": { "formatter": { "trailingCommas": "none", }, }, // CSS formatting (disabled by default, opt-in) "css": { "formatter": { "enabled": true, }, }, } ``` **Why good:** Global settings provide a baseline for all languages, language-specific settings override without repetition, CSS/GraphQL formatting explicitly opted into since they are disabled by default --- ## Key Differences from Prettier Defaults | Setting | Biome Default | Prettier Default | Notes | | ---------------- | ------------- | ---------------- | ---------------------- | | `indentStyle` | `"tab"` | spaces | Biome defaults to tabs | | `indentWidth` | `2` | `2` | Same | | `lineWidth` | `80` | `80` | Same | | `quoteStyle` | `"double"` | `"double"` | Same | | `semicolons` | `"always"` | `true` | Different naming | | `trailingCommas` | `"all"` | `"all"` | Same (Prettier 3.0+) | **Important:** When migrating from Prettier, explicitly set `indentStyle: "space"` if your project uses spaces -- Biome defaults to tabs. --- > For the Prettier-to-Biome option name mapping table, see [reference.md](../reference.md#biome-vs-prettier-option-name-mapping). --- ## See Also - [SKILL.md](../SKILL.md) for core patterns and philosophy - [reference.md](../reference.md) for CLI quick reference **Official Documentation:** - [Biome Configuration Reference](https://biomejs.dev/reference/configuration/) - [Biome Migration Guide](https://biomejs.dev/guides/migrate-eslint-prettier/) -
linting.md 6.9 KB
# Biome -- Linting Examples > Lint rules configuration, domains, suppression comments, and file-specific overrides. Reference from [SKILL.md](../SKILL.md). **Related examples:** - [core.md](core.md) -- Installation, biome.json config, editor integration - [formatting.md](formatting.md) -- Formatter config, Prettier compatibility - [ci.md](ci.md) -- CI pipelines, git hooks, staged files - [migration.md](migration.md) -- Migrating from ESLint + Prettier --- ## Rule Configuration ### Recommended Baseline with Customizations ```jsonc // biome.json { "linter": { "enabled": true, "rules": { "recommended": true, // Enable all style rules, then configure individual ones "style": { "all": true, "useNamingConvention": { "level": "warn", "options": { "strictCase": false, }, }, }, // Disable specific rules "complexity": { "noForEach": "off", }, // Enable nursery rules explicitly "nursery": { "noConsole": "warn", }, }, }, } ``` **Why good:** `recommended: true` provides a strong baseline without per-rule config, group-level overrides (`"all": true`) enable entire categories, individual rules can be tuned with options, nursery rules opted into explicitly for experimental features --- ## Domains (Technology-Specific Rules) Biome v2 introduces domains that group rules by technology: ```jsonc { "linter": { "domains": { "react": "recommended", "test": "recommended", "solid": "off", }, }, } ``` Domains auto-detect from `package.json` dependencies when not explicitly configured. | Domain | Detected From | Purpose | | --------- | --------------------------- | ---------------------------- | | `react` | react in package.json | React-specific rules | | `solid` | solid-js in package.json | SolidJS-specific rules | | `test` | vitest/jest in package.json | Test-specific rules | | `project` | Manual opt-in | Cross-file analysis rules | | `types` | Manual opt-in | Type inference rules (v2.4+) | --- ## Suppression Comments ### Inline Suppression (Next Line) ```typescript // Suppress a specific rule // biome-ignore lint/suspicious/noDebugger: needed during local development debugger; // Suppress formatter for a complex expression // biome-ignore format: manual alignment is clearer here const matrix = [ [1, 0, 0], [0, 1, 0], [0, 0, 1], ]; // Suppress an entire group // biome-ignore lint/style: legacy code, will refactor later var x = 1; ``` ### File-Level Suppression (Top of File) ```typescript // biome-ignore-all lint/style/noDefaultExport: Next.js page requires default export // biome-ignore-all lint/correctness/noUnusedVariables: template file with example vars export default function Page() { const example = "placeholder"; return <div>{example}</div>; } ``` **Important:** `biome-ignore-all` must be placed at the top of the file. Placing it mid-file triggers an unused suppression warning. ### Range Suppression ```typescript // biome-ignore-start lint/suspicious/noDoubleEquals: legacy null checks function processLegacyData(input: unknown) { if (input == null) return; if (input == undefined) return; } // biome-ignore-end lint/suspicious/noDoubleEquals: legacy null checks // Modern code below uses strict equality function processData(input: unknown) { if (input === null || input === undefined) return; } ``` Suppressions can target a category (`lint`), group (`lint/suspicious`), or individual rule (`lint/suspicious/noDebugger`). See [reference.md](../reference.md#suppression-comment-syntax) for the full specifier table. **Important:** Explanations are mandatory. `// biome-ignore lint:` without a reason after the colon will be flagged. --- ## Overrides (File-Specific Rules) ### Test Files, Config Files, and Generated Code ```jsonc { "linter": { "rules": { "recommended": true, "style": { "noDefaultExport": "warn", "useImportType": "error", }, }, }, "overrides": [ { // Test files: relax strictness "includes": [ "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/__tests__/**", ], "linter": { "rules": { "suspicious": { "noExplicitAny": "off", }, "style": { "noDefaultExport": "off", }, }, "domains": { "test": "recommended", }, }, }, { // Config files: allow default exports (bundler configs, etc.) "includes": ["*.config.ts", "*.config.mjs", "*.config.js"], "linter": { "rules": { "style": { "noDefaultExport": "off", }, }, }, }, { // Generated files: disable linting and formatting "includes": ["**/generated/**", "**/*.generated.ts"], "linter": { "enabled": false, }, "formatter": { "enabled": false, }, }, ], } ``` **Why good:** Production code stays strict, test files get appropriate relaxations, config files allow framework-required default exports, generated code is completely excluded from processing --- ## Custom Import Ordering ### React Project with Company Packages ```jsonc { "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ ":NODE:", ":PACKAGE:", ":BLANK_LINE:", ["@company/**"], ":BLANK_LINE:", ":ALIAS:", ":PATH:", ], }, }, }, }, }, } ``` **Result:** ```typescript import { readFileSync } from "node:fs"; import { z } from "zod"; import { apiClient } from "@company/api-client"; import { Button } from "@company/ui"; import { useAuth } from "@/hooks/use-auth"; import { formatDate } from "../utils/date"; import { UserCard } from "./user-card"; ``` ### Separating Type Imports ```jsonc { "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [{ "type": false }, ":BLANK_LINE:", { "type": true }], }, }, }, }, }, } ``` **Result:** ```typescript import { z } from "zod"; import { clsx } from "clsx"; import { Button } from "./button"; import type { User } from "../types/user"; import type { Config } from "@company/shared"; ``` --- ## See Also - [SKILL.md](../SKILL.md) for core patterns and philosophy - [reference.md](../reference.md) for rule groups and severity values **Official Documentation:** - [Biome Linter Rules](https://biomejs.dev/linter/) - [Biome Suppressions](https://biomejs.dev/analyzer/suppressions/) - [Biome Import Organizer](https://biomejs.dev/assist/actions/organize-imports/) -
migration.md 4.2 KB
# Biome -- Migration from ESLint + Prettier > Step-by-step migration guide, rule mapping, and package cleanup. Reference from [SKILL.md](../SKILL.md). **Related examples:** - [core.md](core.md) -- Installation, biome.json config, editor integration - [linting.md](linting.md) -- Lint rules, domains, suppressions, overrides - [formatting.md](formatting.md) -- Formatter config, Prettier compatibility - [ci.md](ci.md) -- CI pipelines, git hooks, staged files --- ## Automated Migration ```bash # Step 1: Migrate Prettier settings (indent, quotes, line width) npx @biomejs/biome migrate prettier --write # Step 2: Migrate ESLint rules (maps to Biome equivalents) npx @biomejs/biome migrate eslint --write # Step 3: Include rules that are "inspired by" ESLint (not exact matches) npx @biomejs/biome migrate eslint --write --include-inspired # Step 4: Enable VCS integration (ESLint respects .gitignore by default) # Add to biome.json manually: # "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true } # Step 5: Verify migration npx @biomejs/biome check . # Step 6: Remove old tooling npm uninstall eslint prettier eslint-config-prettier eslint-plugin-only-warn \ @eslint/js typescript-eslint eslint-plugin-react eslint-plugin-jsx-a11y # Step 7: Remove old config files rm -f .eslintrc* eslint.config.* .prettierrc* prettier.config.* .eslintignore .prettierignore ``` --- ## Manual Migration Checklist | ESLint + Prettier | Biome Equivalent | | -------------------------------------------- | --------------------------------------------- | | `.eslintrc.json` / `eslint.config.ts` | `biome.json` | | `.prettierrc` / `prettier.config.mjs` | `biome.json` (formatter section) | | `.eslintignore` | `biome.json` files.includes with `!` patterns | | `.prettierignore` | `biome.json` files.includes with `!` patterns | | `eslint-config-prettier` | Not needed (no formatter/linter conflicts) | | `eslint-plugin-only-warn` | Set rule severity to `"warn"` | | `eslint-plugin-import` | `assist.actions.source.organizeImports` | | `@typescript-eslint/parser` | Built-in TypeScript support | | `@typescript-eslint/consistent-type-imports` | `style/useImportType` | | `@typescript-eslint/no-unused-vars` | `correctness/noUnusedVariables` | | `import/no-default-export` | `style/noDefaultExport` | | `no-console` | `nursery/noConsole` | --- ## Removing Unnecessary Packages After migration, these packages are no longer needed: ```bash # Core tools (replaced by Biome) npm uninstall eslint prettier # ESLint plugins (handled by Biome rules) npm uninstall @eslint/js typescript-eslint eslint-config-prettier npm uninstall eslint-plugin-only-warn eslint-plugin-react npm uninstall eslint-plugin-jsx-a11y eslint-plugin-unicorn npm uninstall eslint-plugin-import eslint-plugin-simple-import-sort # Prettier plugins npm uninstall @prettier/sync prettier-plugin-tailwindcss ``` --- ## Full Migration vs Hybrid Approach ``` Migrating from ESLint + Prettier? |-- Standard rules only (recommended + typescript-eslint)? | +-- Full migration to Biome (Biome covers these) |-- Using framework-specific ESLint plugins? | |-- React/JSX-a11y/Unicorn? | | +-- Full migration (Biome has equivalent rules) | |-- Custom/niche plugins? | | +-- Hybrid: Biome format + ESLint for custom rules | +-- Many custom rules with specific options? | +-- Hybrid approach (migrate incrementally) +-- Just want faster formatting? +-- Replace Prettier with Biome format, keep ESLint ``` --- ## See Also - [SKILL.md](../SKILL.md) for core patterns and philosophy - [formatting.md](formatting.md) for Prettier option name mapping **Official Documentation:** - [Biome Migration Guide](https://biomejs.dev/guides/migrate-eslint-prettier/) - [Biome Upgrade to v2 Guide](https://biomejs.dev/guides/upgrade-to-biome-v2/) -
setup.md 50 B
This file has been renamed to [core.md](core.md).
-
-
reference.md 12.8 KB
# Biome Quick Reference > CLI commands, configuration options, and rule groups for Biome v2.4.x. See [SKILL.md](SKILL.md) for core patterns and [examples/](examples/) for practical examples. --- ## CLI Commands ### Primary Commands | Command | Purpose | Key Flags | | ------------------------ | ------------------------------------------------ | ---------------------------------------------- | | `biome check .` | Run lint + format + organize imports (read-only) | `--write`, `--unsafe`, `--staged`, `--changed` | | `biome check --write .` | Run everything with auto-fix | `--unsafe` (include unsafe fixes) | | `biome format .` | Format only (read-only) | `--write` | | `biome format --write .` | Format with auto-fix | | | `biome lint .` | Lint only (read-only) | `--write`, `--only`, `--skip` | | `biome lint --write .` | Lint with safe fixes | `--unsafe` | | `biome ci .` | CI mode (read-only, no `--write`) | `--reporter`, `--error-on-warnings` | ### Setup and Migration | Command | Purpose | | ------------------------------------------------- | --------------------------------------- | | `biome init` | Create default biome.json | | `biome migrate --write` | Upgrade config between major versions | | `biome migrate eslint --write` | Convert ESLint config to biome.json | | `biome migrate prettier --write` | Convert Prettier config to biome.json | | `biome migrate eslint --write --include-inspired` | Include inspired (non-equivalent) rules | ### Utility Commands | Command | Purpose | | ------------------------ | --------------------------------------------- | | `biome explain <rule>` | Show documentation for a rule | | `biome rage` | Output debugging information | | `biome search <pattern>` | Search code with Grit patterns (experimental) | | `biome clean` | Remove daemon logs | | `biome start` | Start daemon server | | `biome stop` | Stop daemon server | --- ## Common Flags | Flag | Commands | Purpose | | ----------------------------- | ----------------------- | ---------------------------------------------------------- | | `--write` | check, format, lint | Apply fixes to files | | `--unsafe` | check, lint | Include unsafe (behavior-changing) fixes | | `--staged` | check, format, lint | Process only git staged files | | `--changed` | check, format, lint, ci | Process files changed since default branch | | `--since=<branch>` | check, format, lint, ci | Process files changed since specified branch | | `--only=<group>` | check, lint, ci | Run only specific rule group(s) | | `--skip=<rule>` | check, lint, ci | Skip specific rule(s) | | `--reporter=<fmt>` | all | Output format: default, json, github, gitlab, junit, sarif | | `--error-on-warnings` | all | Exit non-zero on warnings | | `--max-diagnostics=<n>` | all | Limit number of diagnostics shown | | `--verbose` | all | Verbose output | | `--no-errors-on-unmatched` | all | Suppress errors when no files match | | `--files-ignore-unknown=true` | all | Skip unsupported file types | | `--config-path=<path>` | all | Specify config file location | | `--colors=off` | all | Disable colored output | | `--profile-rules` | check, lint | Profile rule execution time (v2.4+) | --- ## Formatter Configuration Options ### Global Options (All Languages) | Option | Type | Default | Notes | | ------------------- | ---------------------------- | -------- | ------------------------------- | | `enabled` | boolean | `true` | Enable/disable formatting | | `indentStyle` | `"tab"` \| `"space"` | `"tab"` | **Biome defaults to tabs** | | `indentWidth` | number | `2` | Spaces per indent level | | `lineWidth` | number | `80` | Maximum line width | | `lineEnding` | `"lf"` \| `"crlf"` \| `"cr"` | `"lf"` | Line ending character | | `bracketSpacing` | boolean | `true` | Spaces inside `{ }` | | `attributePosition` | `"auto"` \| `"multiline"` | `"auto"` | HTML/JSX attribute position | | `useEditorconfig` | boolean | `false` | Respect .editorconfig | | `formatWithErrors` | boolean | `false` | Format files with syntax errors | ### JavaScript/TypeScript Options | Option | Type | Default | Notes | | ------------------ | ------------------------------ | ------------ | ---------------------------- | | `quoteStyle` | `"single"` \| `"double"` | `"double"` | String quote style | | `jsxQuoteStyle` | `"single"` \| `"double"` | `"double"` | JSX attribute quote style | | `quoteProperties` | `"asNeeded"` \| `"preserve"` | `"asNeeded"` | Object property quoting | | `trailingCommas` | `"all"` \| `"es5"` \| `"none"` | `"all"` | Trailing comma behavior | | `semicolons` | `"always"` \| `"asNeeded"` | `"always"` | Semicolon insertion | | `arrowParentheses` | `"always"` \| `"asNeeded"` | `"always"` | Arrow function parens | | `bracketSameLine` | boolean | `false` | JSX closing `>` on same line | ### JSON Options | Option | Type | Default | Notes | | ---------------- | ------------------- | -------- | -------------------- | | `trailingCommas` | `"none"` \| `"all"` | `"none"` | JSON trailing commas | --- ## Linter Rule Groups | Group | Purpose | Default Severity | | --------------- | ------------------------------- | --------------------- | | `accessibility` | Prevents a11y problems | error (recommended) | | `complexity` | Simplifies complex code | error (recommended) | | `correctness` | Detects guaranteed errors | error (recommended) | | `nursery` | Experimental rules | off (opt-in required) | | `performance` | Catches inefficient patterns | error (recommended) | | `security` | Identifies security flaws | error (recommended) | | `style` | Enforces consistent code style | warn (recommended) | | `suspicious` | Flags likely incorrect patterns | error (recommended) | ### Rule Severity Values | Level | CLI Exit | Purpose | | --------- | -------- | ------------------------------ | | `"off"` | N/A | Rule disabled | | `"on"` | varies | Default severity for that rule | | `"info"` | 0 | Informational diagnostic | | `"warn"` | 0 | Non-blocking warning | | `"error"` | 1 | Blocking error | ### Domains (Technology-Specific) | Domain | Detected From | Purpose | | --------- | --------------------------- | -------------------------------------------------------------- | | `react` | react in package.json | React-specific rules | | `solid` | solid-js in package.json | SolidJS-specific rules | | `test` | vitest/jest in package.json | Test-specific rules | | `project` | Manual opt-in | Cross-file analysis (module graph scanning) | | `types` | Manual opt-in | Type inference rules (v2.4+, ~75% tsc coverage for type rules) | --- ## Suppression Comment Syntax | Type | Syntax | Scope | | ----------- | -------------------------------------- | ---------------------------- | | Inline | `// biome-ignore <spec>: reason` | Next line | | File-wide | `// biome-ignore-all <spec>: reason` | Entire file (must be at top) | | Range start | `// biome-ignore-start <spec>: reason` | Until matching end | | Range end | `// biome-ignore-end <spec>: reason` | Ends matching range | ### Specifier Levels | Level | Example | | -------- | ---------------------------- | | Category | `lint`, `format`, `assist` | | Group | `lint/suspicious` | | Rule | `lint/suspicious/noDebugger` | --- ## Configuration File Resolution **Search order:** `biome.json` > `biome.jsonc` > `.biome.json` > `.biome.jsonc` **Search locations:** 1. Current working directory 2. Parent directories (recursively) 3. Home config directory (`$XDG_CONFIG_HOME/biome`, etc.) **Nested configs:** Files use the nearest `biome.json` in parent hierarchy. Child configs use `"root": false`. --- ## Biome vs Prettier: Option Name Mapping | Prettier | Biome | Notes | | ----------------- | ------------------------- | -------------------- | | `printWidth` | `lineWidth` | | | `tabWidth` | `indentWidth` | | | `useTabs` | `indentStyle: "tab"` | | | `semi` | `semicolons: "always"` | Different naming | | `singleQuote` | `quoteStyle: "single"` | Different naming | | `trailingComma` | `trailingCommas` | Plural in Biome | | `bracketSpacing` | `bracketSpacing` | Same | | `bracketSameLine` | `bracketSameLine` | Same | | `arrowParens` | `arrowParentheses` | Longer name in Biome | | `endOfLine` | `lineEnding` | Different naming | | `jsxSingleQuote` | `jsxQuoteStyle: "single"` | Different naming | --- ## Version History | Version | Release | Key Features | | ------- | -------- | -------------------------------------------------------------------- | | v2.4.x | Feb 2026 | Embedded snippets, HTML a11y rules, types domain, rule profiler | | v2.0 | Jun 2025 | Type-aware linting, nested configs, import organizer revamp, plugins | | v1.9.x | 2024 | CSS support, GraphQL support, `--staged` flag | | v1.0 | Aug 2023 | Initial stable release (fork of Rome) | --- ## See Also - [examples/core.md](examples/core.md) for installation, biome.json, editor integration - [examples/linting.md](examples/linting.md) for lint rules, suppressions, overrides - [examples/formatting.md](examples/formatting.md) for formatter options, Prettier mapping - [examples/ci.md](examples/ci.md) for CI pipelines, git hooks, staged files - [examples/migration.md](examples/migration.md) for ESLint/Prettier migration - [SKILL.md](SKILL.md) for core patterns and philosophy **Official Documentation:** - [Biome Configuration Reference](https://biomejs.dev/reference/configuration/) - [Biome CLI Reference](https://biomejs.dev/reference/cli/) - [Biome Linter Rules](https://biomejs.dev/linter/) - [Biome Migration Guide](https://biomejs.dev/guides/migrate-eslint-prettier/) - [Biome Git Hooks](https://biomejs.dev/recipes/git-hooks/) - [Biome CI Integration](https://biomejs.dev/recipes/continuous-integration/) - [Biome VS Code Extension](https://biomejs.dev/reference/vscode/) -
SKILL.md 19.6 KB
--- name: shared-tooling-biome description: Biome v2 unified linter, formatter, and import organizer — single Rust-powered tool replacing ESLint + Prettier with 97% Prettier compatibility and 20x faster performance --- # Biome > **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 `biome.json` for all configuration. Run `biome check --write` to lint, format, and organize imports in one pass. Use `biome ci` in pipelines. > > **Current 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, `import type`, named constants) **(You MUST use `biome.json` or `biome.jsonc` for ALL configuration — Biome does not use JavaScript config files)** **(You MUST pin Biome to an exact version with `--save-exact` — Biome formatting can change between versions)** **(You MUST use `biome ci` in CI pipelines, NOT `biome check` — `ci` is read-only with no `--write` flag)** **(You MUST use `biome check --write` for local development — runs linter, formatter, and import organizer in one pass)** **(You MUST include `$schema` in biome.json for editor autocompletion and validation)** </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 `--staged` flag **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 (`tsconfig.json` is a separate concern) **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, `--staged` flag) - CI integration with GitHub Actions and GitLab CI - Editor integration (VS Code, JetBrains) - Suppression comments (`biome-ignore`, `biome-ignore-all`, range suppressions) - Nested configuration for monorepos - Overrides for file-specific settings --- ## Examples - [Setup & Configuration](examples/core.md) — Installation, biome.json, VS Code, monorepos, framework configs - [Linting Rules](examples/linting.md) — Rule groups, domains, suppressions, overrides, import ordering - [Formatting](examples/formatting.md) — Formatter options, Prettier compatibility, option mapping - [CI & Git Hooks](examples/ci.md) — GitHub Actions, GitLab CI, Husky, Lefthook, staged files - [Migrating from ESLint/Prettier](examples/migration.md) — Automated migration, rule mapping, package cleanup **Other resources:** - [CLI Quick Reference](reference.md) — 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:** 1. **One tool, one config** — biome.json replaces .eslintrc, prettier.config, and import sorting plugins 2. **Sensible defaults** — Biome works out of the box with recommended rules enabled; zero-config is a valid setup 3. **Speed as a feature** — Rust-powered binary processes large codebases in milliseconds, not seconds 4. **Unified commands** — `biome check --write` runs everything in one pass (lint + format + organize imports) 5. **Safe by default** — Safe fixes apply automatically; unsafe fixes require explicit `--unsafe` flag </philosophy> --- <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. ```bash # Install Biome (always pin exact version) npm install --save-dev --save-exact @biomejs/biome # Create default biome.json npx @biomejs/biome init ``` ```jsonc // 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 ```jsonc // 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](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](reference.md#linter-rule-groups) 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. ```jsonc { "linter": { "domains": { "react": "recommended", "test": "recommended" } } } ``` > **Full examples:** See [examples/linting.md](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. ```jsonc { "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](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`. ```jsonc { "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:` | Node.js built-ins and `node:` protocol | | `:BUN:` | Bun-specific modules | | `:PACKAGE:` | Scoped and bare npm packages | | `:PACKAGE_WITH_PROTOCOL:` | Packages with a protocol prefix | | `:ALIAS:` | Aliased imports (`@/`, `#`, `~`, `$`, `%`) | | `:PATH:` | Absolute and relative path imports | | `:URL:` | HTTP/HTTPS imports | | `:BLANK_LINE:` | Visual separator between groups | > **Full examples:** See [examples/linting.md](examples/linting.md#custom-import-ordering) for import ordering with results. --- ### Pattern 5: CLI Commands Use `check` locally, `ci` in pipelines. Key commands: ```bash 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](examples/ci.md) for complete CLI usage, filtering, and reporting options. --- ### Pattern 6: Suppression Comments Biome uses `biome-ignore` comments with required explanations. ```typescript // 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](reference.md#suppression-comment-syntax) for the full suppression syntax table and specifier levels. See [examples/linting.md](examples/linting.md#suppression-comments) 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. ```jsonc // packages/my-app/biome.json — inherits from root { "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json", "extends": "//" } ``` ```jsonc // 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](examples/core.md#monorepo-nested-configuration) for root + child config patterns. --- ### Pattern 8: Overrides (File-Specific Rules) Use `overrides` for file-pattern-specific configuration without nested config files. ```jsonc { "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 > **Full examples:** See [examples/linting.md](examples/linting.md#overrides-file-specific-rules) for test, config, and generated file overrides. </patterns> --- <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 `biome check`** instead of running `biome format` and `biome lint` separately — single pass is faster - **Enable VCS integration** to automatically skip ignored files (`.gitignore`) - **Use `--staged` or `--changed`** in hooks and CI to process only affected files - **Be selective with nursery rules** — some experimental rules may impact performance - **Use `--profile-rules`** (v2.4+) to identify slow lint rules in your configuration **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) </performance> --- <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](examples/migration.md#full-migration-vs-hybrid-approach). </decision_framework> --- <integration> ## Integration Guide **Works with:** - **JSX/TSX**: Full support with `react` domain for React-specific lint rules - **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 `html.experimentalFullSupportEnabled` (v2.4+) **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 > **CI/editor integration:** See [examples/ci.md](examples/ci.md) and [examples/core.md](examples/core.md#vs-code-integration). </integration> --- <red_flags> ## RED FLAGS **High Priority Issues:** - Using `biome check` in CI instead of `biome ci` (`check` allows `--write` which is dangerous in pipelines; `ci` is read-only) - Not pinning Biome version with `--save-exact` (formatting can change between minor versions, causing diff noise) - Missing `$schema` in biome.json (loses editor autocompletion, validation, and discoverability) - Using JavaScript config files instead of biome.json (Biome only supports JSON/JSONC configuration) - Running `biome format` and `biome lint` separately when `biome check` does both (wastes time, parses files twice) **Medium Priority Issues:** - Forgetting to set `indentStyle: "space"` when migrating from Prettier (Biome defaults to tabs) - Not enabling VCS integration (without it, Biome may process node_modules and dist) - Using `--unsafe` without reviewing changes (unsafe fixes can alter program behavior) - Not including `--no-errors-on-unmatched` in git hooks (causes failures when no matching files are staged) - Enabling all nursery rules (they are experimental and may have bugs or performance issues) **Common Mistakes:** - Using `"root": true` in a nested config (this is the default; use `"root": false` for child configs) - Expecting Markdown/YAML formatting support (Biome does not support these languages yet) - Not running `biome migrate --write` when upgrading major versions (config schema changes between v1 and v2) - Suppression comments without explanations (`biome-ignore lint:` requires text after the colon) **Gotchas & Edge Cases:** - Biome defaults to tabs, not spaces — always set `indentStyle` explicitly when migrating from Prettier - CSS and GraphQL formatting is disabled by default — must opt in with `"formatter": { "enabled": true }` - `biome-ignore-all` must be at the top of the file — placing it mid-file triggers an unused suppression warning - Import organizer is part of `assist`, not `linter` — configure under `assist.actions.source.organizeImports` - The `--staged` flag makes lint-staged unnecessary for Biome-only setups (since Biome v1.7.0+) - Type-aware linting (project/types domains) triggers file scanning which can slow down first runs on large projects - `biome migrate eslint --write` does not migrate inspired rules by default — use `--include-inspired` to include them - Range suppressions (`biome-ignore-start`/`biome-ignore-end`) must have matching rule specifiers - Biome treats all JS/TS/JSX/TSX under the `javascript` config key — there is no separate `typescript` section - Configuration files named `.biome.json` (with leading dot) are also discovered (v2.4+) </red_flags> --- <critical_reminders> ## CRITICAL REMINDERS > **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants) **(You MUST use `biome.json` or `biome.jsonc` for ALL configuration — Biome does not use JavaScript config files)** **(You MUST pin Biome to an exact version with `--save-exact` — Biome formatting can change between versions)** **(You MUST use `biome ci` in CI pipelines, NOT `biome check` — `ci` is read-only with no `--write` flag)** **(You MUST use `biome check --write` for local development — runs linter, formatter, and import organizer in one pass)** **(You MUST include `$schema` in biome.json for editor autocompletion and validation)** **Failure to follow these rules will cause inconsistent formatting, broken CI pipelines, and missed lint errors.** </critical_reminders>
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.