Biome 07 🧹 Linting Rules — Rule groups and severity levels
Biome’s linter is organized around rules, and every rule belongs to a group. The group is the taxonomy—the category of the problem the rule detects—and the rule is the specific check. The noDebugger rule is in the suspicious group, because a stray debugger statement is likely an accident. The noUnusedVariables rule is in the correctness group, because an unused variable is a definite mistake . The grouping is the mechanism that lets a project enable or disable an entire category without enumerating every rule, and it is the first layer of the configuration.
The severity is the second layer. Every rule emits a diagnostic with one of three active levels—info, warn, or error—or it is turned off. The error severity causes the CLI to exit with a non-zero code, which is the mechanism that fails the CI pipeline. The warn and the info produce the diagnostics without failing the command, and the --error-on-warnings flag is the mechanism that promotes the warnings to the errors for a single invocation . The severity is the gate, and the group is the category.
Key point: The rules are grouped into correctness, suspicious, style, complexity, performance, security, a11y, and nursery. The severity levels are off, info, warn, and error. The error fails the CLI, the warn fails only with --error-on-warnings, and the info never fails the CLI. The recommended flag enables the curated set, and the "on" value enables a rule with its own default severity.
Why the groups and the severities are separate
The group problem. A backend project has no use for the a11y rules, because accessibility is a browser concern. The "a11y": "off" is the mechanism that disables the whole group without listing the individual rules . The group is the coarse control, and the rule is the fine control. A project that is migrating from ESLint can map the ESLint plugin categories to the Biome groups, and the mapping is the mechanism that makes the migration tractable.
The severity problem. A project that adopts Biome on an existing codebase has hundreds of violations, and the CI would fail on all of them. The warn severity is the mechanism that reports the violations without failing the CI, and the --error-on-warnings flag is the mechanism that promotes the warnings to the errors when the project is ready to enforce them . The severity is the ratchet, and the ratchet is the migration mechanism. The info severity is the third level, and it is the mechanism for the diagnostics that are informational and should never fail the pipeline.
The default severity problem. A rule has its own default severity, and the "on" value enables the rule with that default. The noShoutyConstants rule is not recommended by default, and when it is triggered it emits the info severity. The "on" is the mechanism that keeps the default, and the "error" is the mechanism that overrides it . The distinction matters because a project that sets every rule to "on" and expects the CI to fail will be surprised by the rules that default to info.
The recommended problem. The recommended flag enables the curated set of rules, and the recommended rules emit the error severity by default . The flag is the mechanism that turns on the curated baseline, and the "recommended": false is the mechanism that turns it off for a project that wants only the few rules it explicitly lists. The recommended set is the starting point, and the explicit rules are the refinement.
The override problem. The rule configuration is per-rule, and the file-specific configuration is the override. The javascript.linter.rules is not a valid key, and the overrides array with the file globs is the mechanism for the language-specific rules . The override merges with the top-level config, and the merge is the mechanism that keeps the configuration maintainable. A project that wants the test files to have the different rules uses the overrides array rather than duplicating the whole config.
a. The rule groups and the configuration shape
The linter.rules object contains the groups, and each group contains the rules. The group can be configured as a whole with a severity string, or as an object with the individual rules.
// biome.json — the group-level configuration
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noDebugger": "error",
"noExplicitAny": "warn"
},
"a11y": "off"
}
}
}
The suspicious group is configured as an object with the two rules. The a11y group is configured as the "off" string, which disables the whole group . The two forms are the same mechanism, and the group-level string is the shorthand for the whole group. The group-level string is the mechanism that lets a backend project disable the a11y group in one line.
The recommended flag is the top-level switch. The true is the default, and the recommended rules are enabled. The false is the mechanism that disables the whole recommended set, which is useful when the project wants only the few rules it explicitly lists.
// biome.json — the rule with the options
{
"linter": {
"rules": {
"style": {
"useNamingConvention": {
"level": "error",
"options": { "strictCase": false }
}
}
}
}
}
The rule with the options is the object form. The level is the severity, and the options is the rule-specific configuration . The useNamingConvention is the example, and the strictCase is the option that the rule accepts. The object form is the mechanism that configures the rule beyond the severity.
The fix option is the third field. The "none" disables the code fix, the "safe" keeps the safe fix, and the "unsafe" keeps the unsafe fix . The option is the mechanism that controls the autofix behavior for the specific rule.
// biome.json — the rule with the fix option
{
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": {
"level": "error",
"fix": "none"
}
}
}
}
}
The noUnusedVariables with the fix: "none" is the rule that reports the unused variables but does not apply the automatic removal. The fix is the mechanism that removes the variable, and the none is the mechanism that keeps the manual review.
b. The severity ratchet and the CLI flags
The severity ratchet is the migration pattern. The recommended rules with no violations keep the error severity. The rules with the existing violations are pinned to the warn, so the CI stays green while the violations are burned down. The --error-on-warnings is the flag that promotes the warnings to the errors for the CI run that wants to enforce the ratchet .
// biome.json — the ratchet configuration
{
"linter": {
"rules": {
"recommended": true,
"correctness": {
"useExhaustiveDependencies": "warn",
"noUnusedImports": "warn"
}
}
}
}
The useExhaustiveDependencies and the noUnusedImports are pinned to the warn. The biome ci does not fail on the warnings, and the CI stays green while the violations are fixed . The --error-on-warnings is the mechanism that turns the warnings into the errors once the violations reach zero.
The --only and the --skip flags are the CLI overrides. The --only runs the specific rule or the group, and the --skip disables the specific rule or the group for the single invocation .
# The --only flag runs the specific rule
biome lint --only=style/useNamingConvention ./src
# The --skip flag disables the group
biome lint --skip=style ./src
The --only and the --skip are the mechanism that overrides the configuration for the single command. The --only is the mechanism for the targeted check, and the --skip is the mechanism for the temporary exclusion. A developer who is debugging a specific rule uses the --only to run just that rule, and a developer who is refactoring a specific area uses the --skip to disable the group for the duration.
The overrides array is the file-specific configuration. The javascript.linter.rules is not a valid key, and the overrides with the file globs is the mechanism for the language-specific rules .
// biome.json — the overrides array
{
"linter": {
"rules": {
"recommended": true,
"nursery": "on"
}
},
"overrides": [
{
"includes": ["**/*.ts", "**/*.tsx"],
"linter": {
"rules": {
"nursery": {
"useConsistentTypeDefinitions": {
"level": "on",
"options": { "style": "type" }
}
}
}
}
}
]
}
The top-level nursery: "on" enables all the nursery rules. The override enables the useConsistentTypeDefinitions with the options for the TypeScript files. The override merges with the top-level config, and the merge is the mechanism that keeps the configuration maintainable .
Complete Example Session
// ============================================
// PART 1: THE GROUP-LEVEL CONFIGURATION
// ============================================
{
"linter": {
"rules": {
"recommended": true,
"suspicious": {
"noDebugger": "error"
},
"a11y": "off"
}
}
}
// The suspicious group has the noDebugger at the error.
// The a11y group is disabled.
// ============================================
// PART 2: THE RULE WITH THE OPTIONS
// ============================================
{
"linter": {
"rules": {
"style": {
"useNamingConvention": {
"level": "error",
"options": { "strictCase": false }
}
}
}
}
}
// The rule has the level and the options.
// ============================================
// PART 3: THE FIX OPTION
// ============================================
{
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": {
"level": "error",
"fix": "none"
}
}
}
}
}
// The rule reports but does not fix.
// ============================================
// PART 4: THE RATCHET
// ============================================
{
"linter": {
"rules": {
"recommended": true,
"correctness": {
"useExhaustiveDependencies": "warn"
}
}
}
}
// The rule is pinned to the warn during the migration.
// ============================================
// PART 5: THE --ERROR-ON-WARNINGS
// ============================================
// biome ci --error-on-warnings ./src
// The flag promotes the warnings to the errors.
// The CI fails if any warning is present.
// ============================================
// PART 6: THE --ONLY FLAG
// ============================================
// biome lint --only=style/useNamingConvention ./src
// The command runs only the specified rule.
// ============================================
// PART 7: THE --SKIP FLAG
// ============================================
// biome lint --skip=style ./src
// The command skips the whole style group.
// ============================================
// PART 8: THE OVERRIDES ARRAY
// ============================================
{
"linter": {
"rules": { "recommended": true }
},
"overrides": [
{
"includes": ["**/*.test.ts"],
"linter": {
"rules": {
"suspicious": { "noExplicitAny": "off" }
}
}
}
]
}
// The test files have the noExplicitAny disabled.
// The override merges with the top-level config.
// ============================================
// PART 9: THE DOMAIN
// ============================================
{
"linter": {
"domains": {
"react": "recommended"
}
}
}
// The react domain is enabled.
// The domain is the grouping by the technology.
// ============================================
// PART 10: THE CHECKLIST
// ============================================
// [ ] The recommended rules are enabled.
// [ ] The groups are configured with the severity strings.
// [ ] The rules with the options use the object form.
// [ ] The fix option is set for the rules that need it.
// [ ] The ratchet uses the warn severity during the migration.
// [ ] The --error-on-warnings is used in the CI.
// [ ] The overrides array is used for the file-specific rules.
The ten parts covered the group-level configuration, the rule with the options, the fix option, the ratchet, the --error-on-warnings, the --only flag, the --skip flag, the overrides array, the domain, and the checklist. The through-line is that the group is the coarse control, the rule is the fine control, and the severity is the gate.
Quick Reference
The rule groups
| Group | Purpose |
|---|---|
correctness | The code that is definitely wrong |
suspicious | The code that is likely wrong |
style | The consistent code style |
complexity | The code that is too complex |
performance | The code that is slow |
security | The code that is vulnerable |
a11y | The accessibility rules |
nursery | The new rules that are not yet stable |
The severity levels
| Severity | CLI exit | Purpose |
|---|---|---|
off | No | The rule is disabled |
info | No | The informational diagnostic, never fails |
warn | No (unless --error-on-warnings) | The warning, CI stays green |
error | Yes | The error, CI fails |
The rule configuration shapes
| Shape | Example | Purpose |
|---|---|---|
| The string | "noDebugger": "error" | The severity only |
| The object | "useNamingConvention": { "level": "error", "options": {} } | The severity and the options |
| The group string | "a11y": "off" | The whole group disabled |
The CLI flags
| Flag | Purpose |
|---|---|
--error-on-warnings | Promotes the warnings to the errors |
--only=<rule> | Runs only the specified rule or group |
--skip=<rule> | Skips the specified rule or group |
--write | Applies the safe fixes |
--write --unsafe | Applies the safe and unsafe fixes |
Best Practices
✅ Do This:
// Use the group-level string for the whole group
{ "a11y": "off" } // ✅
// Use the object form for the rule with the options
{ "useNamingConvention": { "level": "error", "options": {} } } // ✅
// Use the warn severity for the ratchet
{ "useExhaustiveDependencies": "warn" } // ✅
❌ Don’t Do This:
// Use the javascript.linter.rules key
{ "javascript": { "linter": { "rules": {} } } } // the invalid key // ❌
// Assume the "on" is the error severity
{ "noShoutyConstants": "on" } // the default is the info // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The group is disabled but the rule is not | The rule is in the overrides | Check the overrides array |
The "on" does not fail the CI | The default severity is info | Use the "error" explicitly |
| The language-specific rule is ignored | The javascript.linter.rules is invalid | Use the overrides array |
| The ratchet never completes | The warn is never promoted | Use the --error-on-warnings |
Real-World Examples
1. The group-level configuration
{ "linter": { "rules": { "a11y": "off" } } }
2. The rule with the severity
{ "linter": { "rules": { "suspicious": { "noDebugger": "error" } } } }
3. The rule with the options
{ "linter": { "rules": { "style": { "useNamingConvention": { "level": "error", "options": {} } } } } }
4. The fix option
{ "linter": { "rules": { "correctness": { "noUnusedVariables": { "level": "error", "fix": "none" } } } } }
5. The ratchet
{ "linter": { "rules": { "correctness": { "useExhaustiveDependencies": "warn" } } } }
6. The –error-on-warnings
biome ci --error-on-warnings ./src
7. The –only flag
biome lint --only=style/useNamingConvention ./src
8. The –skip flag
biome lint --skip=style ./src
9. The overrides array
{ "overrides": [{ "includes": ["**/*.test.ts"], "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } } }] }
10. The domain
{ "linter": { "domains": { "react": "recommended" } } }
Visual
The Group and the Rule
┌──────────────────────────────────────────────────────────────┐
│ THE GROUP IS THE COARSE CONTROL │
│ │
│ suspicious │
│ ┌─────────────────────┐ │
│ │ noDebugger: error │ The rule │
│ │ noExplicitAny: warn │ The rule │
│ └─────────────────────┘ │
│ │
│ a11y: "off" │
│ ┌─────────────────────┐ │
│ │ The whole group is │ The group-level string │
│ │ disabled │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The Severity Ladder
┌──────────────────────────────────────────────────────────────┐
│ THE SEVERITY LEVELS │
│ │
│ error │
│ ┌─────────────────────┐ │
│ │ The CLI exits 1 │ The CI fails │
│ └─────────────────────┘ │
│ │
│ warn │
│ ┌─────────────────────┐ │
│ │ The CLI exits 0 │ The CI passes │
│ │ unless --error-on- │ │
│ │ warnings │ │
│ └─────────────────────┘ │
│ │
│ info │
│ ┌─────────────────────┐ │
│ │ The CLI exits 0 │ Even with --error-on-warnings │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The Override
┌──────────────────────────────────────────────────────────────┐
│ THE OVERRIDE MERGES WITH THE TOP-LEVEL │
│ │
│ linter.rules │
│ ┌─────────────────────┐ │
│ │ recommended: true │ The baseline │
│ │ nursery: "on" │ All the nursery rules │
│ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ overrides │
│ ┌─────────────────────┐ │
│ │ includes: *.ts │ The TypeScript files │
│ │ useConsistentType- │ The specific rule with the │
│ │ Definitions │ options │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| The rule groups | correctness, suspicious, style, complexity, performance, security, a11y, nursery |
| The severity levels | off, info, warn, error |
| The recommended | The recommended: true enables the curated set |
The "on" | Enables the rule with its default severity |
| The ratchet | The warn during the migration, the error after |
The --error-on-warnings | Promotes the warnings to the errors |
| The overrides | The file-specific rule configuration |
Key takeaways:
- The rules are grouped by the kind of problem they detect. The
correctnessgroup is the definitely-wrong code, thesuspiciousgroup is the likely-wrong code, and thea11ygroup is the accessibility. The group is the coarse control, and the rule is the fine control . - The severity is the gate. The
errorfails the CLI, thewarnfails only with--error-on-warnings, and theinfonever fails the CLI . The--error-on-warningsis the flag that promotes the warnings to the errors for the CI run. - The
"on"keeps the rule’s default severity. A rule that defaults to theinfodoes not fail the CI when it is set to the"on". The"error"is the explicit override . - The overrides array is the file-specific configuration. The
javascript.linter.rulesis not a valid key, and theoverrideswith the file globs is the mechanism for the language-specific rules . - The ratchet is the migration pattern. The rules with the violations are pinned to the
warn, and the CI stays green while the violations are fixed. The--error-on-warningsis the mechanism that promotes the warnings once the violations reach zero .
Remember: The Biome linter is the rules, the groups, and the severities. The group is the coarse control, the rule is the fine control, and the severity is the gate. The recommended enables the curated set, the "on" keeps the default severity, and the "error" fails the CI. The overrides array is the file-specific configuration, and the ratchet is the migration pattern.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!