| | |

Biome 12 🧹 VCS Integration — Respecting .gitignore and checking changed files

⏱️ Estimated read: 11 min | |

Biome’s VCS integration is the feature set that lets the toolchain read the version control system’s data instead of re-implementing it. It is opt-in by design. The vcs.enabled flag and the vcs.clientKind field are the two required pieces, and the documentation states plainly that this configuration “doesn’t do anything per se”—the developer must opt into the specific features . The two features that the integration provides are the ignore-file reading and the changed-file filtering. The first is the vcs.useIgnoreFile flag, and the second is the --changed, the --since, and the --staged CLI options.

The integration currently supports Git only, and the documentation is explicit about the limitation . The Git support reads the .gitignore files and the .git/info/exclude file, and in a linked worktree, it reads the .git/info/exclude from the common Git directory, matching Git’s own behavior . The integration is the mechanism that keeps Biome’s file set aligned with the version control’s file set, and the alignment is the reason a file that Git ignores does not get formatted or linted.

Key point: The VCS integration is opt-in. The vcs.enabled: true and the vcs.clientKind: "git" are the required fields, and the vcs.useIgnoreFile: true enables the ignore-file reading. The vcs.defaultBranch field sets the comparison branch for the --changed flag, and the --since flag overrides it. The --staged flag filters to the Git index, and it is not available on the ci command because the CI does not commit.


Why the VCS integration exists

The ignore-duplication problem. A project already has the .gitignore file, and the file lists the build output, the dependencies, and the generated files. Without the VCS integration, Biome would process the files that Git ignores, and the formatting or the linting would touch the build output that the developer never edits. The vcs.useIgnoreFile is the mechanism that makes Biome read the existing .gitignore instead of duplicating the patterns in the biome.json‘s files.includes . The duplication is the maintenance burden, and the integration is the mechanism that removes it.

The full-scan problem. A CI pipeline that runs Biome on the whole repository processes every file, even the files that the pull request did not touch. The scan is the slow path, and the time is the cost. The --changed flag is the mechanism that filters the files to the ones that differ from the vcs.defaultBranch, and the --since flag is the mechanism that compares against an arbitrary branch . The filter is the mechanism that keeps the CI fast, and the speed is the reason the flag exists.

The pre-commit problem. A pre-commit hook should check the files that are about to be committed, not the whole repository. The --staged flag is the mechanism that filters the files to the Git index, and the index is the set of files that the commit will include . The staged filter is the mechanism that makes the hook fast, and the hook is the reason the flag exists.

The changed-file limitation. The --changed flag does not check what actually changed in the code. Adding a space or a newline marks the file as changed, and the flag processes the file . The flag also does not check the downstream files that import from the changed file. If an exported type changes, the dependent files are not automatically checked, and a full lint may still be needed to catch the related errors . The limitation is the trade-off for the speed, and the developer must know when the full scan is necessary.

The CI-versus-local distinction. The --staged flag is not available on the ci command, because the CI environment is not expected to commit changes . The distinction is the mechanism that keeps the flags aligned with their use cases, and the alignment is the reason the ci command has the different surface.


a. The ignore-file reading and the configuration

The VCS configuration is the vcs object in the biome.json. The enabled and the clientKind are the required fields, and the useIgnoreFile is the flag that turns on the ignore reading.

// biome.json — the VCS configuration
{
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true,
    "defaultBranch": "main"
  }
}

The enabled: true and the clientKind: "git" are the two required fields. The useIgnoreFile: true enables the .gitignore reading, and the defaultBranch: "main" sets the comparison branch for the --changed flag . The configuration is the mechanism that connects Biome to the Git repository, and the connection is the reason the ignore file and the changed files work.

The useIgnoreFile reads the .gitignore files and the .git/info/exclude file. In a linked worktree, the .git/info/exclude is read from the common Git directory, which matches Git’s own behavior . The reading is the mechanism that keeps Biome’s file set aligned with Git’s, and the alignment is the reason the build output is not processed.

The biome migrate command is the mechanism that ports the v1 configuration to the v2 structure. The v1 configuration used the top-level files.ignore and the files.include fields, and the v2 uses the files.includes array with the ! exceptions. The VCS configuration is the separate concern, and the vcs.useIgnoreFile is the mechanism that keeps the .gitignore reading separate from the files.includes patterns .


b. The changed-file and the staged-file flags

The --changed flag filters the files to the ones that differ from the vcs.defaultBranch. The flag is the CLI-only feature, and the vcs.defaultBranch is the configuration that sets the comparison branch.

# The changed files against the default branch
biome check --changed

