Linter
Biome’s linter statically analyzes your code to find and fix common errors and to help you write better, modern code. It supports multiple languages and provides a total of 311 rules.
You can quickly try the Biome linter via the CLI. The following command runs the linter on all files from the root of your project:
npx @biomejs/biome lint
yarn biome lint
pnpm biome lint
bunx biome lint
deno run -A npm:@biomejs/biome lint
Or you can specify one or multiple folders, for example ./src
and ./public
npx @biomejs/biome lint ./src ./public
yarn biome lint ./src ./public
pnpm biome lint ./src ./public
bunx biome lint ./src ./public
deno run -A npm:@biomejs/biome lint ./src ./public
The command accepts a list of files and directories.
For more information about all the available options, check the CLI reference.
Rules
Section titled RulesThe linter is organized into rules. A rule is meant to enforce or deny a code style, the use of something that could lead to a bug, and more. Generally, a rule shouldn’t conflict with another rule, unless told otherwise.
Biome rules have a naming convention: Rules that start with use*
are meant to enforce/suggest something, while rules that start with no*
are meant to deny something. When a rule encounters a violation of its concept, it emits a diagnostic.
For example, the noDebugger denies the use of debugger
statements in JavaScript code, and it emits a diagnostic when it finds one.
Biome linter ships with a set of recommended rules that varies based on languages, which are enabled by default when you avail of the default Biome configuration (or no-configuration) when you run the lint
or check
command:
biome lintbiome check
Each lint rule ships with a default severity which you can lean more about by reading the documentation of the rule.
The rules are divided into groups. For example, the noDebugger
rule is part of the suspicious
group.
Biome supports language-agnostic rules. Those are rules that work across more than one language, such as noUselessEscapeInString
, which can report useless escape sequences in both JavaScript and CSS.
Unlike other linters, Biome doesn’t provide any rules that check for code formatting; the Biome formatter is intended to handle all formatting decisions.
Many rules provide a code fix that can be automatically applied.
Biome makes a difference between safe fixes and unsafe fixes, which work slightly differently: The main difference is that safe fixes can be automatically applied when saving a file, while unsafe fixes can’t. Users can override which fixes are considered safe however.
Biome linter comes with a set of recommended rules that are automatically enabled, and vary based on the language.
Safe fixes
Section titled Safe fixesSafe fixes are guaranteed to not change the semantic of your code. They can be applied without explicit review.
To apply safe fixes from the CLI, use --write
:
npx @biomejs/biome lint --write ./src
yarn biome lint --write ./src
pnpm biome lint --write ./src
bunx biome lint --write ./src
deno run -A npm:@biomejs/biome lint --write ./src
From an LSP-compatible editor, you can apply safe fixes on save with the code action source.fixAll.biome
.
Refer to the documentation of your extension to learn how to apply it.
Unsafe fixes
Section titled Unsafe fixesUnsafe fixes may change the semantic of your program. Therefore, it’s advised to manually review the changes.
To apply both safe fixes and unsafe fixes from the CLI, use --write --unsafe
:
npx @biomejs/biome lint --write --unsafe ./src
yarn biome lint --write --unsafe ./src
pnpm biome lint --write --unsafe ./src
bunx biome lint --write --unsafe ./src
deno run -A npm:@biomejs/biome lint --write --unsafe ./src
From an LSP-compatible editor, it’s not possible to apply all unsafe fixes on save. It would be undesirable to change the semantics of your code on save. However, you can review the single code fix and choose to apply it.
Rule pillars
Section titled Rule pillarsIn Biome, rules should be informative and explain to the user why a rule is triggered and tell them what they should to do fix the error. A rule should follow these pillars:
- Explain to the user the error. Generally, this is the message of the diagnostic.
- Explain to the user why the error is triggered. Generally, this is implemented with an additional node.
- Tell the user what they should do. Generally, this is implemented using a code action. If a code action is not applicable a note should tell the user what they should do to fix the error.
If you think a rule doesn’t follow these pillars, please open an issue.
Configure the linter
Section titled Configure the linterIn many cases, you want to change the linter based on your personal needs, or the needs or your organisation/project. Biome allows you to customise the linter, and in this section you will learn how to do it.
Disable a rule
Section titled Disable a ruleYou can turn off a rule with off
.
The following configuration disables the recommended rule noDebugger
:
{ "linter": { "rules": { "suspicious": { "noDebugger": "off" } } }}
Disable recommended rules
Section titled Disable recommended rulesYou can disable the recommended rules with a simple configuration. This may be useful in cases when you only want to enable a few rules.
{ "linter": { "rules": { "recommended": false } }}
Rule severity
Section titled Rule severityBiome lint rules are shipped with their own default severity. If you want to avail of rule default severity, you can use the "on"
configuration.
For example the noShoutyConstants
isn’t recommended by default, and when it’s triggered in emits a diagnostic with information severity.
If you’re happy with this default and you want to avail of it, the configuration will look like this:
{ "linter": { "rules": { "style": { "noShoutyConstants": "on" } } }}
If you aren’t happy with the default severity, Biome allows you to change it with "error"
, "warn"
and "info"
Diagnostics with the "error"
always cause the CLI to exit with an error code. This severity can be useful when you want to block the CI if there’s a violation that belongs to a certain rule.
Warnings are similar to errors, but they don’t cause the CLI to exit with an error code, unless the --error-on-warnings
flag is used. A possible use for the warn
severity is when you want to make the CI pass while there are still diagnostics for a given rule.
The info
severity won’t affect the exit status code of the CLI, even when --error-on-warnings
is passed.
Group severity
Section titled Group severityAdditionally, you can control the severity of lint rules at the group level. This way, it’s possible to control the diagnostic severity of all rules that belong to a group.
For example, a project doesn’t require the use of a11y
rules because it’s code that runs at the backend, so accessibility isn’t a concern. The following example turns off all rules that belong to the a11y
group:
{ "linter": { "rules": { "a11y": "off" } }}
Configure the code fix
Section titled Configure the code fixAs explained above, rules might emit code fixes that are safe or unsafe. Biome allows configuring a safe fix to be treated as unsafe and vice-versa. You can also turn the code fix off entirely.
Code fixes can be configured using the fix
option. It can have one of three values:
none
: the rule won’t emit a code fix;safe
: the rule will emit a safe fix;unsafe
: the rule will emit an unsafe fix;
{ "linter": { "rules": { "correctness": { "noUnusedVariables": { "level": "error", "fix": "none" // no code fix suggested for noUnusedVariables } }, "style": { "useConst": { "level": "warn", "fix": "unsafe" // the code fix for `useConst` is now considered unsafe }, "useTemplate": { "level": "warn", "fix": "safe" // the code fix for `useTemplate` is now considered safe } } } }}
Skip a rule or a group
Section titled Skip a rule or a groupThe command biome lint
accepts an option --skip
that allows disabling individual rules or groups of rules.
For example, the following command skips all the rules that belong to the style
group and the suspicious/noExplicitAny
rule:
biome lint --skip=style --skip=suspicious/noExplicitAny
Run a rule or a group
Section titled Run a rule or a groupThe command biome lint
accepts an option --only
that allows running individual rules or groups of rules.
For example, the following command runs only the rule style/useNamingConvention
, the rule style/noInferrableTypes
and the rules that belong to a11y
. If the rule is disabled in the configuration, then its severity level is set to error
for a recommended rule or warn
otherwise.
biome lint --only=style/useNamingConvention --only=style/noInferrableTypes --only=a11y
Rule options
Section titled Rule optionsA few rules have options. You can set them by shaping the value of the rule differently.
level
will indicate the severity of the diagnostic;options
will change based on the rule.
{ "linter": { "rules": { "style": { "useNamingConvention": { "level": "error", "options": { "strictCase": false } } } } }}
Domains
Section titled DomainsDomains are a Biome feature that allow for grouping rules by technology, or well, domain. Examples of domains are "react"
, "solid"
, and "test"
.
A domain:
- Has its own set of recommended rules.
- Can be automatically enabled when Biome detects certain dependencies in your
package.json
file. - Can define additional global variables.
Biome’s linter will automatically enable the rules that belong to a domain when it detects certain dependencies in the nearest package.json
. For example, if the mocha
dependency is detected, Biome will enable the recommended rules of the test
domain.
However, if there’s no package.json
or the default configuration doesn’t apply, you can enable the domain via configuration:
{ "linter": { "domains": { "test": "recommended" } }}
Additionally, you can enable all rules that belong to a domain using the "all"
value:
{ "linter": { "domains": { "test": "all" } }}
Like rules and groups, you can also turn the rules that belong to a domains with the "off"
value:
{ "linter": { "domains": { "test": "off" } }}
To learn more about each domain, consult the appropriate page.
Suppress lint rules
Section titled Suppress lint rulesThere are times when a developer wants to suppress a lint rule for a specific line of the code, more lines of code, or the entire file.
Biome provide different ways suppress lint rule using specific comments called suppression comments.
Suppression comments have the following format:
// biome-ignore lint: <explanation>// biome-ignore lint/suspicious: <explanation>// biome-ignore lint/suspicious/noDebugger: <explanation>// biome-ignore lint/suspicious/noDebugger(foo): <explanation>// biome-ignore-all lint: <explanation>// biome-ignore-start lint: <explanation>// biome-ignore-end lint: <explanation>
Let’s break it down:
biome-ignore
,biome-ignore-all
,biome-ignore-start
andbiome-ignore-end
are the start of a suppression comment.lint
is the category of the suppression comment, and in this case it suppresses the linter./suspicious/noDebugger
or/suspicious
: optional, group and name, or group of the rule you want to suppress.(foo)
: optional, values associated to the suppression comment, these values are used by the specific rules. Refer to the documentation of the single rule to learn if they are used.<explanation>
explanation why the rule is disabled.
Inline suppressions
Section titled Inline suppressionsThey disable a lint rule for the next line of code.
In the following example, the suppression comment biome-ignore lint/suspicious/noDebugger: reason
will disable the debugger;
statement at line 2, but the debugger
at line 3 will still raise a diagnostic:
// biome-ignore lint/suspicious/noDebugger: reasondebugger;debugger;
Top-level suppressions
Section titled Top-level suppressionsThey disable a lint rule for an entire file. They must be placed at the top of the file, and they must start with biome-ignore-all
.
These suppression comments are very useful when you want to suppression some lint rule for a particular file, and you don’t want to rely to a single configuration override to achieve that.
The following example, the suppression comment biome-ignore-all lint/suspicious/noDebugger: reason
will disable the lint rule for the whole file generated.js
:
// biome-ignore-all lint/suspicious/noDebugger: reason
debuggerdebugger
When a top-level suppression comment isn’t at the top of the file, it is considered unused and Biome will emit a diagnostic with category suppression/unused
.
Range suppressions
Section titled Range suppressionsThey disable a lint rule from a particular line of code, to another line of code, called range.
To mark the beginning of a range suppression, the suppression comment must start with // biome-ignore-start
, and to mark the end of it, the suppression comment must start with // biome-ignore-end
.
The following example will disable the rule lint/suspicious/noDoubleEquals
for line 2 and 3, but the line 5 will raise a diagnostic:
// biome-ignore-start lint/suspicious/noDoubleEquals: reasona == b;c == d;// biome-ignore-end lint/suspicious/noDoubleEquals: reasonf == g;
The range suppression comments use a FILO queue (First in, Last out), which means that the first range suppression encountered by Biome will be the last one to be disabled.
The following example goes more in detail:
- The
debugger
statement at line 1 will raise a diagnostic because there’s no suppression comment that disables it. - The comment
// biome-ignore-start lint/suspicious/noDebugger: reason
at line 2 starts disablingnoDebugger
from line 3 onwards. - The comment
// biome-ignore-start lint/suspicious/noDoubleEquals: reason
at line 3 starts disablingnoDoubleEquals
from line 4 onwards. - The comment
// biome-ignore-end lint/suspicious/noDoubleEquals: reason
at line 7 terminates the suppression ofnoDoubleEquals
that was started by the suppression comment at line 3. - The
debugger
statement at line 8 doesn’t raise diagnostics due to the suppression comment at line 3. - The
f == g
statement raises a diagnostic because the rulenoDoubleEquals
isn’t suppressed anymore. - The rule
noDebugger
is disabled for the rest of the file because there isn’t a suppression commentbiome-ignore-end
that “closes” the suppression comment at line 2.
debugger;// biome-ignore-start lint/suspicious/noDebugger: reasondebugger// biome-ignore-start lint/suspicious/noDoubleEquals: reasona == b;c == d;// biome-ignore-end lint/suspicious/noDoubleEquals: reasondebuggerf == g;
Integration with editors
Section titled Integration with editorsThe first-class integration with LSP-compatible editors allows you to configure certain aspects of how Biome should behave.
When a violation is detected by Biome, a diagnostic is sent to the editor alongside with an arbitrary number of code actions, that are meant to address the diagnostic. Those actions are:
- A possible code fix. This code fix appears only if the rule has a code fix. The code fix appears regardless if it’s safe or unsafe.
- Suppress the diagnostic with an inline suppression.
- Suppress the diagnostic with a top-level suppression.
Usually, by positioning your cursor in the range of the diagnostic and typing a certain shortcut (it varies per editor), a tooltip will appear with the possible code actions.
By default, these actions are always displayed by the editor, however it’s possible to opt-out from them.
Quickfix
Section titled QuickfixUse quickfix.biome
to control whether the editor should show the code fix of any rule:
{ "code_actions_on_format": { "quickfix.biome": false, }}
{ "editor.codeActionsOnSave": { "quickfix.biome": "never", }}
quickfix.biome
Alternatively, it’s also possible turn off the code action for a specific rule. Each rule has a code action associated to it that follow the pattern quickfix.biome.<GROUP>.<NAME>
.
For example, if you want to turn off the code action of the rule noUnusedVariables
, you’ll use quickfix.biome.correctness.noUnusedVariables
:
Editor suppressions
Section titled Editor suppressions{ "code_actions_on_format": { "quickfix.biome.correctness.noUnusedVariables": false, }}
{ "editor.codeActionsOnSave": { "quickfix.biome.correctness.noUnusedVariables": "never", }}
quickfix.biome.correctness.noUnusedVariables
Use source.suppressRule.inline.biome
to control whether the editor should show the inline suppression code action:
{ "code_actions_on_format": { "source.suppressRule.inline.biome": false, }}
{ "editor.codeActionsOnSave": { "source.suppressRule.inline.biome": "never", }}
source.suppressRule.inline.biome
Use source.suppressRule.topLevel.biome
to control whether the editor should show the top-level suppression code action:
{ "code_actions_on_format": { "source.suppressRule.topLevel.biome": false, }}
{ "editor.codeActionsOnSave": { "source.suppressRule.topLevel.biome": "never", }}
source.suppressRule.topLevel.biome
Migrate from other linters
Section titled Migrate from other lintersMany of Biome lint rules are inspired from other linters.
If you want to migrate from other linters such as ESLint or typescript-eslint
, check the rules sources page.
If you are migrating from ESLint, there’s a dedicated migration guide.
- Use the command
biome migrate eslint
to port the rules defined in youreslint
configuration file tobiome.json
:Terminal window biome migrate eslint - Lint the project by suppressing possible new rules that are caught by Biome, using the following command:
The command will suppress all linting violation that Biome finds, using the reason
Terminal window biome lint --write --unsafe --suppress="suppressed due to migration""suppressed due to migration"
. Now the linter shouldn’t error anymore, and it’s possible to remove the suppression comments at a later stage.
Linter Groups
Section titled Linter GroupsThe linter divides rules under groups. Groups are meant to offer some sort of category which rules falls under. This information becomes useful, for users, when choosing a rule to enable/disable, or for developers when creating new lint rules.
Accessibility
Section titled AccessibilityRules focused on preventing accessibility problems.
Complexity
Section titled ComplexityRules that focus on inspecting complex code that could be simplified.
Correctness
Section titled CorrectnessRules that detect code that is guaranteed to be incorrect or useless.
Nursery
Section titled NurseryNew rules that are still under development. Nursery rules require explicit opt-in via configuration on stable versions because they may still have bugs or performance problems. They are enabled by default on nightly builds, but as they are unstable their diagnostic severity may be set to either error or warning, depending on whether we intend for the rule to be recommended or not when it eventually gets stabilized. Nursery rules get promoted to other groups once they become stable or may be removed. Rules that belong to this group are not subject to semantic version.
Performance
Section titled PerformanceRules catching ways your code could be written to run faster, or generally be more efficient.
Security
Section titled SecurityRules that detect potential security flaws.
Style
Section titled StyleRules enforcing a consistent and idiomatic way of writing your code. By default, these rules will only generate warnings instead of errors.
Suspicious
Section titled SuspiciousRules that detect code that is likely to be incorrect or useless.
Frequently Asked Questions (FAQ)
Section titled Frequently Asked Questions (FAQ)Why does rule X has an unsafe fix? It seems safe to me.
There are different reasons why the Biome team decides to mark a fix unsafe, but mostly it boils down to the following:
- The lint rule is still under heavy development, as well as the fix.
- The rule fix can change the semantics of a program, so the fix must be opted in by the user.
- The rule fix can deteriorate the DX while typing and/or saving. An example is
noUnusedVariables
, which adds_
to the name of unused variables. This can deteriorate the DX of programmers while typing and saving.
If a code fix doesn’t follow these three guidelines, it’s possible that the team forgot to make the rule fix safe. Please open an issue or send a PR!