How Biome works
This is a guide that explains how the tool works, assumptions, and internal information useful when setting up the project and the configuration file.
Configuration
Section titled ConfigurationThe configuration file is considered optional, Biome has good defaults. Use the configuration file to change those defaults.
The Biome configuration file is named biome.json
and should be placed in the root directory of your project. The root
directory is usually the directory containing your project’s package.json
.
Since version 1.6.0
, Biome accepts also the file biome.jsonc
.
This configuration file enables the formatter and sets the preferred indent style and width. The linter is disabled:
{ "formatter": { "enabled": true, "indentStyle": "tab", "lineWidth": 120 }, "linter": { "enabled": false }}
Default configuration
Section titled Default configurationWhen you run biome init
, the default configuration emitted is the following:
{ "organizeImports": { "enabled": true }, "linter": { "enabled": true, "rules": { "recommended": true } }}
Configuration file resolution
Section titled Configuration file resolutionBiome uses auto discovery to find the nearest biome.json
file. It starts looking for biome.json
in the current
working directory, and then it starts looking in the parent directories until:
- it finds a
biome.json
file; - it applies Biome’s defaults if no
biome.json
is found;
Here’s an example:
└── app ├── backend │ ├── package.json │ └── biome.json └── frontend ├── legacy │ └── package.json ├── new │ └── package.json └── biome.json
- biome commands that run in
app/backend/package.json
will use the configuration fileapp/backend/biome.json
; - biome commands that run in
app/frontend/legacy/package.json
andapp/frontend/new/package.json
will use the configuration fileapp/frontend/biome.json
;
The extends
option
Section titled The extends optionThe extends
option allows to break down a configuration in multiple file and “share” common patterns among multiple projects/folders.
{ "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", "extends": ["./formatter.json", "./linter.json"]}
{ "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", "formatter": { "indentSize": 2 }, "javascript": { "formatter": { "semicolons": "asNeeded" } }}
{ "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", "linter": { "rules": { "complexity": { "noUselessConstructor": "off" } } }}
The files defined in this array:
- must exist in the file system;
- are resolved from the path where the
biome.json
file is defined; - must be relative paths. Paths to libraries are not resolved;
- must be reachable by Biome, e.g. symbolic links might not be resolved by Biome;
- will be processed in order: from the first one to the last one;
- can override the same properties, but ultimately only the last one will be used by Biome;
Import biome.json
from a library
Section titled Import biome.json from a libraryFrom version v1.6.0
, Biome is able to resolve configuration files from node_modules/
, so you can export your configuration file from a library, and import it in multiple projects.
In order to do so, the first thing to do is to set up your “shared” Biome configuration in a certain way. Let’s suppose that your library is called @org/shared-configs
, and you want to import the Biome configuration using the specifier @org/shared-configs/biome
. You have to set up the package.json
is a specific way:
{ "name": "@org/shared-configs", "exports": { "./biome": "./biome.json" }}
Make sure that @org/shared-configs
is correctly installed in your project, and update the biome.json
file to look like the following snippet:
{ "extends": ["@org/shared-configs/biome"]}
Biome will attempt to resolve your library @org/shared-configs/
from your working directory. The working directory is:
- when using the CLI, the directory where you execute your scripts from. Usually it matches the location of your
package.json
file; - when using the LSP, the root directory of your project.
For more information about the resolution algorithm, read the Node.js documentation.
Protected Files
Section titled Protected FilesThe following files are currently ignored by Biome. This means that no diagnostics will be ever emitted by Biome for those files.
composer.lock
npm-shrinkwrap.json
package-lock.json
yarn.lock
The following files are parsed as JSON
files with the options json.parser.allowComments
and json.parser.allowTrailingCommas
set to true
. This is because editor tools like VSCode treat them like this.
.babelrc.json
.babelrc
.ember-cli
.eslintrc.json
.eslintrc
.hintrc
.jsfmtrc
.jshintrc
.swcrc
babel.config.json
jsconfig.json
tsconfig.json
tslint.json
typedoc.json
typescript.json
include
and ignore
explained
Section titled include and ignore explainedBiome will resolve the globs specified in include
and ignore
relatively from the working directory.
The working directory is the directory where you usually run a CLI command. This means that you have to place particular attention when the configuration file is placed in a different directory from where you execute your command.
For example, you have a project that contains two directories called backend/
and frontend/
,
and decide to place your biome.json
at the root folder of the project.
Inside the frontend/
project, you have your package.json
with some scripts that run Biome:
├── backend├── biome.json└── frontend └── package.json
{ "files": { "include": ["src/**/*.js", "src/**/*.ts"] }, "formatter": { "indentStyle": "space" }}
{ "name": "frontend-project", "scripts": { "format": "biome format --write ./" }}
When you run the script format
inside frontend/package.json
,
the working directory resolved by that script will be frontend/
,
the globs src/**/*.js
and src/**/*.ts
will have as “base” directory frontend/
.
Glob syntax explained
Section titled Glob syntax explainedThe syntax and meaning of these two options loosely follow the globset rules but without the ability to set options.
*
matches zero or more characters.
**
recursively matches directories but are only legal in three situations. First, if the glob starts with**/
, then it matches all directories. For example,**/foo
matchesfoo
andbar/foo
but notfoo/bar
. Secondly, if the glob ends with/**
, then it matches all sub-entries. For example,foo/**
matchesfoo/a
andfoo/a/b
, but notfoo
. Thirdly, if the glob contains/**/
anywhere within the pattern, then it matches zero or more directories. Using**
anywhere else is illegal (N.B. the glob**
is allowed and means “match everything”).Metacharacters such as
*
and?
can be escaped with character class notation. e.g.,[*]
matches*
.
Check the wikipedia page for more information.