# The changed files against a specific branch
biome check --changed --since=next

The --since flag overrides the vcs.defaultBranch, and the override is the mechanism that lets the developer compare against an arbitrary branch . The biome check --changed --since=next is the command that compares against the next branch, and the comparison is the mechanism that filters the files.

The --staged flag filters the files to the Git index. The flag is the mechanism that makes the pre-commit hook fast, and the index is the set of files that the commit will include.

# The staged files only
biome check --staged

The --staged flag is not available on the ci command, because the CI does not commit . The distinction is the mechanism that keeps the flags aligned with their use cases, and the alignment is the reason the ci command has the different surface.

The --changed and the --staged flags can be combined with the --write flag. The --write applies the fixes, and the --staged filters the files. The combination is the mechanism that makes the pre-commit hook fix the staged files, and the hook is the reason the combination exists.


Complete Example Session

// ============================================
// PART 1: THE VCS CONFIGURATION
// ============================================

{
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true,
    "defaultBranch": "main"
  }
}

// The enabled and the clientKind are the required fields.
// The useIgnoreFile enables the .gitignore reading.
// The defaultBranch sets the comparison branch.

// ============================================
// PART 2: THE IGNORE FILE
// ============================================

// The .gitignore file
// node_modules
// dist
// coverage
// *.log

// The biome check ignores the listed files.
// The ignore reading is the mechanism that aligns Biome with Git.

// ============================================
// PART 3: THE CHANGED FILES
// ============================================

// biome check --changed

// The command processes only the files that differ from the main branch.
// The defaultBranch is the comparison point.

// ============================================
// PART 4: THE SINCE FLAG
// ============================================

// biome check --changed --since=next

// The command compares against the next branch.
// The --since flag overrides the vcs.defaultBranch.

// ============================================
// PART 5: THE STAGED FILES
// ============================================

// biome check --staged

// The command processes only the Git-indexed files.
// The pre-commit hook uses this.

// ============================================
// PART 6: THE STAGED WRITE
// ============================================

// biome check --staged --write

// The command fixes the staged files and applies the fixes.
// The fixes are added to the index.

// ============================================
// PART 7: THE CI COMMAND
// ============================================

// biome ci

// The ci command does not accept --staged.
// The CI does not commit, so the staged filter is not applicable.

// ============================================
// PART 8: THE CHANGED LIMITATION
// ============================================

// The --changed flag does not check what actually changed.
// Adding a space marks the file as changed.
// The downstream files are not automatically checked.
// A full lint may still be needed.

// ============================================
// PART 9: THE LINKED WORKTREE
// ============================================

// The .git/info/exclude is read from the common Git directory.
// The behavior matches Git's own behavior.

// ============================================
// PART 10: THE CHECKLIST
// ============================================

// [ ] The vcs.enabled is true.
// [ ] The vcs.clientKind is "git".
// [ ] The vcs.useIgnoreFile is true for the .gitignore reading.
// [ ] The vcs.defaultBranch is set for the --changed flag.
// [ ] The --since flag is used for the arbitrary branch.
// [ ] The --staged flag is used for the pre-commit hook.
// [ ] The --staged flag is not used on the ci command.

The ten parts covered the VCS configuration, the ignore file, the changed files, the --since flag, the staged files, the staged write, the CI command, the changed limitation, the linked worktree, and the checklist. The through-line is that the VCS integration is opt-in, and the flags are the mechanism that filters the files.


Quick Reference

The VCS configuration

FieldPurpose
vcs.enabledEnable the integration
vcs.clientKindThe VCS type, currently "git"
vcs.useIgnoreFileRead the .gitignore and the .git/info/exclude
vcs.defaultBranchThe comparison branch for the --changed flag

The CLI flags

FlagPurpose
--changedProcess the files changed from the defaultBranch
--since=<branch>Override the defaultBranch
--stagedProcess the Git-indexed files
--writeApply the fixes to the filtered files

The flag availability

Command--staged
checkYes
ciNo

The limitations

LimitationDetail
The changed detectionThe whitespace changes count as changed
The downstream filesThe dependent files are not automatically checked

Best Practices

✅ Do This:

