| name | biome-config |
| description | Update Biome linting rules, formatting configs, and import organization settings. Use when adding new lint rules, customizing code style, or fixing workspace-specific linting issues. |
| allowed-tools | Read, Edit, Bash, Grep, Glob |
Biome Configuration Skill
This skill helps you configure and customize Biome for linting and formatting across the monorepo.
When to Use This Skill
- Adding new linting rules
- Customizing code formatting
- Configuring import organization
- Fixing linting errors across the codebase
- Setting up workspace-specific rules
- Debugging Biome configuration issues
- Migrating from ESLint/Prettier
Biome Overview
Biome is an all-in-one toolchain for web projects that provides:
- Linting: Fast, opinionated linting
- Formatting: Consistent code formatting
- Import Organization: Automatic import sorting
The project uses Biome instead of ESLint and Prettier for better performance.
Configuration Structure
sgcarstrends/
├── biome.json # Root Biome config
├── apps/
│ ├── api/
│ │ └── biome.json # API-specific config (extends root)
│ └── web/
│ └── biome.json # Web-specific config (extends root)
└── packages/
└── database/
└── biome.json # Database-specific config
Root Configuration
// biome.json
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "main"
},
"files": {
"ignoreUnknown": false,
"ignore": [
"node_modules",
"dist",
"build",
".next",
".turbo",
"coverage",
".sst"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noUselessCatch": "error",
"noUselessConstructor": "error",
"noUselessEmptyExport": "error",
"noWith": "error"
},
"correctness": {
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyCharacterClassInRegex": "error",
"noEmptyPattern": "error",
"noGlobalObjectCalls": "error",
"noInvalidConstructorSuper": "error",
"noInvalidNewBuiltin": "error",
"noNonoctalDecimalEscape": "error",
"noPrecisionLoss": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noSwitchDeclarations": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "error",
"useIsNan": "error",
"useValidForDirection": "error",
"useYield": "error"
},
"security": {
"noDangerouslySetInnerHtml": "error",
"noDangerouslySetInnerHtmlWithChildren": "error"
},
"style": {
"noArguments": "error",
"noVar": "error",
"useConst": "error",
"useTemplate": "error"
},
"suspicious": {
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCommentText": "error",
"noCompareNegZero": "error",
"noDebugger": "error",
"noDoubleEquals": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "error",
"noExplicitAny": "warn",
"noExtraNonNullAssertion": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noImportAssign": "error",
"noMisleadingCharacterClass": "error",
"noMisleadingInstantiator": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noShadowRestrictedNames": "error",
"noUnsafeDeclarationMerging": "error",
"noUnsafeNegation": "error",
"useGetterReturn": "error",
"useValidTypeof": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false
}
}
}
Workspace-Specific Configuration
Apps Configuration
// apps/web/biome.json
{
"extends": ["../../biome.json"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off" // Allow 'any' in web app for flexibility
}
}
}
}
Test Files Configuration
// Override for test files (if needed)
{
"overrides": [
{
"include": ["**/__tests__/**", "**/*.test.ts", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
}
]
}
Common Commands
Check Code
# Check all files
pnpm biome check .
# Check specific directory
pnpm biome check apps/web
# Check and apply safe fixes
pnpm biome check --write .
# Check only linting
pnpm biome lint .
# Check only formatting
pnpm biome format .
Format Code
# Format all files
pnpm biome format --write .
# Format specific files
pnpm biome format --write apps/web/src/**/*.ts
# Check formatting without writing
pnpm biome format .
Organize Imports
# Organize imports
pnpm biome check --organize-imports-enabled=true --write .
CI Mode
# Check without modifying files (for CI)
pnpm biome ci .
Linting Rules
Enabling/Disabling Rules
Disable a rule globally:
{
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
}
Change severity:
{
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "warn" // error, warn, off
}
}
}
}
Disable inline:
// biome-ignore lint/suspicious/noExplicitAny: Legacy code needs refactoring
function legacy(data: any) {
// ...
}
Disable for entire file:
/* biome-ignore lint/suspicious/noExplicitAny: Test file */
Recommended Rules
Enable all recommended:
{
"linter": {
"rules": {
"recommended": true
}
}
}
Enable specific categories:
{
"linter": {
"rules": {
"recommended": false,
"correctness": {
"recommended": true
},
"security": {
"recommended": true
},
"performance": {
"recommended": true
}
}
}
}
Formatting Configuration
JavaScript/TypeScript
{
"javascript": {
"formatter": {
"quoteStyle": "double", // "single" or "double"
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded", // "asNeeded" or "preserve"
"trailingCommas": "es5", // "none", "es5", or "all"
"semicolons": "always", // "always" or "asNeeded"
"arrowParentheses": "always", // "always" or "asNeeded"
"bracketSpacing": true,
"bracketSameLine": false
}
}
}
Line Width and Indentation
{
"formatter": {
"indentStyle": "space", // "space" or "tab"
"indentWidth": 2, // Number of spaces
"lineWidth": 100, // Max line length
"lineEnding": "lf" // "lf", "crlf", or "cr"
}
}
Import Organization
Configuration
{
"organizeImports": {
"enabled": true
}
}
Import Groups
Biome automatically organizes imports into groups:
- Built-in modules (e.g.,
fs,path) - External modules (e.g.,
react,next) - Internal modules (e.g.,
@/components,~/utils) - Relative imports (e.g.,
./utils,../types)
Example:
// Before
import { Button } from "./components/button";
import { useState } from "react";
import path from "path";
import { db } from "@/lib/db";
// After
import path from "path";
import { useState } from "react";
import { db } from "@/lib/db";
import { Button } from "./components/button";
Git Integration
Git Hooks with Husky
Biome integrates with git hooks:
// .husky/pre-commit
pnpm biome check --write --staged
Git-Aware Processing
{
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true, // Respect .gitignore
"defaultBranch": "main"
}
}
Ignoring Files
Via Configuration
{
"files": {
"ignore": [
"node_modules",
"dist",
"build",
".next",
".turbo",
"coverage",
".sst",
"**/*.config.js",
"migrations/**"
]
}
}
Via .gitignore
With useIgnoreFile: true, Biome respects .gitignore.
Inline Ignore
// biome-ignore format: Auto-generated code
const generated = "...";
Package.json Scripts
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"format:check": "biome format .",
"biome:ci": "biome ci ."
}
}
VS Code Integration
Install Extension
- Install "Biome" extension
- Configure as default formatter
Settings
// .vscode/settings.json
{
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
Migration from ESLint/Prettier
1. Remove Old Tools
# Remove ESLint
pnpm remove -r eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# Remove Prettier
pnpm remove -r prettier
# Remove config files
rm .eslintrc.json .prettierrc .prettierignore
2. Install Biome
# Already installed in project
pnpm add -D -w @biomejs/biome
3. Migrate Configuration
Convert ESLint rules to Biome:
- Check Biome documentation for equivalent rules
- Some rules may not have direct equivalents
- Use
biome migrate eslintfor automated migration
npx @biomejs/biome migrate eslint --write
4. Update Scripts
Replace in package.json:
{
"scripts": {
"lint": "biome check .", // was: eslint .
"format": "biome format --write ." // was: prettier --write .
}
}
Troubleshooting
Rule Conflicts
Issue: Rule seems to contradict another Solution: Check rule documentation, disable one if needed
Performance Issues
Issue: Biome is slow on large codebase Solutions:
- Check
files.ignoreis properly set - Run on specific directories
- Use
--max-diagnosticsto limit output
Format Not Applied
Issue: Files not formatting on save Solutions:
- Check VS Code extension is installed
- Verify
editor.defaultFormatteris set to Biome - Check
biome.jsonis in workspace root
Import Organization Not Working
Issue: Imports not organizing Solutions:
- Verify
organizeImports.enabled: true - Run explicitly:
biome check --organize-imports-enabled=true --write . - Check for syntax errors in file
Advanced Configuration
Per-File Overrides
{
"overrides": [
{
"include": ["**/*.config.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
},
{
"include": ["apps/api/**/*.ts"],
"formatter": {
"lineWidth": 120
}
}
]
}
Custom Rule Severity
{
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": "error"
},
"style": {
"useConst": "warn"
},
"suspicious": {
"noExplicitAny": "off"
}
}
}
}
CI Integration
GitHub Actions
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
biome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- run: pnpm install
- run: pnpm biome ci .
References
- Biome Documentation: https://biomejs.dev
- Migration Guide: https://biomejs.dev/guides/migrate-eslint-prettier
- Rules Reference: https://biomejs.dev/linter/rules
- Related files:
biome.json- Root configuration- Root CLAUDE.md - Code style guidelines
Best Practices
- Use Root Config: Define common rules in root
biome.json - Extend in Workspaces: Extend root config for workspace-specific rules
- Git Integration: Enable VCS integration for
.gitignoresupport - Pre-commit Hooks: Run Biome on staged files
- CI Checks: Use
biome ciin continuous integration - Inline Ignores: Use sparingly and with clear comments
- Consistent Formatting: Apply formatting across entire codebase
- Regular Updates: Keep Biome updated for new rules and fixes