---
title: Git Hooks
description: Using Biome in Git Hooks
---

Git allows executing scripts during the run of a git command using [Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks).
For example, you can format and lint the staged files before committing or pushing.
Several tools exist to simplify the management of Git Hooks.
In the following sections we introduce some of them and how they can be used with Biome.


## Lefthook

[Lefthook](https://github.com/evilmartians/lefthook) provides a fast, cross-platform, and dependency-free hook manager.
It can be [installed via NPM](https://github.com/evilmartians/lefthook#install).

Add a file named `lefthook.yml` at the root of your Git repository.
Some examples of _Lefthook_ configurations:

- Check formatting and lint before committing

  ```yaml title="lefthook.yml"
  pre-commit:
    commands:
      check:
        glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
        run: npx @biomejs/biome check --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
  ```

- Format, lint, and apply safe code fixes before committing

  ```yaml title="lefthook.yml"
  pre-commit:
    commands:
      check:
        glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
        run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
        stage_fixed: true
  ```

  `stage_fixed: true` adds again the staged files.

- Check formatting and lint before pushing

  ```yaml title="lefthook.yml"
  pre-push:
    commands:
      check:
        glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
        run: npx @biomejs/biome check --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {push_files}
  ```

Note that you don't need to use both `glob` and `--files-ignore-unknown=true`.
Using only `--files-ignore-unknown=true` allows handling files supported in the present and in the future by Biome.
If you wish more control over which files are handled, you should use `glob`.

`--no-errors-on-unmatched` silents possible errors in case *no files are processed*.

Once configured, run `lefthook install` to set up the hooks.


## Husky

[Husky](https://github.com/typicode/husky) is a widely-used hook manager in the JavaScript ecosystem.
Husky doesn't hide unstaged changes and is not able to provide the list of staged files.
This is why it is often used in tandem with another tool such as _lint-staged_ or _git-format-staged_.

If your project contains a `package.json`,
you can automatically set up _husky_ hooks upon package installation using `scripts.prepare`:

```json title="package.json"
{
  "scripts": {
    "prepare": "husky"
  }
}
```

### lint-staged

[lint-staged](https://github.com/lint-staged/lint-staged) is one of the most used tools in the JavaScript ecosystem.

Add the following husky configuration:

```shell title=".husky/pre-commit"
lint-staged
```

The configuration of lint-staged is directly embedded in `package.json`.
Here's some example of commands that you could find useful when running the Git hooks:

```jsonc title="package.json"
{
  "lint-staged": {
    // Run Biome on staged files that have the following extensions: js, ts, jsx, tsx, json and jsonc
    "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [
      "biome check --files-ignore-unknown=true", // Check formatting and lint
      "biome check --write --no-errors-on-unmatched", // Format, sort imports, lint, and apply safe fixes
      "biome check --write --organize-imports-enabled=false --no-errors-on-unmatched", // format and apply safe fixes
      "biome check --write --unsafe --no-errors-on-unmatched", // Format, sort imports, lints, apply safe/unsafe fixes
      "biome format --write --no-errors-on-unmatched", // Format
      "biome lint --write --no-errors-on-unmatched", // Lint and apply safe fixes
    ],
    // Alternatively you can pass every files and ignore unknown extensions
    "*": [
      "biome check --no-errors-on-unmatched --files-ignore-unknown=true", // Check formatting and lint
    ]
  }
}
```

Remember to use the CLI option `--no-errors-on-unmatched` in your command, to silent possible errors in case *no files are processed*.


### git-format-staged

In contrast to other tools such as _lefthook_, _pre-commit_, and _lint-staged_,
[git-format-staged](https://github.com/hallettj/git-format-staged) doesn't use `git stash` internally.
This avoids manual intervention when conflicts arise between unstaged changes and updated staged changes.
See the [comparison of _git-format-staged_ with other tools](https://github.com/hallettj/git-format-staged#comparisons-to-similar-utilities).

Some examples of configuration:

- Check formatting and lint before committing

  ```shell title=".husky/pre-commit"
  git-format-staged --formatter 'biome check --files-ignore-unknown=true --no-errors-on-unmatched \"{}\"' .
  ```

- Format, lint, and apply safe code fixes before committing

  ```shell title=".husky/pre-commit"
  git-format-staged --formatter 'biome check --write --files-ignore-unknown=true --no-errors-on-unmatched \"{}\"' .
  ```


## pre-commit

[pre-commit](https://pre-commit.com/) provides a multi-language hook manager.
Biome provides four [pre-commit](https://pre-commit.com/) hooks via the [biomejs/pre-commit](https://github.com/biomejs/pre-commit) repository.

| hook `id`       | description                                                                 |
| --------------- | --------------------------------------------------------------------------- |
| `biome-ci`      | Check formatting, check if imports are organized, and lints                 |
| `biome-check`   | Format, organize imports, lint, and apply safe fixes to the committed files |
| `biome-format`  | Format the committed files                                                  |
| `biome-lint`    | Lint and apply safe fixes to the committed files                            |

In the following example, we assume that you [installed pre-commit](https://pre-commit.com/index.html#install) and run `pre-commit install` in your repository.
if you want to use the `biome-check` hook, add the following pre-commit configuration to the root of your project in a file named `.pre-commit-config.yaml`:

```yaml title=".pre-commit-config.yaml"
repos:
-   repo: https://github.com/biomejs/pre-commit
    rev: "v2.0.6"  # Use the sha / tag you want to point at
    hooks:
    -   id: biome-check
        additional_dependencies: ["@biomejs/biome@2.1.1"]
```

This will run `biome check --write` when you run `git commit`.

Note that you must specify which version of Biome to use thanks to the `additional_dependencies` option.
[pre-commit](https://pre-commit.com/) separately installs tools and need to know which one to install.

If Biome is already installed as a `npm` package in your local repository,
then it can be a burden to update both `package.json` and `.pre-commit-config.yaml` when you update Biome.
Instead of using the provided Biome hooks, you can specify your own [local hook](https://pre-commit.com/index.html#repository-local-hooks).

For example, if you use `npm`, you can write the following hook in `.pre-commit-config.yaml`:

```yaml title=".pre-commit-config.yaml"
repos:
  - repo: local
    hooks:
      - id: local-biome-check
        name: biome check
        entry: npx @biomejs/biome check --write --files-ignore-unknown=true --no-errors-on-unmatched
        language: system
        types: [text]
        files: "\\.(jsx?|tsx?|c(js|ts)|m(js|ts)|d\\.(ts|cts|mts)|jsonc?)$"
```

The pre-commit option `files` is optional,
because Biome is able to ignore unknown files (using the option `--files-ignore-unknown=true`).


## Shell script

You can also use a custom shell script.
Note that you can encounter cross-platform incompatibilities.
We recommend the use of a dedicated tool as the one presented in the previous sections.

Some examples of shells scripts:

- Check formatting and lint before committing

  ```shell title=".git/hooks/pre-commit"
  #!/bin/sh
  set -eu

  npx @biomejs/biome check --staged --files-ignore-unknown=true --no-errors-on-unmatched
  ```

- Format, lint, and apply safe code fixes before committing

  ```shell title=".git/hooks/pre-commit"
  #!/bin/sh
  set -eu

  if git status --short | grep --quiet '^MM'; then
    printf '%s\n' "ERROR: Some staged files have unstaged changes" >&2
    exit 1;
  fi

  npx @biomejs/biome check --write --staged --files-ignore-unknown=true --no-errors-on-unmatched

  git update-index --again
  ```

  Note that we make the hook fail if staged files have unstaged changes.