// Enable the ignore-file reading
{ "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true } } // ✅
# Use the staged filter for the pre-commit hook
biome check --staged --write                                      // ✅

❌ Don’t Do This:

# Use the staged flag on the ci command
biome ci --staged // the flag is not available                    // ❌
// Assume the VCS configuration does anything without the flags
{ "vcs": { "enabled": true } } // no features are enabled         // ❌

Common Pitfalls

PitfallWhy It HappensFix
The .gitignore is not respectedThe vcs.useIgnoreFile is not setAdd the flag
The --changed flag does not filterThe vcs.defaultBranch is missingSet the field
The --staged flag is rejectedThe ci command is usedUse the check command
The downstream error is missedThe --changed does not check the dependentsRun a full lint

Real-World Examples

1. The VCS configuration

{ "vcs": { "enabled": true, "clientKind": "git" } }

2. The ignore-file reading

{ "vcs": { "useIgnoreFile": true } }

3. The default branch

{ "vcs": { "defaultBranch": "main" } }

4. The changed check

biome check --changed

5. The since flag

biome check --changed --since=next

6. The staged check

biome check --staged

7. The staged write

biome check --staged --write

8. The CI command

biome ci

9. The linked worktree

The .git/info/exclude is read from the common Git directory.

10. The downstream limitation

The --changed flag does not check the dependent files.

Visual

The VCS Integration Flow

┌──────────────────────────────────────────────────────────────┐
│  THE VCS INTEGRATION                                         │
│                                                              │
│  The biome.json                                              │
│  ┌─────────────────────┐                                    │
│  │ vcs.enabled         │  The required field                │
│  │ vcs.clientKind      │  "git"                             │
│  │ vcs.useIgnoreFile   │  The .gitignore reading            │
│  └──────────┬──────────┘                                    │
│             │                                                │
│             ▼                                                    │
│  ┌─────────────────────┐                                    │
│  │ The file set        │  The ignored files are excluded    │
│  │                     │  The changed files are filtered    │
│  └─────────────────────┘                                    │
└──────────────────────────────────────────────────────────────┘

The Changed and Staged Flags

┌──────────────────────────────────────────────────────────────┐
│  THE CHANGED AND STAGED FLAGS                                │
│                                                              │
│  --changed                                                   │
│  ┌─────────────────────┐                                    │
│  │ The files that      │  The comparison with the           │
│  │ differ from the     │  defaultBranch                     │
│  │ defaultBranch       │                                    │
│  └─────────────────────┘                                    │
│                                                              │
│  --staged                                                    │
│  ┌─────────────────────┐                                    │
│  │ The files in the    │  The pre-commit hook mechanism     │
│  │ Git index           │                                    │
│  └─────────────────────┘                                    │
└──────────────────────────────────────────────────────────────┘

The Ignore File

┌──────────────────────────────────────────────────────────────┐
│  THE IGNORE FILE READING                                     │
│                                                              │
│  The .gitignore                                              │
│  ┌─────────────────────┐                                    │
│  │ node_modules        │  The ignored files                 │
│  │ dist                │                                    │
│  │ coverage            │                                    │
│  └──────────┬──────────┘                                    │
│             │                                                │
│             ▼                                                    │
│  ┌─────────────────────┐                                    │
│  │ The biome check     │  The files are excluded            │
│  │ skips the files     │                                    │
│  └─────────────────────┘                                    │
└──────────────────────────────────────────────────────────────┘

Summary

ItemValue
The integrationThe opt-in Git support
The required fieldsvcs.enabled, vcs.clientKind
The ignore readingvcs.useIgnoreFile
The comparison branchvcs.defaultBranch
The changed flag--changed, with the --since override
The staged flag--staged, not available on ci
The limitationThe whitespace counts as changed, the dependents are not checked

Key takeaways:

  • The VCS integration is opt-in. The vcs.enabled and the vcs.clientKind are the required fields, and the configuration “doesn’t do anything per se” until the specific features are enabled .
  • The vcs.useIgnoreFile reads the .gitignore and the .git/info/exclude. The reading is the mechanism that keeps Biome’s file set aligned with Git’s, and the linked worktree reads the exclude from the common Git directory .
  • The --changed flag filters to the files that differ from the vcs.defaultBranch. The --since flag overrides the default branch, and the override is the mechanism that compares against an arbitrary branch .
  • The --staged flag filters to the Git index. The flag is the pre-commit hook mechanism, and it is not available on the ci command because the CI does not commit .
  • The --changed flag has the limitations. The whitespace changes count as changed, and the downstream files that import from the changed file are not automatically checked . The full lint is still needed for the dependent errors.

Remember: The Biome VCS integration is the opt-in Git support. The vcs.enabled and the vcs.clientKind are the required fields, and the vcs.useIgnoreFile is the ignore-file reading. The --changed and the --since flags filter the changed files, and the --staged flag filters the Git index. The integration is the mechanism that aligns Biome with the version control system, and the flags are the mechanism that keeps the CI and the pre-commit hook fast.

Was this helpful?


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!