Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/content/docs/guides/big-projects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,61 @@ case, we suggest ignoring the nested project entirely using
[the `files.includes` field](/reference/configuration/#filesincludes).
:::

### Globs resolution

The resolution of globs defined in the `*.includes` fields doesn't change when a nested configuration file extends the root.

For example, the following project is placed in the folder `/Users/todo`, and contains a root configuration in `/Users/todo/biome.json`, and one
inside `/Users/todo/app/biome.json`.

- Globs defined in `/Users/todo/biome.json` are resolved from `/Users/todo/`.
- Globs defined in `/Users/todo/app/biome.json` are resolved from `/Users/todo/app`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think part of the confusion may arise from this kind of description. From my perspective, these two points contradict the actual behavior, because the root glob is evaled from the config file it was defined in only if no other config file inherits from it. If a package config file inherits from the root, then globs are not evaled from the file they are defined in but rather the file that inherits them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's confusing if the docs and the behaviour are contradicting one another. But I do think the behaviour as described here sounds the most sensible, so I would consider the actual behaviour to be a bug then.


The root configuration excludes `app/generate.ts`, and the nested configuration extends the root, as follow:

<FileTree>
- app
- biome.json
- generated.ts
- package.json
- biome.json
- package.json
</FileTree>

```json title="/Users/todo/biome.json"
{
"files": {
"includes": [
"**",
"!app/generated.ts"
]
}
}
```

```json title="/Users/todo/app/biome.json"
{
"extends": "//"
}
```

**This setting won't exclude `app/generated.ts` if/when you decide to run a command from `/Users/todo/app`**. That's because when Biome resolves globs from `app/biome.json`,
the extended glob `!app/generated.ts` is resolved like this: `/Users/todo/app ~ !app/generatd.ts`, which doesn't match any existing folder inside the project.

To properly exclude `app/generated.ts`, you have two options:
- Prepend the glob with `**`, so that any folder is matched:
Copy link

@brandonw brandonw Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right-- prepending ** doesn't help because the /app/ part will still not match anything because are are executing from the app directory.

You would need to remove the package path from the root config so that it sees the package relative path correctly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. The objective is to exclude app/generated.ts, not generated.ts.

What am I missing? Please provide an example so I can understand

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have the paths:

biome.json
app/generated.ts
app/biome.json

and app/biome.json extends from biome.json, then including !**/app/generated.ts in the root means it is ingested into the app config as-is. That means from the app conffig, the glob resolves as !**/app/generated.ts. The glob prefix checks the current dir and any subdirs for app/ and finds nothing, because the app dir is what has already been traversed in the transform from root->app config. It doesn't do anything because you aren't adding an unknown prefix in the transition from root->app. You are removing a known prefix.

Prefixing a ** to the glob only helps if there are no intermediate directories between the root and the package configs. If there are, then they likely interfere and render the glob useless.

Let me know if I am making any sense 🤞

```json title="/Users/todo/biome.json" ins="!**" ins={5}
{
"files": {
"includes": [
"**",
"!**/app/generated.ts"
]
}
}
```
- Move the `!app/generated.ts` glob inside `/Users/todo/app/biome.json`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this done? Is there a way to manipulate the global files.includes from configs that inherit the root? The json schema nor the config file reference doesn't seem to think so.

It may be worth clarifying what exactly you can do if you want to move the path into the package config. I think something like:

      "formatter": {
        "enabled": false
      },
      "linter": {
        "enabled": false
      },
      "assist": {
        "enabled": false
      }

in an exclude, but I am not 100% on that.


## Other ways to share a configuration file

As we saw above, the `extends` field allows you to split your configuration
Expand Down
10 changes: 10 additions & 0 deletions src/content/docs/reference/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ This is required so Biome can orchestrate multiple files in CLI and editors at t

A list of [glob patterns](#glob-syntax-reference) of files to process.

All globs are resolved from the configuration file where they are defined.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ematipico this seems opposite of the above-- they are not resolved from the config file they are defined, but rather from the "leaf" or "package" config file, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. What about "configuration where they are loaded from"?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that sounds better 👍


If a folder matches a glob pattern, all files inside that folder will be
processed.

Expand Down Expand Up @@ -245,6 +247,8 @@ Enables Biome's linter.

A list of [glob patterns](#glob-syntax-reference) of files to lint.

All globs are resolved from the configuration file where they are defined.

The following example lints all files with a `.js` extension inside the `src`
folder:

Expand Down Expand Up @@ -392,6 +396,8 @@ Enables Biome's assist.

A list of [glob patterns](#glob-syntax-reference) of files to lint.

All globs are resolved from the configuration file where they are defined.

The following example analyzes all files with a `.js` extension inside the `src`
folder:

Expand Down Expand Up @@ -504,6 +510,8 @@ Enables Biome's formatter.

A list of [glob patterns](#glob-syntax-reference) of files to format.

All globs are resolved from the configuration file where they are defined.

The following example formats all files with a `.js` extension inside the `src`
folder:

Expand Down Expand Up @@ -1483,6 +1491,8 @@ The order of the patterns matter. If a file *can* match three patterns, only the
A list of [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)) of
files for which to apply customised settings.

All globs are resolved from the configuration file where they are defined.

```jsonc title="biome.jsonc"
{
"overrides": [{
Expand Down