Biome Linter & Formatter Setup is a development Claude Skill built by Lê Thành Danh. Best for: Frontend teams migrate legacy linting/formatting to Biome for 20-100x faster performance and zero dependency overhead..
Configure, customize, and migrate Biome for JavaScript/TypeScript projects; replace ESLint + Prettier with single unified toolchain.
name: biome description: Biome (formerly Rome) — fast unified linter and formatter for JavaScript, TypeScript, JSON, and CSS. Configuration, rule customization, migration from ESLint/Prettier, CI integration layer: utility category: tooling triggers:
Biome is a high-performance unified toolchain for web projects — linting, formatting, and import sorting in a single binary with zero dependencies. It replaces ESLint + Prettier with a single tool that runs 20-100x faster. This skill covers configuration, rule customization, migration from legacy tools, and CI integration.
| Aspect | ESLint + Prettier | Biome |
|--------|-------------------|-------|
| Speed | ~5-30s on large projects | ~100-500ms on same projects |
| Config files | .eslintrc + .prettierrc + plugins | Single biome.json |
| Dependencies | 50-200+ transitive deps | Zero (single binary) |
| Conflict risk | ESLint/Prettier rule conflicts | Unified — no conflicts |
| Language support | JS/TS (via plugins for others) | JS, TS, JSX, TSX, JSON, CSS |
biome check = biome format + biome lint + biome organize-imports
Single pass over each file:
1. Parse into AST (custom high-perf parser)
2. Run lint rules against AST
3. Apply formatting
4. Sort imports
5. Output diagnostics + fixes
# Install as dev dependency
pnpm add -D @biomejs/biome
# Or install globally
pnpm add -g @biomejs/biome
# Initialize config
pnpm biome init
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"organizeImports": {
"enabled": true
},
"formatter": {
"enabled": true,
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf"
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"jsxQuoteStyle": "double"
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
},
"css": {
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 100
},
"linter": {
"enabled": true
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": { "maxAllowedComplexity": 15 }
}
},
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error",
"useExhaustiveDependencies": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn"
},
"style": {
"useConst": "error",
"noNonNullAssertion": "warn",
"useTemplate": "error"
},
"performance": {
"noAccumulatingSpread": "error",
"noDelete": "warn"
},
"nursery": {
"useSortedClasses": {
"level": "warn",
"options": {}
}
}
}
},
"files": {
"ignore": [
"node_modules",
".next",
"dist",
"build",
"coverage",
"*.gen.ts",
"*.d.ts"
],
"maxSize": 1048576
}
}
{
"scripts": {
"check": "biome check .",
"check:fix": "biome check --write .",
"lint": "biome lint .",
"lint:fix": "biome lint --write .",
"format": "biome format .",
"format:fix": "biome format --write .",
"ci": "biome ci ."
}
}
# Automatic migration — reads existing configs and generates biome.json
pnpm biome migrate eslint --write
pnpm biome migrate prettier --write
# Review the generated config
pnpm biome check --diagnostic-level=info .
Manual migration mapping for common ESLint rules:
| ESLint Rule | Biome Equivalent |
|-------------|-----------------|
| no-unused-vars | correctness/noUnusedVariables |
| no-console | suspicious/noConsoleLog |
| prefer-const | style/useConst |
| eqeqeq | suspicious/noDoubleEquals |
| no-debugger | suspicious/noDebugger |
| @typescript-eslint/no-explicit-any | suspicious/noExplicitAny |
| react-hooks/exhaustive-deps | correctness/useExhaustiveDependencies |
| import/order | organizeImports (built-in) |
| prettier/prettier | formatter (built-in) |
Post-migration cleanup:
# Remove old configs and dependencies
rm .eslintrc* .prettierrc* .eslintignore .prettierignore
pnpm remove eslint prettier eslint-config-prettier eslint-plugin-react \
eslint-plugin-react-hooks @typescript-eslint/parser \
@typescript-eslint/eslint-plugin eslint-plugin-import
# .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
with:
version: latest
- run: biome ci .
# Pre-commit hook (via lefthook or husky)
# .lefthook/pre-commit/biome.sh
#!/bin/sh
pnpm biome check --staged --no-errors-on-unmatched --files-ignore-unknown=true
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
},
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
"[json]": { "editor.defaultFormatter": "biomejs.biome" },
"[css]": { "editor.defaultFormatter": "biomejs.biome" }
}
biome ci in CI (exits non-zero on any issue, unlike biome check)vcs.useIgnoreFile to respect .gitignore automatically--staged flag in pre-commit hooks to only check staged filesfiles.maxSize to skip generated/minified filesrecommended: true and override specific rules as needed"level": "warn" during migration, tighten to "error" once cleanbiomejs/setup-biome@v2 for reproducibilitybiome explain <rule-name> to understand any diagnostic| Pitfall | Fix |
|---------|-----|
| Running biome check in CI instead of biome ci | biome ci is stricter — fails on warnings too. Always use ci in pipelines |
| Forgetting to remove ESLint/Prettier after migration | Delete old configs and uninstall packages to avoid confusion |
| Formatting conflicts with Tailwind class sorting | Enable nursery/useSortedClasses in Biome instead of prettier-plugin-tailwindcss |
| Ignoring files not working | Set vcs.enabled: true and vcs.useIgnoreFile: true to respect .gitignore |
| Rules not applying to JSX/TSX | Ensure javascript section is configured — JSX/TSX inherit from it |
| Large generated files causing slowdowns | Add patterns to files.ignore or set files.maxSize |
| Team members not using Biome formatter | Add .vscode/settings.json to repo and document setup |
// biome.json (root)
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"linter": {
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error"
}
}
},
"formatter": {
"indentStyle": "tab",
"lineWidth": 100
}
}
// apps/web/biome.json (extends root)
{
"extends": ["../../biome.json"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "error"
}
}
}
}
// Suppress a single rule for the next line
// biome-ignore lint/suspicious/noExplicitAny: legacy API requires any
const response: any = await legacyApi.fetch();
// Suppress formatting for a block
// biome-ignore format: matrix alignment is intentional
const matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
];
# Lint only TypeScript files
biome lint --include="**/*.ts" --include="**/*.tsx" .
# Format only JSON config files
biome format --write --include="**/*.json" .
# Check everything except test files
biome check --exclude="**/*.test.*" --exclude="**/*.spec.*" .
/plugin install biome-linter-formatter-setup@InugamiDevRequires Claude Code CLI.
Frontend teams migrate legacy linting/formatting to Biome for 20-100x faster performance and zero dependency overhead.
No reviews yet. Be the first to review this skill.
Lê Thành Danh
@InugamiDev