# prek
> A fast Git hook manager written in Rust, designed as a drop-in alternative to pre-commit, reimagined.
## Introduction
# prek
prek is a framework for running hooks on your code. It runs them before you commit changes, on demand, or in CI. These hooks can format files, catch lint errors, detect secrets, or run any other command your project defines. prek also installs and manages the tools and dependencies they need.
You may already be familiar with the [pre-commit](https://pre-commit.com/) tool. prek is a reimagined version of it, built in Rust. It is faster and distributed as a single binary with no runtime dependencies. It is fully compatible with pre-commit configurations and hooks, so you can use it as a drop-in replacement without changing your setup.
Note
Although prek is pretty new, it's already powering real‑world projects like [CPython](https://github.com/python/cpython), [Apache Airflow](https://github.com/apache/airflow), [FastAPI](https://github.com/fastapi/fastapi), and more projects are picking it up—see [Who is using prek?](#who-is-using-prek). If you're looking for an alternative to `pre-commit`, please give it a try—we'd love your feedback!
## Features
- A single binary with no dependencies, does not require Python or any other runtime.
- [Faster](https://prek.j178.dev/benchmark/) than `pre-commit` and more efficient in disk space usage.
- Fully compatible with the original pre-commit configurations and hooks.
- Built-in support for monorepos (i.e. [workspace mode](https://prek.j178.dev/monorepos/)), including concurrent execution for independent same-depth projects.
- Integration with [`uv`](https://github.com/astral-sh/uv) for managing Python virtual environments and dependencies.
- Improved toolchain installations for Python, Node.js, Bun, Go, Rust and Ruby, shared between hooks.
- [Built-in](https://prek.j178.dev/built-in-hooks/) Rust-native implementation of some common hooks.
## Where to Start
- New to `prek`: start with [Installation](installation/), then follow the [Quickstart](quickstart/).
- Already set up: use [Running Hooks](running-hooks/) for day-to-day commands and handling hook failures.
- Replacing another hook tool: follow [Migrating from Other Hook Tools](migration/).
- Writing config: read [Configuration](configuration/), then use the [Configuration Reference](reference/configuration/) for exact keys.
- Defining hooks directly in your project configuration: use [Local Hooks](local-hooks/).
- Adding repository checks to a pipeline: see [Continuous Integration](ci/).
- Looking for setup patterns: browse the [Cookbook](cookbook/).
- Working in a monorepo: see [Monorepos](monorepos/).
- Looking for flags or environment variables: use the [CLI Reference](reference/cli/) and [Environment Variable Reference](reference/environment-variables/).
- Reviewing trust and pinning choices: read the [Security Guide](security/).
## Why prek?
### prek is faster
- It is [multiple times faster](https://prek.j178.dev/benchmark/) than `pre-commit` while also using less disk space.
- Hook environments and toolchains are shared across hooks instead of being duplicated per repository, which reduces both install time and cache size.
- Repository fetches and independent hook environment setup run in parallel, hooks can run concurrently by [`priority`](https://prek.j178.dev/reference/configuration/#priority) using reusable [aliases](https://prek.j178.dev/reference/configuration/#priorities), and independent workspace projects at the same directory depth can run concurrently.
- It uses [`uv`](https://github.com/astral-sh/uv) for creating Python virtualenvs and installing dependencies, which is known for its speed and efficiency.
- For supported hooks from `pre-commit-hooks`, the [automatic fast path](https://prek.j178.dev/built-in-hooks/#use-the-automatic-fast-path) runs built-in Rust implementations without requiring any configuration changes.
- The prek-only `repo: builtin` mode provides offline, zero-setup hooks, including native `deny-pattern` and `require-pattern` alternatives for common `pygrep` checks.
### prek is easier to work with
- No need to install Python or any other runtime just to use `prek`; it is a single binary.
- Its [language support](https://prek.j178.dev/reference/language-support/) covers every language available in `pre-commit`, plus Bun, Deno, mise, and PHP, and it automatically installs managed toolchains when needed for Python, Node.js, Bun, Deno, Go, mise, Rust, and Ruby.
- It supports native [`prek.toml`](https://prek.j178.dev/configuration/) in addition to pre-commit YAML, and [`prek util yaml-to-toml`](https://prek.j178.dev/reference/cli/#prek-util-yaml-to-toml) helps migrate existing configs.
- Built-in support for [workspaces](https://prek.j178.dev/monorepos/) means monorepos can keep separate configs per project and still run everything from one command, while independent same-depth projects run concurrently without mixing file scopes.
- [`prek install`](https://prek.j178.dev/reference/cli/#prek-install) and [`prek uninstall`](https://prek.j178.dev/reference/cli/#prek-uninstall) honor repo-local and worktree-local `core.hooksPath`.
- Hook [`groups`](https://prek.j178.dev/reference/configuration/#groups) let one config define workflows such as CI, linting, or formatting; `--group`, `--require-group`, and `--no-group` select them at runtime.
- [`prek run`](https://prek.j178.dev/reference/cli/#prek-run) can select or skip multiple projects and hooks, target tracked files with repeatable `--glob` or `--directory` filters, pass explicit paths with `--files`, and preview the selection with `--dry-run`.
- The progress UI streams a live preview from running hooks, so long-running checks do not look stuck and failures are easier to diagnose.
- [`prek list`](https://prek.j178.dev/reference/cli/#prek-list), [`prek util identify`](https://prek.j178.dev/reference/cli/#prek-util-identify), and [`prek util list-builtins -v`](https://prek.j178.dev/reference/cli/#prek-util-list-builtins) make it easier to inspect configured hooks, debug file matching, and discover builtins with their supported options.
### prek includes security-focused safeguards
- For supported managed toolchain downloads, `prek` verifies the downloaded archive or installer checksum before extracting or installing it, helping ensure the integrity of downloaded toolchains.
- [`prek update`](https://prek.j178.dev/reference/cli/#prek-update) can keep newly published releases on hold with `--cooldown-days`, filter eligible tags with glob patterns, and freeze revisions to commit SHAs.
- [`prek update`](https://prek.j178.dev/reference/cli/#prek-update) validates pinned SHA revisions against the fetched upstream refs, including impostor-commit detection, and keeps `# frozen:` comments in sync with the configured commit.
- [`prek update --check`](https://prek.j178.dev/reference/cli/#prek-update--check) is useful in CI when you want updates or frozen-reference mismatches to fail the job without rewriting the config.
For more detailed improvements prek offers, take a look at [Difference from pre-commit](https://prek.j178.dev/diff/).
## Who is using prek?
prek is pretty new, but it is already being used or recommended by some projects and organizations. GitHub stars are current as of April 15, 2026.
- [apache/airflow](https://github.com/apache/airflow/issues/44995) 45,050 stars
- [apache/iggy](https://github.com/apache/iggy/pull/2383) 4,116 stars
- [apache/lucene](https://github.com/apache/lucene/pull/15629) 3,401 stars
- [ast-grep/ast-grep](https://github.com/ast-grep/ast-grep.github.io/commit/e30818144b2967a7f9172c8cf2f4596bba219bf5) 13,413 stars
- [astral-sh/ruff](https://github.com/astral-sh/ruff/pull/22505) 47,070 stars
- [astral-sh/ty](https://github.com/astral-sh/ty/pull/2469) 18,308 stars
- [authlib/authlib](https://github.com/authlib/authlib/pull/804) 5,271 stars
- [cachix/devenv](https://github.com/cachix/devenv/pull/2304) 6,665 stars
- [cocoindex-io/cocoindex](https://github.com/cocoindex-io/cocoindex/pull/1564) 6,865 stars
- [commitizen-tools/commitizen](https://github.com/commitizen-tools/commitizen) 3,377 stars
- [DetachHead/basedpyright](https://github.com/DetachHead/basedpyright/pull/1413) 3,267 stars
- [django/djangoproject.com](https://github.com/django/djangoproject.com/pull/2252) 1,994 stars
- [fastapi/asyncer](https://github.com/fastapi/asyncer/pull/437) 2,407 stars
- [fastapi/fastapi](https://github.com/fastapi/fastapi/pull/14572) 97,209 stars
- [fastapi/typer](https://github.com/fastapi/typer/pull/1453) 19,210 stars
- [Future-House/paper-qa](https://github.com/Future-House/paper-qa/pull/1098) 8,377 stars
- [getsentry/sentry](https://github.com/getsentry/sentry/pull/110808) 43,639 stars
- [godotengine/godot](https://github.com/godotengine/godot/pull/119150) 110,312 stars
- [home-assistant/core](https://github.com/home-assistant/core/pull/160427) 86,029 stars
- [jcrist/msgspec](https://github.com/jcrist/msgspec/pull/918) 3,692 stars
- [jlowin/fastmcp](https://github.com/jlowin/fastmcp/pull/2309) 24,539 stars
- [MoonshotAI/kimi-cli](https://github.com/MoonshotAI/kimi-cli/pull/535) 7,800 stars
- [openclaw/openclaw](https://github.com/openclaw/openclaw/pull/1720) 357,512 stars
- [OpenLineage/OpenLineage](https://github.com/OpenLineage/OpenLineage/pull/3965) 2,406 stars
- [pdm-project/pdm](https://github.com/pdm-project/pdm/pull/3593) 8,553 stars
- [prowler-cloud/prowler](https://github.com/prowler-cloud/prowler/pull/10601) 13,592 stars
- [pyodide/pyodide](https://github.com/pyodide/pyodide/pull/6182) 14,527 stars
- [python-attrs/attrs](https://github.com/python-attrs/attrs/commit/c95b177682e76a63478d29d040f9cb36a8d31915) 5,770 stars
- [python-telegram-bot/python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot/pull/5142) 29,025 stars
- [python/cpython](https://github.com/python/cpython/issues/143148) 72,330 stars
- [simple-icons/simple-icons](https://github.com/simple-icons/simple-icons/pull/14245) 24,873 stars
For a more comprehensive list of open-source projects using prek see the [list of dependents on github](https://github.com/j178/prek/network/dependents).
## Badges
Show that your project uses prek with a badge in your README:
```markdown
[](https://github.com/j178/prek)
```
```html
```
```rst
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json
:target: https://github.com/j178/prek
:alt: prek
```
## Installation
# Installation
prek provides multiple installation methods to suit different needs and environments.
Prebuilt releases are available for macOS, Linux, and Windows across the architectures listed on the [GitHub Releases](https://github.com/j178/prek/releases) page.
## Standalone Installer
The standalone installer automatically downloads and installs the correct binary for your platform:
Use `curl` to download the script and execute it with `sh`:
```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/download/v0.5.3/prek-installer.sh | sh
```
Use `irm` to download the script and execute it with `iex`:
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://github.com/j178/prek/releases/download/v0.5.3/prek-installer.ps1 | iex"
```
Changing the [execution policy](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies) allows running a script from the internet.
Tip
The installation script may be inspected before use. Alternatively, binaries can be downloaded directly from [GitHub Releases](#github-releases).
## Package Managers
### PyPI
prek is published as Python binary wheel to PyPI, you can install it using `pip`, `uv` (recommended), or `pipx`:
```bash
# Using uv (recommended)
uv tool install prek
# Using uvx (install and run in one command)
uvx prek
# Adding prek to the project dev-dependencies
uv add --dev prek
# Using pip
pip install prek
# Using pipx
pipx install prek
```
### Homebrew (macOS/Linux)
```bash
brew install prek
```
### mise
To use prek with [mise](https://mise.jdx.dev) ([v2025.8.11](https://github.com/jdx/mise/releases/tag/v2025.8.11) or later):
```bash
mise use prek
```
### npm
prek is published as a [Node.js package](https://www.npmjs.com/package/@j178/prek) and can be installed with any npm-compatible package manager:
```bash
# npm
npm install -g @j178/prek
# pnpm
pnpm add -g @j178/prek
# bun
bun install -g @j178/prek
```
Or as a project dependency:
```bash
npm add -D @j178/prek
```
### Nix
prek is available via [Nixpkgs](https://search.nixos.org/packages?channel=unstable&show=prek&query=prek).
```shell
# Choose what's appropriate for your use case.
# One-off in a shell:
nix-shell -p prek
# NixOS or non-NixOS without flakes:
nix-env -iA nixos.prek
# Non-NixOS with flakes:
nix profile install nixpkgs#prek
```
### Conda
prek is available as `prek` via [conda-forge](https://anaconda.org/conda-forge/prek).
```shell
conda install conda-forge::prek
```
### Scoop (Windows)
prek is available via [Scoop](https://scoop.sh/#/apps?q=prek).
```powershell
scoop install main/prek
```
### Winget (Windows)
prek is available via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/).
```powershell
winget install --id j178.Prek
```
### MacPorts
prek is available via [MacPorts](https://ports.macports.org/port/prek/).
```bash
sudo port install prek
```
### cargo-binstall
Install pre-compiled binaries from GitHub using [cargo-binstall](https://github.com/cargo-bins/cargo-binstall):
```bash
cargo binstall prek
```
## Docker
prek provides a Docker image at [`ghcr.io/j178/prek`](https://github.com/j178/prek/pkgs/container/prek).
See the guide on [using prek in Docker](../integrations/#docker) for more details.
## GitHub Releases
Pre-built binaries are available for download from the [GitHub releases](https://github.com/j178/prek/releases) page.
## Build from Source
Build from source using Cargo (Rust 1.96+ is required):
```bash
cargo install --locked prek
```
## Verify the installation
For a global installation, confirm that `prek` is available on your `PATH`:
```bash
prek --version
```
If you added prek as a project dependency, run it through that package manager:
```bash
uv run prek --version
```
```bash
npm exec -- prek --version
```
The rest of this documentation uses the shorter `prek` form. For a project dependency, substitute `uv run prek` or `npm exec -- prek`.
## Run without installing
To try prek in an isolated environment without adding it to your project, use `uvx`:
```bash
uvx prek --version
```
Use `uvx prek` in place of `prek` in subsequent commands.
## Updating
If installed via the standalone installer, prek can update itself to the latest version:
```bash
prek self update
```
If you installed prek with a package manager, use its upgrade command. For example, use `uv tool upgrade prek` for a uv tool installation or `pip install --upgrade prek` for a pip installation.
## Shell Completion
Tip
Run `echo $SHELL` to determine your shell.
To enable shell autocompletion for prek commands, run one of the following:
```bash
echo 'eval "$(COMPLETE=bash prek)"' >> ~/.bashrc
```
```bash
echo 'eval "$(COMPLETE=zsh prek)"' >> ~/.zshrc
```
```bash
echo 'COMPLETE=fish prek | source' >> ~/.config/fish/config.fish
```
```powershell
Add-Content -Path $PROFILE -Value '$env:COMPLETE = "powershell"; prek | Out-String | Invoke-Expression; Remove-Item Env:\COMPLETE'
```
Then restart your shell or source the config file.
## Artifact Verification
Release artifacts are signed with [GitHub Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations) to provide cryptographic proof of their origin. Verify downloads using the [GitHub CLI](https://cli.github.com/):
```console
$ gh attestation verify prek-x86_64-unknown-linux-gnu.tar.gz --repo j178/prek
Loaded digest sha256:xxxx... for file://prek-x86_64-unknown-linux-gnu.tar.gz
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
- Attestation #1
- Build repo:..... j178/prek
- Build workflow:. .github/workflows/release.yml@refs/tags/vX.Y.Z
```
This confirms the artifact was built by the official release workflow.
## Quickstart
# Quickstart
This page helps you get productive with **prek** in minutes, whether you are migrating from [pre-commit](https://pre-commit.com/) or starting from scratch.
First follow the [installation guide](.././installation/) to install prek on your system.
[I already use pre-commit](#already-using-pre-commit) [I'm new to pre-commit-style tools](#new-to-pre-commit-style-workflows)
## Already using pre-commit?
Great news - prek is designed as a drop-in replacement, you only need two tweaks:
1. Replace every `pre-commit` command in your scripts or documentation with `prek`. Your existing `.pre-commit-config.yaml` continues to work unchanged.
```console
$ prek run
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
typos....................................................................Passed
cargo fmt................................................................Passed
cargo clippy.............................................................Passed
```
1. Reinstall the Git shims once via `prek install -f` (run this if you previously executed `pre-commit install`).
From here you can explore what prek adds on top of pre-commit:
- [Key differences and new features](.././diff/)
- [Built-in Rust-native hooks](../built-in-hooks/)
- [Workspace mode for monorepos](../monorepos/)
## New to pre-commit-style workflows?
Follow this short example to experience how prek automates linting and formatting tasks.
### 1. Initialize the repository
From the root of a Git repository without an existing hook configuration, run:
```bash
prek init
```
This creates a starter `prek.toml` and installs the `pre-commit` Git shim so Git runs prek when you commit.
Note
`prek.toml` is the native configuration file for **prek**. prek also supports `.pre-commit-config.yaml`, so you can keep your existing configuration.
The generated configuration uses prek's built-in hooks:
```toml
[[repos]]
repo = "builtin"
hooks = [
{ id = "trailing-whitespace" },
{ id = "end-of-file-fixer" },
{ id = "check-added-large-files" },
]
```
Add a small YAML file so the first run has something to check, then stage both files:
example.yaml
```yaml
project: prek
enabled: true
```
```bash
git add prek.toml example.yaml
```
`prek run` checks the staged snapshot, so a new or changed config must be staged before this default run. You can still review or unstage it after trying the workflow.
### 2. Run hooks on demand
Use `prek run` to execute all configured hooks on the files in your current git staging area:
```console
$ prek run
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check for added large files..............................................Passed
```
The built-in hooks in this example are ready to run immediately. Remote hooks can take longer on their first run while prek downloads their repository and prepares the environment.
Need to run a single hook? Pass its ID, for example `prek run trailing-whitespace`. You can also target specific files with `--files`, or run against the entire repository with `--all-files`. Use `--all-files` after adding or changing a hook to check existing files that are not staged.
### 3. Customize the hooks
Edit the generated configuration to add or remove hooks. For example, add Ruff to lint and format Python files:
```toml
[[repos]]
repo = "https://github.com/astral-sh/ruff-pre-commit"
rev = "v0.16.0"
hooks = [
{ id = "ruff-check" },
{ id = "ruff-format" },
]
```
Because `prek init` installed the Git shim, every `git commit` invokes the configured hooks for the files in that commit. Run `prek install` to reinstall the shim later, or `prek uninstall` to remove it.
### 4. Go further
For other setups, `prek init --format yaml` creates `.pre-commit-config.yaml`. Use `prek init --no-install` to create only the config, then run `prek install` when you are ready to enable checks on commit. To create a config in an existing subdirectory, see [Monorepos](../monorepos/#add-a-project-configuration).
- Explore richer configuration options in the official [pre-commit documentation](https://pre-commit.com/). Every example there works with prek.
- See [Running Hooks](../running-hooks/) for the commands you will use after setup and how to handle hook failures.
- Check the [configuration reference](.././reference/configuration/) for prek-specific settings.
- Browse the [built-in hooks](../built-in-hooks/) and the [difference guide](.././diff/) to see what else you can leverage.
That’s it! You now have automated checks running locally with minimal setup. When you’re ready to dive deeper, the rest of the docs cover advanced workflows, language-specific installers, and more.
## Migrating from Other Tools
# Migrating from Other Hook Tools
Move one hook at a time when replacing an existing setup. Keep the old hook available until the equivalent `prek` hook has run successfully on the whole repository and in CI.
## From pre-commit
Start with the two-step path in the [Quickstart](../quickstart/#already-using-pre-commit). The [Compatibility](../compatibility/) and [Differences](../diff/) pages cover the cases worth checking when a repository depends on less common behavior.
## From lint-staged or Husky
A lint-staged command usually becomes a [`repo = "local"`](../local-hooks/) hook. For example, this hook runs the project's ESLint installation and lets `prek` append matching filenames:
```toml
[[repos]]
repo = "local"
[[repos.hooks]]
id = "eslint"
name = "eslint"
language = "system"
entry = "npm exec -- eslint"
files = "\\.[cm]?[jt]sx?$"
pass_filenames = true
```
```yaml
repos:
- repo: local
hooks:
- id: eslint
name: eslint
language: system
entry: npm exec -- eslint
files: '\.[cm]?[jt]sx?$'
pass_filenames: true
```
The project must install its Node dependencies before this hook runs. Map the rest of the setup as follows:
| Existing concept | prek equivalent |
| ------------------------------- | --------------------------------------------------------- |
| lint-staged file glob | `files`, `types`, `types_or`, and `exclude` |
| Filenames appended to a command | `pass_filenames = true`, which is the default |
| Command discovers its own files | `pass_filenames = false` |
| Shell pipeline or expansion | Prefer a direct command; otherwise set `shell` explicitly |
| Husky hook script | A Git stage plus `prek install` |
If a Husky script also performs unrelated work, keep that work in a project script and call the script from a local hook. This keeps the Git shim small and makes the command easy to run outside Git.
## From Lefthook
Translate each Lefthook command into a local hook:
| Lefthook concept | prek equivalent |
| -------------------------------------------- | -------------------------------------------- |
| Hook name such as `pre-commit` or `pre-push` | Hook `stages` and an installed Git shim |
| `commands..run` | Local hook `entry` and `args` |
| `{staged_files}` | The default `pass_filenames = true` behavior |
| `glob` and `exclude` | `files`, `types`, and `exclude` |
| Parallel command groups | Hooks with the same `priority` |
Installing a shim and making a hook eligible for that stage are separate choices. For example:
```toml
default_install_hook_types = ["pre-commit", "pre-push"]
[[repos]]
repo = "local"
[[repos.hooks]]
id = "tests"
name = "tests"
language = "system"
entry = "cargo test"
pass_filenames = false
stages = ["pre-push"]
```
Hooks remain sequential when `priority` is omitted. Give independent hooks the same explicit [`priority`](../reference/configuration/#priority) only after checking that they do not modify the same files or contend for shared state.
## Keep the existing hook during rollout
If `.git/hooks/` already belongs to another tool, a normal `prek install` moves it to `.legacy` and installs prek in migration mode. The prek shim runs both hook implementations.
```bash
prek install
```
When the migration is complete, replace the legacy hook:
```bash
prek install --force
```
Before using `--force`, make sure the old hook contains no checks that are still needed. If you uninstall while migration mode is active, `prek uninstall` restores the legacy hook to its original path.
## Migration checklist
1. Put each existing check in a local or remote hook.
1. Confirm file filtering and whether the command accepts filenames.
1. Configure every Git stage that the old tool handled.
1. Stage the config and run `prek run --all-files`.
1. Add the same command to [CI](../ci/).
1. Install the Git shims, initially preserving the old hook if useful.
1. Remove the old tool and dependencies only after local and CI runs agree.
## Running Hooks
# Running Hooks
Run hooks on demand or let Git run them when you commit. If you are setting up prek for the first time, start with the [Quickstart](../quickstart/).
For a repository that already has a config, enable its Git hooks in your checkout by running `prek install` from the repository root. If another tool already owns the hook, see [migration mode](../migration/#keep-the-existing-hook-during-rollout).
## Run hooks yourself
You do not need to create a commit to run the configured hooks.
Run hooks for the files currently staged in Git:
```bash
prek run
```
Run hooks against the whole repository, commonly before opening a pull request:
```bash
prek run --all-files
```
Run a single hook by ID:
```bash
prek run ruff
```
Inspect what would run without executing hooks or changing files:
```bash
prek run --dry-run
```
## Prepare hook environments
prek normally prepares a hook's environment the first time it is needed. To prepare environments in advance while setting up a checkout, run:
```bash
prek prepare-hooks
```
When setting up a checkout, `prek install --prepare-hooks` installs the Git shims and prepares environments together. See [Debugging](../debugging/#cache-problems) for inspecting and cleaning cached environments.
## What happens when you commit
Use Git as usual: stage the changes that belong in the commit, then commit them.
```console
$ git add settings.json
$ git commit -m "Update settings"
check json...............................................................Passed
mixed line ending........................................................Passed
[main 0123456] Update settings
1 file changed, 1 insertion(+)
```
Before Git creates the commit, the `pre-commit` shim runs hooks configured for that stage against the staged files. Unstaged changes are temporarily stashed while the hooks run, so the hooks check the contents that will be committed.
If every hook passes, Git creates the commit. If a hook fails or modifies files, prek exits unsuccessfully and Git stops without creating the commit.
## When a hook reports a failure
A hook can reject a change and print the problem it found. For example:
```console
$ git commit -m "Update settings"
check json...............................................................Failed
- hook id: check-json
- exit code: 1
settings.json: Failed to json decode (trailing comma at line 3 column 1)
```
Read the hook output, fix the reported problem, stage the corrected file, and retry the commit:
```console
$ git add settings.json
$ git commit -m "Update settings"
check json...............................................................Passed
[main 0123456] Update settings
1 file changed, 1 insertion(+)
```
The failed attempt did not create a partial commit. Other hooks may have reported additional problems, so check the complete output before retrying.
## When a hook modifies files
Formatters and other fixing hooks can update files automatically. prek marks the run as failed so that you can review and stage those changes before committing them:
```console
$ git commit -m "Normalize line endings"
mixed line ending........................................................Failed
- hook id: mixed-line-ending
- exit code: 1
- files were modified by this hook
Fixing mixed.txt
```
Inspect the changes, make any further edits you want, stage the final result, and retry:
```console
$ git diff -- mixed.txt
$ git add mixed.txt
$ git commit -m "Normalize line endings"
mixed line ending........................................................Passed
[main 0123456] Normalize line endings
1 file changed, 3 insertions(+), 3 deletions(-)
```
A hook can both modify files and report another error. In that case, keep the automatic fixes you want and resolve the remaining error before staging and retrying.
## Skip hooks for one commit
When one known hook is not applicable, skip only that hook by ID:
```bash
PREK_SKIP=ruff git commit -m "Update generated files"
```
`SKIP=ruff` is accepted for compatibility. In a workspace, the value can also be a [project or project-qualified selector](../reference/workspace/#selectors).
When the repository's policy permits it, Git can instead bypass the entire `pre-commit` and `commit-msg` hook chain for one commit:
```bash
git commit --no-verify
```
This does not fix the reported problem, and the same checks may still fail in continuous integration. Prefer fixing or explicitly resolving the hook failure when possible.
## Run a command in a hook environment
Use `prek exec` to run an explicit command with the toolchain, installed dependencies, and environment variables prepared for one configured hook. The hook environment is prepared first if necessary:
```bash
prek exec prettier -- prettier --stdin-filepath src/app.js < src/app.js
```
The hook selector must resolve to exactly one hook. In a workspace, use a project-qualified selector when needed, for example:
```bash
prek exec frontend:prettier -- prettier --version
```
The command runs in your current directory with the selected hook's environment. See [`prek exec`](../reference/cli/#prek-exec) for supported hooks and complete execution behavior.
## Inspect and debug
List the hooks and projects discovered in the current workspace:
```bash
prek list
```
Use verbose output when a hook fails without enough context:
```bash
prek run -vvv
```
See [Debugging](../debugging/) for logs, cache problems, and hooks that do not run as expected.
## Where to go next
- [Configuration](../configuration/) covers config file formats, discovery, validation, and updating hooks.
- [Local Hooks](../local-hooks/) covers inline hook definitions, file passing, filtering, and working-directory behavior.
- [Continuous Integration](../ci/) covers full-repository and revision-range checks in CI.
- [Monorepos](../monorepos/) covers nested project configs and project selection.
- [CLI Reference](../reference/cli/) lists every command and option.
## Configuration
# Configuration
Use a project config to choose hooks and customize their options. If you need a starter config, follow the [Quickstart](../quickstart/). This page covers editing, validating, and updating that config; [Running Hooks](../running-hooks/) covers executing it.
## Choose a config file
prek reads one config per project. Keep an existing `.pre-commit-config.yaml`, or use `prek.toml` for a new setup. Both formats describe the same configuration model.
| Filename | Format |
| ------------------------- | ------ |
| `prek.toml` | TOML |
| `.pre-commit-config.yaml` | YAML |
| `.pre-commit-config.yml` | YAML |
If several of these files exist in one directory, prek uses the first one in the order above. Use one file per project to make it clear which config applies.
To convert a YAML config, run [`prek util yaml-to-toml`](../reference/cli/#prek-util-yaml-to-toml). The conversion does not preserve YAML comments. If the config must also work with upstream pre-commit, keep YAML and read [Sharing a config with pre-commit](#sharing-a-config-with-pre-commit).
## Add and configure hooks
List hook repositories under `repos`, pin each remote repository to a `rev`, and select its hooks by `id`:
```toml
[[repos]]
repo = "https://github.com/pre-commit/pre-commit-hooks"
rev = "v6.0.0"
hooks = [
{ id = "trailing-whitespace" },
{ id = "check-added-large-files", args = ["--maxkb=1024"] },
]
```
```yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: check-added-large-files
args: [--maxkb=1024]
```
The hook repository supplies defaults such as the command and language. Add options to a hook entry to customize it. Here, `args` changes the large-file limit to 1024 KB. Consult the hook's documentation for the arguments it accepts.
You can also use:
- [Local Hooks](../local-hooks/) to define commands directly in the project config.
- [Built-in Hooks](../built-in-hooks/) to use hooks bundled with prek.
### TOML and YAML syntax
For larger TOML hook entries, use an array of tables instead of an inline table. This is equivalent to the large-file hook above:
```toml
[[repos]]
repo = "https://github.com/pre-commit/pre-commit-hooks"
rev = "v6.0.0"
[[repos.hooks]]
id = "check-added-large-files"
args = ["--maxkb=1024"]
```
prek also accepts multiline inline tables from TOML 1.1. If an editor does not support that syntax, use the array-of-tables form above.
In YAML, quote regular expressions containing backslashes, for example `files: '\.rs$'`. YAML anchors, aliases, and merge keys can reuse repeated configuration.
## Choose which files and stages to check
A hook's `files`, `exclude`, `types`, `types_or`, and `exclude_types` options control which files it receives. Top-level `files` and `exclude` apply to every hook in that project. For example, exclude generated files from all hooks by adding this at the top of the config, before the repository entries:
```toml
exclude = '^generated/'
```
```yaml
exclude: '^generated/'
```
`files` and `exclude` accept regular expressions or prek's explicit glob form. Type filters use file type tags; inspect a file's tags with:
```bash
prek util identify path/to/file
```
A hook's `stages` limits the Git hook stages where it runs. To install the corresponding Git shim, use `default_install_hook_types` or [`prek install --hook-type`](../reference/cli/#prek-install--hook-type). Setting `stages` alone does not install a shim.
See the [Configuration Reference](../reference/configuration/) for filter combinations, stage names, and all available options.
## Config location and scope
prek searches upward from the current directory for a config, stopping at the Git repository root. The first config found defines the workspace root; prek then discovers nested projects below it.
Each project applies its config independently. A parent's filters do not disable a child's hooks, and a child config does not override its parent. See [Monorepos](../monorepos/) for setting up and selecting nested projects, or the [Workspace Reference](../reference/workspace/) for discovery and file-scope rules.
Passing `--config` selects one config and disables workspace discovery. Hooks then run from the Git repository root with [repository-relative paths](../reference/workspace/#single-config-mode).
## Validate changes
After editing a config, validate it and run the hooks against existing files:
```bash
prek validate-config prek.toml
prek run --all-files
```
Use the repository's YAML config filename instead if applicable. [`prek validate-config`](../reference/cli/#prek-validate-config) accepts one or more config files. See [Debugging](../debugging/#a-hook-is-skipped-or-receives-no-files) if a hook is skipped unexpectedly.
If you want IDE completion / validation, prek publishes a JSON Schema through the [JSON Schema Store](https://www.schemastore.org/prek.json), so some editors may pick it up automatically.
## Update hook versions
Update pinned remote hook revisions with:
```bash
prek update
```
Review the config diff, then run `prek run --all-files` to check the updated hooks against the repository. Use `prek update --check` to check for available updates without changing the config. See [`prek update`](../reference/cli/#prek-update) for selecting repositories and controlling updates.
## User settings
`prek` also reads an optional user-level global config from the platform config directory:
- Linux and macOS: `~/.config/prek/prek.toml` (or `$XDG_CONFIG_HOME/prek/prek.toml` when `XDG_CONFIG_HOME` is set)
- Windows: `%APPDATA%\prek\prek.toml`
This file is for user-level prek settings, not hook definitions. Project hooks still live in the project config files described above. For the supported global settings, see the [configuration reference](../reference/configuration/#global-config-file).
## Sharing a config with pre-commit
Existing pre-commit YAML configs work in prek. To use the same config with both tools, keep the YAML format and avoid prek-only extensions. Upstream pre-commit may warn about unknown keys or reject unsupported features.
See [Compatibility](../compatibility/#if-you-need-strict-upstream-portability) for the features that affect portability and [Differences](../diff/) for broader behavior differences.
## Local Hooks
# Local Hooks
`repo: local` defines hooks directly in the current project's configuration instead of loading them from a separate hook repository.
## A minimal local hook
The following hook expects `uv` and the project's dependencies to be available. `prek` appends matching Python filenames to the command.
```toml
[[repos]]
repo = "local"
[[repos.hooks]]
id = "ruff"
name = "ruff"
language = "system"
entry = "uv run ruff check"
types = ["python"]
```
```yaml
repos:
- repo: local
hooks:
- id: ruff
name: ruff
language: system
entry: uv run ruff check
types: [python]
```
`language = "system"` means that prek does not install the command. The entry and any interpreters or package managers it invokes must already be available on `PATH`.
## Choose a language
For a project linter or formatter, start with `language = "system"` as in the example above. Other choices depend on how the command should be installed:
| What the command needs | Language |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| A tool already installed by the project or CI image | [`system`](../reference/language-support/#system) |
| A checked-in executable script | [`script`](../reference/language-support/#script) |
| Dependencies installed in a hook environment | The ecosystem's language, such as `python` or `node` |
| A packaged container runtime | [`docker`](../reference/language-support/#docker) or [`docker_image`](../reference/language-support/#docker_image) |
The [Language Support reference](../reference/language-support/) lists supported languages, toolchain requirements, and installation behavior. For simple content or filename checks, a [built-in hook](../reference/built-in-hooks/) may already do what you need.
## Decide how the command receives files
`pass_filenames` defaults to `true`. Matching filenames are appended after `entry` and `args`:
```text
uv run ruff check path/to/one.py path/to/two.py
```
Set it to `false` when the command discovers files itself or always checks a whole workspace:
```toml
[[repos]]
repo = "local"
[[repos.hooks]]
id = "cargo-fmt"
name = "cargo fmt"
language = "system"
entry = "cargo fmt --all -- --check"
types = ["rust"]
pass_filenames = false
```
A positive integer limits each invocation to that many filenames and lets prek split a large match set into batches. See [`pass_filenames`](../reference/configuration/#pass_filenames) before using this prek-specific form.
## Filter when the hook runs
Local hooks use the same [file and stage filters](../configuration/#choose-which-files-and-stages-to-check) as remote hooks. In the Ruff example, `types = ["python"]` limits the command to Python files. In the Cargo example, `types = ["rust"]` controls whether the command runs, while `pass_filenames = false` lets Cargo select files itself.
## Commands do not use a shell by default
prek splits `entry` into arguments and invokes the program directly. Operators such as `|`, `&&`, redirects, variables, and globs are not interpreted by a shell.
Prefer putting complex logic in a checked-in script and using that script as the entry. If shell syntax is truly part of the hook, set the prek-specific [`shell`](../reference/configuration/#shell) option and write the command for that shell. Shell-specific hooks are less portable, especially between Windows and Unix systems.
## Working directory
A local hook runs in the directory of the project whose config defines it. In a single-config repository this is normally the Git root. In [workspace mode](../monorepos/), a nested project's hooks run in that nested project directory. Entries should therefore use paths relative to their own project rather than the directory from which the user invoked prek.
For the exact entry resolution model, see [Hook Entry Resolution](../internals/#hook-entry-resolution).
## Built-in Hooks
# Built-in Hooks
prek includes fast, Rust-native implementations of popular hooks for speed and low overhead.
Use `repo: builtin` to select them directly, or keep a supported remote hook config and let prek use its automatic fast path.
| | `repo: builtin` | Automatic fast path |
| ---------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------- |
| Config remains usable by upstream `pre-commit` | No | Yes |
| Remote repository and manifest | Not used | Cloned at the pinned `rev` |
| Environment available for fallback | Not needed | Yes |
| Network needed for first preparation | No | Yes |
| How to opt out | Replace `repo: builtin` with a remote or local hook | Set the hook's declared language or `PREK_NO_FAST_PATH=1` |
Check implementation notes when behavior matters
The Rust implementations target the same purpose as their upstream hooks, but a hook can have documented differences in arguments, defaults, or edge cases. Check its entry in the [Hook Reference](../reference/built-in-hooks/#hook-reference). To compare behavior, disable the fast path and run the pinned implementation.
## Use built-in hooks directly
Add `repo: builtin` and select hooks by ID:
```toml
[[repos]]
repo = "builtin"
hooks = [
{ id = "trailing-whitespace" },
{ id = "check-added-large-files" },
]
```
```yaml
repos:
- repo: builtin
hooks:
- id: trailing-whitespace
- id: check-added-large-files
```
List the builtins bundled with your installed prek version using:
```bash
prek util list-builtins
```
See the [built-in hook reference](../reference/built-in-hooks/) for the complete list of hooks, supported arguments, and behavior notes.
## Use the automatic fast path
For supported hooks from `https://github.com/pre-commit/pre-commit-hooks`, prek runs the built-in implementation automatically. Your existing remote config can stay compatible with upstream pre-commit. The `rev` field does not affect fast-path detection. It still selects the manifest that prek reads and the repository implementation used for fallback.
```yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks # Enables fast path
rev: v6.0.0 # Used for the manifest and fallback, not fast-path detection
hooks:
- id: trailing-whitespace
```
Note
In this mode, `prek` will still clone the repository and create the environment (e.g., a Python venv) to ensure full compatibility and fallback capabilities. However, the actual hook execution bypasses the environment and runs the native Rust code.
See [fast-path support](../reference/built-in-hooks/#automatic-fast-path) for the list of hooks that use the built-in implementation automatically. Other hooks run via the standard method.
### Run the repository implementation
To use the pinned repository implementation for a single hook, explicitly set the language declared by that hook:
```yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-yaml
language: python # Use the pinned repository implementation
```
To disable the fast path for every hook in a prek invocation:
```bash
PREK_NO_FAST_PATH=1 prek run
```
## Monorepos
# Monorepos
Keep shared checks in the repository root and give individual projects their own hook configurations. When you run prek from the root, it discovers the nested configs and runs their hooks too. This is called **workspace mode**; no workspace manifest or opt-in setting is needed.
## Add a project configuration
Start with a root config for checks that apply across the repository. Add a config in each directory that needs its own checks:
```text
my-repo/
├── .git/
├── prek.toml
└── frontend/
├── prek.toml
└── package.json
```
For example, trim trailing whitespace throughout the repository:
prek.toml
```toml
[[repos]]
repo = "builtin"
hooks = [{ id = "trailing-whitespace" }]
```
Then check JSON syntax in `frontend/`:
frontend/prek.toml
```toml
[[repos]]
repo = "builtin"
hooks = [{ id = "check-json" }]
```
Each directory containing a config is a **project**. Projects can also use `.pre-commit-config.yaml` or `.pre-commit-config.yml`, and can contain further nested projects. See [Local Hooks](../local-hooks/) to run a project's existing linter or formatter.
If you prefer a starter config, `prek init frontend --no-install` creates one in an existing project directory. Edit it to choose that project's hooks.
## Run checks across the repository
Run these commands from the repository root:
```bash
prek list
prek run --all-files
```
`prek list` shows the discovered projects and hooks. In this example, `frontend/package.json` is checked by both `frontend`'s JSON hook and the root's whitespace hook. A child config adds checks; it does not override its parent.
To run hooks automatically when committing, install the Git shim once from the repository root:
```bash
prek install
```
Stage the config files along with your changes before committing or running `prek run` without `--all-files`. That run checks staged files. Configure `default_install_hook_types` in the root config if you need Git stages other than `pre-commit`; installation does not combine this setting from subprojects.
## Run or skip a project
From the repository root, select a project with a trailing slash, or qualify a hook ID with its project path:
```bash
# Run hooks from frontend and any projects nested inside it
prek run frontend/ --all-files
# Run only frontend's JSON check
prek run frontend:check-json --all-files
# Run every hook named check-json in the workspace
prek run check-json --all-files
# Run the other projects' hooks
prek run --skip frontend/ --all-files
```
Selecting `frontend/` leaves out the root project's hooks. Skipping `frontend/` leaves the root's hooks eligible to check files inside `frontend/`.
To skip a project for one commit, use `PREK_SKIP=frontend/ git commit`. See the [workspace reference](../reference/workspace/#selectors) for combining selectors, hook aliases, and skip precedence.
## Choose which checks apply to a project's files
Hooks run in their project's directory. The filenames they receive and the `files` / `exclude` patterns are relative to that directory. For example, a frontend hook sees `package.json`, while a root hook sees `frontend/package.json`.
Each project applies its filters independently. A root-level `exclude` can prevent a root hook from checking `frontend/`, but does not disable the frontend project's hooks. Put checks that need files from several projects in a config at their common ancestor.
If a project should handle its files without any parent checks, add `orphan` at the top level of its config, before `[[repos]]`:
```toml
orphan = true
```
```yaml
orphan: true
```
For `frontend/`, this excludes its files from the root's hooks. Keep the shared checks you still want in the frontend config. Even if you skip an orphan project, its files do not fall back to parent hooks. See [orphan projects](../reference/workspace/#orphan-projects) for the full rules.
## Exclude a directory from project discovery
To stop discovering configs under a directory, add it to `.prekignore` at the repository root:
.prekignore
```text
legacy/
```
Then run `prek run --all-files --refresh`. This excludes projects under `legacy/`; root hooks can still check files there. Use the root config's `exclude` if those files should also be excluded from its checks.
Discovery already respects Git ignore rules. `.prekignore` adds exclusions without ignoring the files in Git. See the [discovery rules](../reference/workspace/#discovery) for other exclusions.
## Work from a project directory
Running inside `frontend/` uses its config as the workspace root and discovers projects below it. You can do the same from the repository root with:
```bash
prek -C frontend run --all-files
```
Use `-C` to change the working directory before discovery. Use `--config` when you want to run exactly one config with paths relative to the Git repository root:
| Command from the repository root | Configs used | Hook working directory |
| -------------------------------------- | -------------------------------- | ------------------------ |
| `prek run frontend/` | Frontend and its nested projects | Each project's directory |
| `prek -C frontend run` | Frontend and its nested projects | Each project's directory |
| `prek run --config frontend/prek.toml` | Only `frontend/prek.toml` | Git repository root |
Passing `--config` disables workspace discovery, even when the config is in a subdirectory. See [single config mode](../reference/workspace/#single-config-mode) for file scope and filtering.
## A new project is not being discovered
After adding a config or changing `.prekignore`, refresh discovery:
```bash
prek list --refresh
prek run --all-files --refresh
```
If the project is still missing, check that it is below the workspace root and not excluded by the [discovery rules](../reference/workspace/#discovery). For staged-file runs, also stage the new config. See [Debugging](../debugging/#a-config-or-workspace-change-is-not-detected) for more help.
## Continuous Integration
# Continuous Integration
Run the same checked-in configuration locally and in CI. For most repositories, the reliable default is:
```bash
prek run --all-files
```
This checks every tracked file instead of depending on a CI job's staging area. The command exits unsuccessfully when a hook fails or modifies files, so no extra wrapper is required.
## GitHub Actions
prek can be used in GitHub Actions via the [j178/prek-action](https://github.com/j178/prek-action) repository.
Example workflow:
```yaml
name: Prek checks
on: [push, pull_request]
jobs:
prek:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
```
This action installs prek and runs `prek run --all-files` on your repository.
prek is also available via [`taiki-e/install-action`](https://github.com/taiki-e/install-action) for installing various tools.
## Other CI systems
Install a pinned prek version using one of the methods in the [Installation](../installation/) guide, check out the repository, and run:
```bash
prek run --all-files
```
Project-local commands still need their project dependencies. For example, a local hook that invokes `npm exec` requires the Node dependencies to be installed before prek runs.
## Check only a revision range
Large repositories can run hooks only for files changed between two refs:
```bash
prek run --from-ref origin/main --to-ref HEAD
```
The checkout must contain both refs and enough history to calculate the diff. Shallow CI checkouts often need a larger fetch depth or an explicit fetch of the base branch. If that setup is unreliable, use `--all-files`.
## Cache and credentials
`PREK_HOME` contains cloned hook repositories, prepared environments, managed toolchains, and logs. Caching it can reduce setup time, but cache correctness depends on the prek version, platform, config, and hook revisions. Start without a cache, then add a narrowly keyed cache only if environment preparation is a meaningful part of the job.
Private hook repositories need non-interactive Git credentials. Configure the CI provider's credential helper or token before running prek, and avoid printing tokens in verbose logs. See the [private repository FAQ](../faq/#how-do-i-use-hooks-from-private-repositories) and the [Security Guide](../security/).
## Automatically fix pull requests with autofix.ci
[`autofix.ci`](https://autofix.ci/) can commit changes made by formatting and other fixing hooks back to a pull request. It cannot fix a check-only failure; the configured hook must modify files itself.
Install the [autofix.ci GitHub App](https://autofix.ci/setup), then add `.github/workflows/autofix.yml`:
```yaml
name: autofix.ci
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
autofix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
with:
install-only: true
- name: Run prek
id: prek
continue-on-error: true
run: prek run --all-files
- name: Verify fixes
if: steps.prek.outcome == 'failure'
run: prek run --all-files
- name: Commit fixes
if: always() && !cancelled()
uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4
```
Keep the workflow name exactly `autofix.ci`; the service uses it to identify the trusted workflow. The first prek run may fail after a hook changes files, so the workflow lets that step continue and runs prek again against the updated working tree. The final step still records those changes when another check cannot be fixed, while the failed verification keeps the job unsuccessful.
Run all fixing tools in this job and call `autofix-ci/action` only once, after they finish. The workflow itself keeps read-only repository access; the GitHub App provides the scoped permission used to create the fix commit. See the [autofix.ci security model](https://autofix.ci/security) for details.
## Cookbook
# Cookbook
Short recipes for setup patterns that go beyond the default project-local workflow.
## Enable a Global Hook with Git Config
Git 2.54 introduced [config-based hooks](https://github.blog/open-source/git/highlights-from-git-2-54/#h-config-based-hooks), which let Git run hooks from config instead of hook scripts. This is useful when you want a personal `prek` hook that works across repositories.
Only enable discovery for repositories you trust
The discovery form below reads the current repository's config and executes its hooks during Git operations. A repository can therefore cause project-controlled code to run with your user permissions. Use this pattern only for trusted repositories. For broader use, point the hook at a fixed config that you control and review the [Security Guide](../security/).
Confirm that your Git version supports config-based hooks:
```bash
git --version
```
The version must be 2.54 or newer.
Choose the Git hook event you want to run on, for example `pre-commit`, then register a global config-based hook:
```bash
git config --global hook.prek-pre-commit.event pre-commit
git config --global hook.prek-pre-commit.command 'prek hook-impl --hook-type pre-commit --skip-on-missing-config --'
```
Edit your global Git config directly, for example in `~/.gitconfig`:
```text
[hook "prek-pre-commit"]
event = pre-commit
command = prek hook-impl --hook-type pre-commit --skip-on-missing-config --
```
The config has three moving parts:
- `hook..event`: the Git hook event to listen for, such as `pre-commit`, `pre-push`, or `commit-msg`.
- `hook..command`: the command Git runs for that event.
- ``: a user-defined name for this configured hook. Keep it unique in your Git config.
Keep these command options
Keep `--skip-on-missing-config` in the command so repositories without a `prek.toml` or `.pre-commit-config.yaml` do not fail ordinary Git operations.
Keep the trailing `--` so Git-provided hook arguments, such as a `commit-msg` filename or `pre-push` remote name and URL, are forwarded to `prek hook-impl` instead of being parsed as hook selectors.
By default, `prek hook-impl` discovers the current repository's config. If you want one global hook config to run in every repository, pass that config explicitly:
```bash
git config --global hook..command 'prek hook-impl --hook-type --config --'
```
For example, a global config file at `~/.config/prek/global-hooks.toml` can run gitleaks in every repository:
```toml
[[repos]]
repo = "https://github.com/gitleaks/gitleaks"
rev = "v8.24.2"
hooks = [{ id = "gitleaks" }]
```
Then point the global Git hook at that config:
```bash
git config --global hook.gitleaks.event pre-commit
git config --global hook.gitleaks.command 'prek hook-impl --hook-type pre-commit --config ~/.config/prek/global-hooks.toml --'
```
### Remove a global config-based hook
Remove both keys for the friendly name you registered. For the first example on this page, run:
```bash
git config --global --unset-all hook.prek-pre-commit.event
git config --global --unset-all hook.prek-pre-commit.command
```
For a different friendly name, replace `prek-pre-commit` in both commands. This changes the global Git configuration; it does not remove project-local hook scripts installed by `prek install`.
## More recipes
- [Run an existing project linter or formatter](../local-hooks/)
- [Run hooks in continuous integration](../ci/)
- [Migrate while preserving an existing Git hook](../migration/#keep-the-existing-hook-during-rollout)
## Integrations
# Integrations
Use prek in container images and with coding agents. For GitHub Actions and other CI workflows, see [Continuous Integration](../ci/).
## Docker
prek publishes container images under `ghcr.io/j178/prek`:
| Tags | Base | Contents |
| -------------------------------------------------- | ---------------------- | -------------------------------- |
| `X.Y.Z`, `X.Y`, `latest` | `scratch` | The `prek` binary only |
| `X.Y.Z-alpine`, `X.Y-alpine`, `alpine` | Current Alpine release | `prek`, Git, and CA certificates |
| `X.Y.Z-alpine3.24`, `X.Y-alpine3.24`, `alpine3.24` | `alpine:3.24` | Version-pinned Alpine variant |
Note
Docker image tags before `0.4.10` include a leading `v`, for example `ghcr.io/j178/prek:v0.4.9`. The Alpine variant is available starting with `0.4.10`.
### Minimal (scratch)
The image is based on `scratch` (no shell, no package manager). It contains the prek binary at `/prek`.
A common pattern is to copy the binary into your own image:
```dockerfile
FROM debian:bookworm-slim
COPY --from=ghcr.io/j178/prek:0.5.3 /prek /usr/local/bin/prek
```
If you prefer, you can also run the distroless image directly:
```bash
docker run --rm ghcr.io/j178/prek:0.5.3 --version
```
### Alpine
The Alpine variant includes `prek`, Git, CA certificates, a shell, and the Alpine package manager.
```bash
docker run --rm ghcr.io/j178/prek:0.5.3-alpine --version
```
Use `X.Y.Z-alpine3.24` to pin both the prek and Alpine versions, or `alpine3.24` to pin only the Alpine version while tracking the latest prek release. Tags without the numbered Alpine suffix, such as `X.Y.Z-alpine` and `alpine`, use the current supported Alpine release.
### Verifying Images
All Docker image variants are signed with [GitHub Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations) to verify they were built by official prek workflows. Verify using the [GitHub CLI](https://cli.github.com/):
```console
$ gh attestation verify --owner j178 oci://ghcr.io/j178/prek:latest
Loaded digest sha256:xxxx... for oci://ghcr.io/j178/prek:latest
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
- Attestation #1
- Build repo:..... j178/prek
- Build workflow:. .github/workflows/build-docker.yml@refs/tags/vX.Y.Z
```
Tip
Use a specific version tag (e.g., `ghcr.io/j178/prek:0.5.3`) or image digest rather than `latest` for verification.
## prek skill for agents
To let agents use `prek`, install the `prek` skill with `gh skill` (`v2.90.0+`):
```bash
gh skill install j178/prek prek
```
## Hook Repositories
# Authoring Hooks
This page is for hook authors who publish a repository consumed by end users. If you only need to configure hooks in your own project, see [Run Existing Project Commands](../local-hooks/).
A minimal hook repository has a manifest at its root plus the source and packaging files required by its language. For example, a Python hook might use:
```text
my-hook/
├── .pre-commit-hooks.yaml
├── pyproject.toml
└── src/
└── my_hook/
└── __init__.py
```
The exact packaging files vary by language. The manifest tells consumers which installed command to run; the language backend determines how the repository is installed.
## Manifest file: `.pre-commit-hooks.yaml`
Hook repositories must include a `.pre-commit-hooks.yaml` file at the repo root. There is no separate `prek` manifest format; `prek` reads the same `.pre-commit-hooks.yaml` manifest defined by upstream `pre-commit`. This keeps hook repositories compatible with the broader pre-commit ecosystem.
Hooks should exit non-zero on failure (or modify files and exit non-zero for fixers).
The manifest is a YAML list of hook definitions. `prek` supports these fields in each manifest hook:
| Field | Required | `prek`-only | Type | Description |
| ------------------------- | -------- | ----------- | --------------------------- | ---------------------------------------------------------------------------------------------- |
| `id` | Yes | No | string | Stable identifier used in end-user configs. |
| `name` | Yes | No | string | Human-friendly label shown in output. |
| `entry` | Yes | No | string | Command to execute. |
| `shell` | No | Yes | string enum | Run `entry` through a predefined shell adapter (`sh`, `bash`, `pwsh`, `powershell`, or `cmd`). |
| `language` | Yes | No | string | Execution environment, for example `python`, `node`, or `system`. |
| `alias` | No | No | string | Alternate identifier accepted by `prek run`. |
| `files` | No | No | regex string or glob map | Include only matching files. |
| `exclude` | No | No | regex string or glob map | Exclude matching files. |
| `types` | No | No | list of strings | Require all listed file type tags. |
| `types_or` | No | No | list of strings | Require at least one listed file type tag. |
| `exclude_types` | No | No | list of strings | Exclude files with any listed file type tag. |
| `additional_dependencies` | No | No | list of strings | Extra dependencies installed into managed hook environments. |
| `args` | No | No | list of strings | Extra arguments appended to `entry` before filenames. |
| `env` | No | Yes | map of strings | Environment variables for hook environment creation and execution. |
| `always_run` | No | No | boolean | Run even when no files match. |
| `fail_fast` | No | No | boolean | Stop the run immediately if this hook fails. |
| `pass_filenames` | No | No | boolean or positive integer | Control whether, or how many, matching filenames are passed. |
| `description` | No | No | string | Free-form metadata shown in listings; its first line is also shown with run details. |
| `language_version` | No | No | string or map | Language/toolchain version request and source preference. |
| `log_file` | No | No | string path | Write hook output to a file when the hook fails or is verbose. |
| `require_serial` | No | No | boolean | Avoid concurrent invocations of this hook. |
| `stages` | No | No | list of stage names | Git hook stages where this hook is eligible to run. |
| `verbose` | No | No | boolean | Print output even when the hook succeeds. |
| `minimum_prek_version` | No | Yes | version string | Minimum `prek` version required for this hook. |
For fields shared with upstream `pre-commit`, `prek` follows the upstream manifest semantics. For the upstream reference, see: .
`prek`-only manifest fields
`prek`-only fields are accepted by `prek`, but upstream `pre-commit` will not recognize them.
End-user configuration may also set [`env`](../reference/configuration/#prek-only-env) and [`shell`](../reference/configuration/#shell). When both the manifest and end-user config define `env`, the maps are merged and end-user values override duplicate keys.
`pass_filenames: n` with a positive integer is also a `prek` extension. Upstream `pre-commit` only accepts a boolean value.
The `{ glob: ... }` mapping form for `files` and `exclude` is a `prek` extension. Use the regex string form when a manifest must also work with upstream `pre-commit`.
The `language_version` options map with `request` and `preference` fields is a `prek` extension. Use the string form when a manifest must also work with upstream `pre-commit`.
When `shell` is set, `entry` is treated as shell source. Hook `args` and filenames are passed as script arguments, so POSIX shell entries should read them with `"$@"`. `shell` is supported only for language backends that use the shell-aware entry resolver; see [`shell`](../reference/configuration/#shell) for the supported languages and exact shell adapter commands.
Manifest fields only
Project configuration-only fields, such as `priority` and `groups`, are not manifest hook fields.
### Editor completion and validation
`prek` maintains a [`prek-hooks.schema.json`](https://raw.githubusercontent.com/j178/prek/master/prek-hooks.schema.json) schema for `.pre-commit-hooks.yaml`. The schema stays in the `prek` repository instead of being registered with SchemaStore, so editors must opt into it explicitly.
With YAML Language Server, add this directive at the top of the manifest:
```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/j178/prek/master/prek-hooks.schema.json
```
This enables completion and validation for both upstream fields and `prek` extensions such as glob filters, `env`, and `shell`.
Example:
```yaml
- id: format-json
name: format json
entry: python3 -m tools.format_json
language: python
files: "\\.json$"
- id: lint-shell
name: shellcheck
entry: shellcheck
language: system
types: [shell]
```
Prefer entries that invoke an executable directly. Do not assume a shell is present or that POSIX paths work on Windows unless the hook explicitly declares that platform requirement. The [Language Support](../reference/language-support/) and [Hook Entry Resolution](../internals/#hook-entry-resolution) pages describe the runtime and working-directory contracts.
## Choosing hook stages
Hook authors can declare which Git hook stages they support with `stages` in `.pre-commit-hooks.yaml`. End users can override that list in their configuration. If neither is set, `prek` falls back to the top-level `default_stages` (which defaults to all stages).
The `manual` stage is special: it never runs automatically and is only executed when a user explicitly runs `prek run --hook-stage manual `.
For what each stage means and whether it operates on repository files, see [Supported Git Hook Stages](../reference/configuration/#supported-git-hook-stages).
Example:
```yaml
- id: lint
name: lint
entry: my-lint
language: python
stages: [pre-commit, pre-merge-commit, pre-push, manual]
```
## Passing arguments to hooks
When users configure a hook with `args`, `prek` passes those arguments before the list of file paths. If `args` is empty or omitted, only file paths are provided.
Example end-user config:
```yaml
repos:
- repo: https://github.com/example/hook-repo
rev: v1.0.0
hooks:
- id: my-hook
args: [--max-line-length=120]
```
Invocation shape:
```text
my-hook --max-line-length=120 path/to/file1 path/to/file2
```
Hook processes also receive stage-specific `PRE_COMMIT_*` variables. See [Variables exposed to hooks](../reference/environment-variables/#variables-exposed-to-hooks) for the values available during `pre-push`, commit-message, rebase, checkout, and rewrite stages.
## Versioning for `prek update`
End users pin your repository using the `rev` field in their config. To make [`prek update`](../reference/cli/#prek-update) work as expected, publish git tags for releases:
- Prefer semantic version tags like `v1.2.3` or `1.2.3`.
- Push tags to the remote (annotated or lightweight tags both work).
- Avoid moving tags; treat them as immutable release references.
`prek update` selects the newest tag by default. With `--bleeding-edge`, it uses the default branch tip instead of tags. With `--freeze`, it writes commit SHAs into `rev` instead of tag names.
## Develop locally with `prek try-repo`
[`prek try-repo`](../reference/cli/#prek-try-repo) runs hooks from a repository without publishing a release. This is handy while iterating on a hook.
```bash
# In another repository where you want to test the hook
prek try-repo ../path/to/hook-repo my-hook-id --verbose
```
Notes:
- `prek try-repo` accepts any path or git URL `git clone` understands.
- For `prepare-commit-msg` or `commit-msg` hooks, pass the appropriate `--commit-msg-filename` argument when testing.
## Validation and CI
Validate your manifest locally with [`prek validate-manifest`](../reference/cli/#prek-validate-manifest):
```bash
prek validate-manifest .pre-commit-hooks.yaml
```
This ensures the manifest is well-formed before publishing a release tag.
Run that command in CI, then exercise the hook against a small fixture repository or with `prek try-repo`. See [Continuous Integration](../ci/) for the general CI setup.
## CLI Reference
# CLI Reference
Running `prek` without a subcommand is equivalent to running `prek run`.
## Exit status
| Code | Meaning |
| ----- | ------------------------------------------------------------------------------------------------- |
| `0` | The command succeeded. |
| `1` | A hook, validation, or other expected user-level check failed. |
| `2` | Command-line input, configuration, or an operational error prevented the command from completing. |
| `130` | The command was interrupted. |
`prek exec` propagates the exit code of the external command it runs.
## prek
A fast Git hook manager written in Rust, designed as a drop-in alternative to pre-commit, reimagined.
### Usage
```text
prek [OPTIONS] [HOOK|PROJECT]... [COMMAND]
```
### Commands
[`prek init`](#prek-init) : Create a prek configuration and install Git hook shims
[`prek install`](#prek-install) : Install prek Git hook shims
[`prek prepare-hooks`](#prek-prepare-hooks) : Prepare environments for configured hooks
[`prek run`](#prek-run) : Run configured hooks
[`prek exec`](#prek-exec) : Run a command in the environment prepared for a configured hook
[`prek list`](#prek-list) : List configured hooks
[`prek uninstall`](#prek-uninstall) : Uninstall prek Git hook shims
[`prek validate-config`](#prek-validate-config) : Validate prek configuration files
[`prek validate-manifest`](#prek-validate-manifest) : Validate pre-commit hook manifests (`.pre-commit-hooks.yaml`)
[`prek update`](#prek-update) : Update configured repositories
[`prek cache`](#prek-cache) : Manage the prek cache
[`prek try-repo`](#prek-try-repo) : Try hooks from a repository
[`prek util`](#prek-util) : Run utility commands
[`prek self`](#prek-self) : Manage the prek installation
## prek init
Create a prek configuration and install Git hook shims
### Usage
```text
prek init [OPTIONS] [PATH]
```
### Arguments
[`PATH`](#prek-init--path) : Existing directory to initialize.
```
Defaults to the current Git worktree root. Relative paths are resolved from the current directory after applying `--cd`, and the resolved path must be inside the current Git worktree.
```
### Options
[`--cd`](#prek-init--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-init--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-init--config), `-c` *config* : Path to alternate config file
[`--format`](#prek-init--format) *format* : Select the configuration format to create
```
[default: toml]
Possible values:
- `yaml`
- `toml`
```
[`--help`](#prek-init--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-init--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-install`](#prek-init--no-install) : Do not install Git hook shims
[`--no-progress`](#prek-init--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-init--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-init--refresh) : Refresh all cached data
[`--verbose`](#prek-init--verbose), `-v` : Use verbose output
[`--version`](#prek-init--version), `-V` : Display the prek version
## prek install
Install prek Git hook shims.
The effective hooks directory defaults to `.git/hooks/`, but repo-local or worktree-local `core.hooksPath` is honored when set.
The Git shims installed by this command are determined by `--hook-type` or `default_install_hook_types` in the config file, falling back to `pre-commit` when neither is set.
A hook's `stages` field does not affect which Git shims this command installs.
### Usage
```text
prek install [OPTIONS] [HOOK|PROJECT]...
```
### Arguments
[`HOOK|PROJECT`](#prek-install--includes) : Include the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Run all hooks with the specified ID across all projects
- `project-path/`: Run all hooks from the specified project
- `project-path:hook-id`: Run only the specified hook from the specified project
Can be specified multiple times to select multiple hooks/projects.
```
### Options
[`--allow-missing-config`](#prek-install--allow-missing-config) : Allow a missing configuration file
[`--cd`](#prek-install--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-install--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-install--config), `-c` *config* : Path to alternate config file
[`--force`](#prek-install--force), `--overwrite`, `-f` : Force installation and overwrite existing Git shims.
```
If `core.hooksPath` is configured outside this repository, install the shims into this repository's default hooks directory.
```
[`--git-dir`](#prek-install--git-dir) *git-dir* : Install Git shims into the `hooks` subdirectory of the given git directory (`/hooks/`).
```
When this flag is used, `prek install` bypasses the safety check that normally refuses to install shims while `core.hooksPath` is configured outside the repo. It only writes shims to `/hooks`; Git will keep using `core.hooksPath` until that config changes.
```
[`--help`](#prek-install--help), `-h` : Display the concise help for this command
[`--hook-type`](#prek-install--hook-type), `-t` *hook-type* : Which Git shim(s) to install.
```
Specifies which Git hook type(s) you want to install shims for. Can be specified multiple times to install shims for multiple hook types.
If not specified, uses `default_install_hook_types` from the config file, or defaults to `pre-commit` if that is also not set.
Note: This is different from a hook's `stages` parameter in the config file, which declares which stages a hook *can* run in.
Possible values:
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--log-file`](#prek-install--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-install--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--prepare-hooks`](#prek-install--prepare-hooks), `--install-hooks` : Also prepare environments for all hooks used in the config file
[`--quiet`](#prek-install--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-install--refresh) : Refresh all cached data
[`--skip`](#prek-install--skip) *hook|project* : Skip the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Skip all hooks with the specified ID across all projects
- `project-path/`: Skip all hooks from the specified project
- `project-path:hook-id`: Skip only the specified hook from the specified project
Can be specified multiple times. Also accepts `PREK_SKIP` or `SKIP` environment variables (comma-delimited).
```
[`--verbose`](#prek-install--verbose), `-v` : Use verbose output
[`--version`](#prek-install--version), `-V` : Display the prek version
## prek prepare-hooks
Prepare environments for configured hooks.
This command does not install Git shims. To install the Git shims along with the hook environments in one command, use `prek install --prepare-hooks`.
### Usage
```text
prek prepare-hooks [OPTIONS] [HOOK|PROJECT]...
```
### Arguments
[`HOOK|PROJECT`](#prek-prepare-hooks--includes) : Include the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Run all hooks with the specified ID across all projects
- `project-path/`: Run all hooks from the specified project
- `project-path:hook-id`: Run only the specified hook from the specified project
Can be specified multiple times to select multiple hooks/projects.
```
### Options
[`--cd`](#prek-prepare-hooks--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-prepare-hooks--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-prepare-hooks--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-prepare-hooks--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-prepare-hooks--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-prepare-hooks--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-prepare-hooks--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-prepare-hooks--refresh) : Refresh all cached data
[`--skip`](#prek-prepare-hooks--skip) *hook|project* : Skip the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Skip all hooks with the specified ID across all projects
- `project-path/`: Skip all hooks from the specified project
- `project-path:hook-id`: Skip only the specified hook from the specified project
Can be specified multiple times. Also accepts `PREK_SKIP` or `SKIP` environment variables (comma-delimited).
```
[`--verbose`](#prek-prepare-hooks--verbose), `-v` : Use verbose output
[`--version`](#prek-prepare-hooks--version), `-V` : Display the prek version
## prek run
Run configured hooks
### Usage
```text
prek run [OPTIONS] [HOOK|PROJECT]...
```
### Arguments
[`HOOK|PROJECT`](#prek-run--includes) : Include the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Run all hooks with the specified ID across all projects
- `project-path/`: Run all hooks from the specified project
- `project-path:hook-id`: Run only the specified hook from the specified project
Can be specified multiple times to select multiple hooks/projects.
```
### Options
[`--all-files`](#prek-run--all-files), `-a` : Run hooks on all tracked files in the repository
[`--cd`](#prek-run--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-run--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-run--config), `-c` *config* : Path to alternate config file
[`--directory`](#prek-run--directory), `-d` *dir* : Run hooks on tracked files under the specified directory.
```
Paths are resolved relative to the current working directory after applying `--cd`. This option can be repeated and combined with `--files` and `--glob`.
```
[`--dry-run`](#prek-run--dry-run) : Do not run the hooks, but print the hooks that would have been run
[`--fail-fast`](#prek-run--fail-fast) : Stop running hooks after the first failure
[`--files`](#prek-run--files) *files* : Run hooks on the specified file paths.
```
Paths are resolved relative to the current working directory after applying `--cd`. They may be tracked or untracked. This option accepts multiple paths and can be combined with `--glob` and `--directory`.
```
[`--from-ref`](#prek-run--from-ref), `--source`, `-s` *from-ref* : The original ref in a `...` diff expression. Files changed in this diff will be run through the hooks
[`--glob`](#prek-run--glob) *pattern* : Run hooks on tracked files matching the specified glob pattern.
```
Patterns are matched against paths relative to the current working directory after applying `--cd`. Quote patterns to prevent shell expansion. This option can be repeated and combined with `--files` and `--directory`.
```
[`--group`](#prek-run--group) *group* : Run hooks belonging to the specified group.
```
Can be specified multiple times; a hook may match any specified group. When combined with `--require-group`, both filters must match. `@ungrouped` matches hooks without groups.
```
[`--help`](#prek-run--help), `-h` : Display the concise help for this command
[`--hide-status`](#prek-run--hide-status) *status* : Hide hook reports with the specified final status.
```
Can be specified multiple times or as a comma-separated list. This does not change hook execution or exit codes.
Possible values:
- `passed`
- `failed`
- `skipped`
```
[`--last-commit`](#prek-run--last-commit) : Run hooks against the last commit. Equivalent to `--from-ref HEAD~1 --to-ref HEAD`
[`--log-file`](#prek-run--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-group`](#prek-run--no-group) *group* : Do not run hooks belonging to the specified group.
```
Can be specified multiple times. Exclusion wins over inclusion. The special selector `@ungrouped` is also supported.
```
[`--no-progress`](#prek-run--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-run--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-run--refresh) : Refresh all cached data
[`--require-group`](#prek-run--require-group) *group* : Run hooks belonging to every specified group.
```
Can be specified multiple times; a hook must match every specified group. When combined with `--group`, it must also match at least one `--group`. `--no-group` excludes matching hooks regardless of argument order.
For example, `--require-group fast --group format --group lint-only` selects hooks in `fast` and either `format` or `lint-only`. The special selector `@ungrouped` is also supported.
```
[`--show-diff-on-failure`](#prek-run--show-diff-on-failure) : When hooks fail, run `git diff` directly afterward
[`--skip`](#prek-run--skip) *hook|project* : Skip the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Skip all hooks with the specified ID across all projects
- `project-path/`: Skip all hooks from the specified project
- `project-path:hook-id`: Skip only the specified hook from the specified project
Can be specified multiple times. Also accepts `PREK_SKIP` or `SKIP` environment variables (comma-delimited).
```
[`--stage`](#prek-run--stage), `--hook-stage` *stage* : The stage during which the hook is fired.
```
When specified, only hooks configured for that stage (for example `manual`, `pre-commit`, or `pre-push`) will run. When not specified and no group filter is active, this command starts with hooks eligible for `pre-commit`. If no hook is selected and the command named hook IDs, those same IDs are matched again against hooks configured for `manual`. With `--group`, `--require-group`, or `--no-group`, omitting the stage lets hooks from any configured stage match, using the default file input mode; hooks that only run at `commit-msg` or `prepare-commit-msg` are ignored.
Possible values:
- `manual`
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--to-ref`](#prek-run--to-ref), `--origin`, `-o` *to-ref* : The destination ref in a `from_ref...to_ref` diff expression. Defaults to `HEAD` if `from_ref` is specified
[`--verbose`](#prek-run--verbose), `-v` : Use verbose output
[`--version`](#prek-run--version), `-V` : Display the prek version
## prek exec
Run a command in the environment prepared for a configured hook.
The selector must resolve to exactly one hook. Its environment is prepared first if necessary, including its toolchain, dependencies, and environment variables.
Everything after `--` replaces the hook's configured `entry` and `args`. This command does not select files, schedule other hooks, or stash changes. The child process runs in the current working directory after `--cd`, inherits standard input, output, and error, and returns its exit status.
The `docker`, `docker_image`, `fail`, `julia`, and `pygrep` languages are unsupported. Builtin and meta hooks are also unsupported.
### Usage
```text
prek exec [OPTIONS] -- ...
```
### Arguments
[`HOOK`](#prek-exec--selector) : Hook whose execution environment should be used.
```
Supports `hook-id` and `project-path:hook-id` selectors and must resolve to exactly one configured hook.
```
[`COMMAND`](#prek-exec--command) : Command and arguments to execute
### Options
[`--cd`](#prek-exec--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-exec--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-exec--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-exec--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-exec--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-exec--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-exec--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-exec--refresh) : Refresh all cached data
[`--verbose`](#prek-exec--verbose), `-v` : Use verbose output
[`--version`](#prek-exec--version), `-V` : Display the prek version
## prek list
List configured hooks
### Usage
```text
prek list [OPTIONS] [HOOK|PROJECT]...
```
### Arguments
[`HOOK|PROJECT`](#prek-list--includes) : Include the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Run all hooks with the specified ID across all projects
- `project-path/`: Run all hooks from the specified project
- `project-path:hook-id`: Run only the specified hook from the specified project
Can be specified multiple times to select multiple hooks/projects.
```
### Options
[`--cd`](#prek-list--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-list--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-list--config), `-c` *config* : Path to alternate config file
[`--group`](#prek-list--group) *group* : Show hooks belonging to the specified group.
```
Can be specified multiple times. `@ungrouped` matches hooks without groups.
```
[`--help`](#prek-list--help), `-h` : Display the concise help for this command
[`--hook-stage`](#prek-list--hook-stage) *hook-stage* : Show only hooks that has the specified stage
```
Possible values:
- `manual`
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--language`](#prek-list--language) *language* : Show only hooks that are implemented in the specified language
```
Possible values:
- `bun`
- `conda`
- `coursier`
- `dart`
- `deno`
- `docker`
- `docker-image`
- `dotnet`
- `fail`
- `golang`
- `haskell`
- `julia`
- `lua`
- `mise`
- `node`
- `perl`
- `php`
- `pygrep`
- `python`
- `r`
- `ruby`
- `rust`
- `script`
- `swift`
- `system`
```
[`--log-file`](#prek-list--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-group`](#prek-list--no-group) *group* : Do not show hooks belonging to the specified group.
```
Can be specified multiple times. Exclusion wins over inclusion. The special selector `@ungrouped` is also supported.
```
[`--no-progress`](#prek-list--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--output-format`](#prek-list--output-format) *output-format* : The output format
```
[default: text]
Possible values:
- `text`
- `json`
```
[`--quiet`](#prek-list--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-list--refresh) : Refresh all cached data
[`--require-group`](#prek-list--require-group) *group* : Show hooks belonging to every specified group.
```
Can be specified multiple times. Composes with `--group` and `--no-group`. The special selector `@ungrouped` is also supported.
```
[`--skip`](#prek-list--skip) *hook|project* : Skip the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Skip all hooks with the specified ID across all projects
- `project-path/`: Skip all hooks from the specified project
- `project-path:hook-id`: Skip only the specified hook from the specified project
Can be specified multiple times. Also accepts `PREK_SKIP` or `SKIP` environment variables (comma-delimited).
```
[`--verbose`](#prek-list--verbose), `-v` : Use verbose output
[`--version`](#prek-list--version), `-V` : Display the prek version
## prek uninstall
Uninstall prek Git hook shims
### Usage
```text
prek uninstall [OPTIONS]
```
### Options
[`--all`](#prek-uninstall--all) : Uninstall all prek-managed Git shims.
```
Scans the hooks directory and removes every hook managed by prek, regardless of hook type.
```
[`--cd`](#prek-uninstall--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-uninstall--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-uninstall--config), `-c` *config* : Path to alternate config file
[`--git-dir`](#prek-uninstall--git-dir) *git-dir* : Uninstall Git shims from the `hooks` subdirectory of the given git directory (`/hooks/`).
```
When this flag is used, `prek uninstall` bypasses the safety check that normally refuses to modify shims while `core.hooksPath` is configured outside the repo. It only removes shims from `/hooks`; Git may still use the configured `core.hooksPath` until that config changes.
```
[`--help`](#prek-uninstall--help), `-h` : Display the concise help for this command
[`--hook-type`](#prek-uninstall--hook-type), `-t` *hook-type* : Which Git shim(s) to uninstall.
```
Specifies which Git hook type(s) you want to uninstall shims for. Can be specified multiple times to uninstall shims for multiple hook types.
If not specified, uses `default_install_hook_types` from the config file, or defaults to `pre-commit` if that is also not set. Use `--all` to remove all prek-managed hooks.
Possible values:
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--log-file`](#prek-uninstall--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-uninstall--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-uninstall--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-uninstall--refresh) : Refresh all cached data
[`--verbose`](#prek-uninstall--verbose), `-v` : Use verbose output
[`--version`](#prek-uninstall--version), `-V` : Display the prek version
## prek validate-config
Validate prek configuration files
### Usage
```text
prek validate-config [OPTIONS] [CONFIG]...
```
### Arguments
[`CONFIG`](#prek-validate-config--configs) : The path to the configuration file
### Options
[`--cd`](#prek-validate-config--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-validate-config--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-validate-config--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-validate-config--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-validate-config--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-validate-config--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-validate-config--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-validate-config--refresh) : Refresh all cached data
[`--verbose`](#prek-validate-config--verbose), `-v` : Use verbose output
[`--version`](#prek-validate-config--version), `-V` : Display the prek version
## prek validate-manifest
Validate pre-commit hook manifests (`.pre-commit-hooks.yaml`)
### Usage
```text
prek validate-manifest [OPTIONS] [MANIFEST]...
```
### Arguments
[`MANIFEST`](#prek-validate-manifest--manifests) : The path to the manifest file
### Options
[`--cd`](#prek-validate-manifest--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-validate-manifest--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-validate-manifest--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-validate-manifest--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-validate-manifest--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-validate-manifest--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-validate-manifest--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-validate-manifest--refresh) : Refresh all cached data
[`--verbose`](#prek-validate-manifest--verbose), `-v` : Use verbose output
[`--version`](#prek-validate-manifest--version), `-V` : Display the prek version
## prek update
Update configured repositories
### Usage
```text
prek update [OPTIONS]
```
### Options
[`--bleeding-edge`](#prek-update--bleeding-edge) : Update to the bleeding edge of the default branch instead of the latest tagged version
[`--cd`](#prek-update--cd), `-C` *dir* : Change to directory before running
[`--check`](#prek-update--check) : Alias of `--dry-run --exit-code`
[`--color`](#prek-update--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-update--config), `-c` *config* : Path to alternate config file
[`--cooldown-days`](#prek-update--cooldown-days) *days* : Minimum release age (in days) required for a version to be eligible.
```
The age is computed from the tag creation timestamp for annotated tags, or from the tagged commit timestamp for lightweight tags. If the current `rev` is newer than the latest cooldown-eligible tag, `prek update` keeps the current `rev` instead of downgrading it. Defaults to `update.cooldown_days` in the project or global config, or `0` when unset. Valid values are `0` through `255`; `0` disables this check.
```
[`--dry-run`](#prek-update--dry-run) : Do not write changes to the config file, only display what would be changed
[`--exclude-repo`](#prek-update--exclude-repo) *repo* : Do not update this repository. This option may be specified multiple times
[`--exclude-tag`](#prek-update--exclude-tag) *pattern* : Ignore tags matching this glob pattern. This option may be specified multiple times. Defaults to `update.exclude_tags` in the project or global config when unset.
```
For example, use `--exclude-tag nightly` to skip a moving tag, or `--exclude-tag '*-{alpha,beta,rc}*'` to skip common prerelease tags.
```
[`--exit-code`](#prek-update--exit-code) : Exit with status 1 if updates are available
[`--freeze`](#prek-update--freeze) : Store "frozen" hashes in `rev` instead of tag names. Defaults to `update.freeze` in the project or global config, or `false` when unset
[`--help`](#prek-update--help), `-h` : Display the concise help for this command
[`--include-tag`](#prek-update--include-tag) *pattern* : Only consider tags matching this glob pattern. This option may be specified multiple times. Defaults to `update.include_tags` in the project or global config when unset.
```
For example, use `--include-tag 'v*'` to only consider version tags and ignore tags such as `nightly`.
```
[`--jobs`](#prek-update--jobs), `-j` *jobs* : Number of threads to use
```
[default: 0]
```
[`--log-file`](#prek-update--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-update--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-update--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-update--refresh) : Refresh all cached data
[`--repo`](#prek-update--repo) *repo* : Only update this repository. This option may be specified multiple times
[`--repo-exclude-tag`](#prek-update--repo-exclude-tag) *repo=pattern* : Ignore tags matching this glob pattern for a repository (`=`). This option may be specified multiple times. Adds to the effective `update` exclude filters for the named repository.
```
Repo-specific exclude filters are added to global `--exclude-tag` filters; matching either filter excludes the tag for that repository.
For example, use `--repo-exclude-tag https://github.com/example/repo=nightly` or `--repo-exclude-tag https://github.com/example/repo=*-rc*` to skip nightly or prerelease tags for one repository.
```
[`--repo-include-tag`](#prek-update--repo-include-tag) *repo=pattern* : Only consider tags matching this glob pattern for a repository (`=`). This option may be specified multiple times. Overrides the effective include filters for the named repository.
```
When set for a repository, this overrides any global `--include-tag` filters for that repository.
For example, use `--repo-include-tag https://github.com/example/repo=v*` to only consider version tags for one repository.
```
[`--verbose`](#prek-update--verbose), `-v` : Use verbose output
[`--version`](#prek-update--version), `-V` : Display the prek version
## prek cache
Manage the prek cache
### Usage
```text
prek cache [OPTIONS]
```
### Commands
[`prek cache dir`](#prek-cache-dir) : Show the location of the prek cache
[`prek cache gc`](#prek-cache-gc) : Remove unused cached repositories, hook environments, and other data
[`prek cache clean`](#prek-cache-clean) : Remove all prek cached data
[`prek cache size`](#prek-cache-size) : Show the size of the prek cache
### prek cache dir
Show the location of the prek cache
### Usage
```text
prek cache dir [OPTIONS]
```
### Options
[`--cd`](#prek-cache-dir--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-cache-dir--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-cache-dir--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-cache-dir--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-cache-dir--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-cache-dir--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-cache-dir--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-cache-dir--refresh) : Refresh all cached data
[`--verbose`](#prek-cache-dir--verbose), `-v` : Use verbose output
[`--version`](#prek-cache-dir--version), `-V` : Display the prek version
### prek cache gc
Remove unused cached repositories, hook environments, and other data
### Usage
```text
prek cache gc [OPTIONS]
```
### Options
[`--cd`](#prek-cache-gc--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-cache-gc--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-cache-gc--config), `-c` *config* : Path to alternate config file
[`--dry-run`](#prek-cache-gc--dry-run) : Print what would be removed, but do not delete anything
[`--help`](#prek-cache-gc--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-cache-gc--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-cache-gc--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-cache-gc--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-cache-gc--refresh) : Refresh all cached data
[`--verbose`](#prek-cache-gc--verbose), `-v` : Use verbose output
[`--version`](#prek-cache-gc--version), `-V` : Display the prek version
### prek cache clean
Remove all prek cached data
### Usage
```text
prek cache clean [OPTIONS]
```
### Options
[`--cd`](#prek-cache-clean--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-cache-clean--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-cache-clean--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-cache-clean--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-cache-clean--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-cache-clean--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-cache-clean--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-cache-clean--refresh) : Refresh all cached data
[`--verbose`](#prek-cache-clean--verbose), `-v` : Use verbose output
[`--version`](#prek-cache-clean--version), `-V` : Display the prek version
### prek cache size
Show the size of the prek cache
### Usage
```text
prek cache size [OPTIONS]
```
### Options
[`--cd`](#prek-cache-size--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-cache-size--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-cache-size--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-cache-size--help), `-h` : Display the concise help for this command
[`--human`](#prek-cache-size--human), `--human-readable`, `-H` : Display the cache size in human-readable format (e.g., `1.2GiB` instead of raw bytes)
[`--log-file`](#prek-cache-size--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-cache-size--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--output-format`](#prek-cache-size--output-format) *output-format* : Select the output format
```
[default: auto]
Possible values:
- `auto`: Display a human-readable size in terminals and raw bytes otherwise
- `human`: Display the cache size in a human-readable format
- `machine`: Display the cache size in raw bytes
```
[`--quiet`](#prek-cache-size--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-cache-size--refresh) : Refresh all cached data
[`--verbose`](#prek-cache-size--verbose), `-v` : Use verbose output
[`--version`](#prek-cache-size--version), `-V` : Display the prek version
## prek try-repo
Try hooks from a repository
### Usage
```text
prek try-repo [OPTIONS] [HOOK|PROJECT]...
```
### Arguments
[`REPO`](#prek-try-repo--repo) : Repository to source hooks from
[`HOOK|PROJECT`](#prek-try-repo--includes) : Include the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Run all hooks with the specified ID across all projects
- `project-path/`: Run all hooks from the specified project
- `project-path:hook-id`: Run only the specified hook from the specified project
Can be specified multiple times to select multiple hooks/projects.
```
### Options
[`--all-files`](#prek-try-repo--all-files), `-a` : Run hooks on all tracked files in the repository
[`--cd`](#prek-try-repo--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-try-repo--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-try-repo--config), `-c` *config* : Path to alternate config file
[`--directory`](#prek-try-repo--directory), `-d` *dir* : Run hooks on tracked files under the specified directory.
```
Paths are resolved relative to the current working directory after applying `--cd`. This option can be repeated and combined with `--files` and `--glob`.
```
[`--dry-run`](#prek-try-repo--dry-run) : Do not run the hooks, but print the hooks that would have been run
[`--fail-fast`](#prek-try-repo--fail-fast) : Stop running hooks after the first failure
[`--files`](#prek-try-repo--files) *files* : Run hooks on the specified file paths.
```
Paths are resolved relative to the current working directory after applying `--cd`. They may be tracked or untracked. This option accepts multiple paths and can be combined with `--glob` and `--directory`.
```
[`--from-ref`](#prek-try-repo--from-ref), `--source`, `-s` *from-ref* : The original ref in a `...` diff expression. Files changed in this diff will be run through the hooks
[`--glob`](#prek-try-repo--glob) *pattern* : Run hooks on tracked files matching the specified glob pattern.
```
Patterns are matched against paths relative to the current working directory after applying `--cd`. Quote patterns to prevent shell expansion. This option can be repeated and combined with `--files` and `--directory`.
```
[`--help`](#prek-try-repo--help), `-h` : Display the concise help for this command
[`--hide-status`](#prek-try-repo--hide-status) *status* : Hide hook reports with the specified final status.
```
Can be specified multiple times or as a comma-separated list. This does not change hook execution or exit codes.
Possible values:
- `passed`
- `failed`
- `skipped`
```
[`--last-commit`](#prek-try-repo--last-commit) : Run hooks against the last commit. Equivalent to `--from-ref HEAD~1 --to-ref HEAD`
[`--log-file`](#prek-try-repo--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-try-repo--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-try-repo--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-try-repo--refresh) : Refresh all cached data
[`--rev`](#prek-try-repo--rev), `--ref` *rev* : Manually select a rev to run against, otherwise the `HEAD` revision will be used
[`--show-diff-on-failure`](#prek-try-repo--show-diff-on-failure) : When hooks fail, run `git diff` directly afterward
[`--skip`](#prek-try-repo--skip) *hook|project* : Skip the specified hooks or projects.
```
Supports flexible selector syntax:
- `hook-id`: Skip all hooks with the specified ID across all projects
- `project-path/`: Skip all hooks from the specified project
- `project-path:hook-id`: Skip only the specified hook from the specified project
Can be specified multiple times. Also accepts `PREK_SKIP` or `SKIP` environment variables (comma-delimited).
```
[`--stage`](#prek-try-repo--stage), `--hook-stage` *stage* : The stage during which the hook is fired.
```
When specified, only hooks configured for that stage (for example `manual`, `pre-commit`, or `pre-push`) will run. When not specified, this command starts with hooks eligible for `pre-commit`. If no hook is selected and the command named hook IDs, those same IDs are matched again against hooks configured for `manual`.
Possible values:
- `manual`
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--to-ref`](#prek-try-repo--to-ref), `--origin`, `-o` *to-ref* : The destination ref in a `from_ref...to_ref` diff expression. Defaults to `HEAD` if `from_ref` is specified
[`--verbose`](#prek-try-repo--verbose), `-v` : Use verbose output
[`--version`](#prek-try-repo--version), `-V` : Display the prek version
## prek util
Run utility commands
### Usage
```text
prek util [OPTIONS]
```
### Commands
[`prek util identify`](#prek-util-identify) : Show file identification tags
[`prek util list-builtins`](#prek-util-list-builtins) : List all built-in hooks bundled with prek
[`prek util init-template-dir`](#prek-util-init-template-dir) : Install Git shims in a directory intended for use with `git config init.templateDir`
[`prek util yaml-to-toml`](#prek-util-yaml-to-toml) : Convert a YAML configuration file to prek.toml
### prek util identify
Show file identification tags
### Usage
```text
prek util identify [OPTIONS] [PATH]...
```
### Arguments
[`PATH`](#prek-util-identify--paths) : The path(s) to the file(s) to identify
### Options
[`--cd`](#prek-util-identify--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-util-identify--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-util-identify--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-util-identify--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-util-identify--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-util-identify--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--output-format`](#prek-util-identify--output-format) *output-format* : The output format
```
[default: text]
Possible values:
- `text`
- `json`
```
[`--quiet`](#prek-util-identify--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-util-identify--refresh) : Refresh all cached data
[`--verbose`](#prek-util-identify--verbose), `-v` : Use verbose output
[`--version`](#prek-util-identify--version), `-V` : Display the prek version
### prek util list-builtins
List all built-in hooks bundled with prek
### Usage
```text
prek util list-builtins [OPTIONS]
```
### Options
[`--cd`](#prek-util-list-builtins--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-util-list-builtins--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-util-list-builtins--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-util-list-builtins--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-util-list-builtins--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-util-list-builtins--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--output-format`](#prek-util-list-builtins--output-format) *output-format* : The output format
```
[default: text]
Possible values:
- `text`
- `json`
```
[`--quiet`](#prek-util-list-builtins--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-util-list-builtins--refresh) : Refresh all cached data
[`--verbose`](#prek-util-list-builtins--verbose), `-v` : Use verbose output
[`--version`](#prek-util-list-builtins--version), `-V` : Display the prek version
### prek util init-template-dir
Install Git shims in a directory intended for use with `git config init.templateDir`
### Usage
```text
prek util init-template-dir [OPTIONS]
```
### Arguments
[`DIRECTORY`](#prek-util-init-template-dir--directory) : The directory in which to write the Git shim
### Options
[`--cd`](#prek-util-init-template-dir--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-util-init-template-dir--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-util-init-template-dir--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-util-init-template-dir--help), `-h` : Display the concise help for this command
[`--hook-type`](#prek-util-init-template-dir--hook-type), `-t` *hook-type* : Which Git shim(s) to install.
```
Specifies which Git hook type(s) you want to install shims for. Can be specified multiple times to install shims for multiple hook types.
If not specified, uses `default_install_hook_types` from the config file, or defaults to `pre-commit` if that is also not set.
Possible values:
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
```
[`--log-file`](#prek-util-init-template-dir--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-allow-missing-config`](#prek-util-init-template-dir--no-allow-missing-config) : Assume cloned repos should have a `pre-commit` config
[`--no-progress`](#prek-util-init-template-dir--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-util-init-template-dir--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-util-init-template-dir--refresh) : Refresh all cached data
[`--verbose`](#prek-util-init-template-dir--verbose), `-v` : Use verbose output
[`--version`](#prek-util-init-template-dir--version), `-V` : Display the prek version
### prek util yaml-to-toml
Convert a YAML configuration file to prek.toml
### Usage
```text
prek util yaml-to-toml [OPTIONS] [CONFIG]
```
### Arguments
[`CONFIG`](#prek-util-yaml-to-toml--input) : The YAML configuration file to convert. If omitted, discovers `.pre-commit-config.yaml` or `.pre-commit-config.yml` in the current directory
### Options
[`--cd`](#prek-util-yaml-to-toml--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-util-yaml-to-toml--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-util-yaml-to-toml--config), `-c` *config* : Path to alternate config file
[`--force`](#prek-util-yaml-to-toml--force) : Overwrite the output file if it already exists
[`--help`](#prek-util-yaml-to-toml--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-util-yaml-to-toml--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-util-yaml-to-toml--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--output`](#prek-util-yaml-to-toml--output), `-o` *output* : Path to write the generated prek.toml file. Defaults to `prek.toml` in the same directory as the input file
[`--quiet`](#prek-util-yaml-to-toml--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-util-yaml-to-toml--refresh) : Refresh all cached data
[`--verbose`](#prek-util-yaml-to-toml--verbose), `-v` : Use verbose output
[`--version`](#prek-util-yaml-to-toml--version), `-V` : Display the prek version
## prek self
Manage the prek installation
### Usage
```text
prek self [OPTIONS]
```
### Commands
[`prek self update`](#prek-self-update) : Update prek
### prek self update
Update prek
### Usage
```text
prek self update [OPTIONS] [TARGET_VERSION]
```
### Arguments
[`TARGET_VERSION`](#prek-self-update--target_version) : Update to the specified version. If not provided, prek will update to the latest version
### Options
[`--cd`](#prek-self-update--cd), `-C` *dir* : Change to directory before running
[`--color`](#prek-self-update--color) *color* : Whether to use color in output
```
May also be set with the `PREK_COLOR` environment variable.
[default: auto]
Possible values:
- `auto`: Enables colored output only when the output is going to a terminal or TTY with support
- `always`: Enables colored output regardless of the detected environment
- `never`: Disables colored output
```
[`--config`](#prek-self-update--config), `-c` *config* : Path to alternate config file
[`--help`](#prek-self-update--help), `-h` : Display the concise help for this command
[`--log-file`](#prek-self-update--log-file) *log-file* : Write trace logs to the specified file. If not specified, trace logs will be written to `$PREK_HOME/prek.log`
[`--no-progress`](#prek-self-update--no-progress) : Hide all progress outputs.
```
For example, spinners or progress bars.
```
[`--quiet`](#prek-self-update--quiet), `-q` : Use quiet output.
```
Repeating this option, e.g., `-qq`, will enable a silent mode in which prek will write no output to stdout.
May also be set with the `PREK_QUIET` environment variable.
```
[`--refresh`](#prek-self-update--refresh) : Refresh all cached data
[`--token`](#prek-self-update--token) *token* : A GitHub token for authentication. A token is not required but can be used to reduce the chance of encountering rate limits
```
May also be set with the `GITHUB_TOKEN` environment variable.
```
[`--verbose`](#prek-self-update--verbose), `-v` : Use verbose output
[`--version`](#prek-self-update--version), `-V` : Display the prek version
## Configuration Reference
# Configuration Reference
This page documents the configuration keys that `prek` understands.
## Global config file
`prek` reads an optional user-level global config from:
- Linux and macOS: `~/.config/prek/prek.toml` (or `$XDG_CONFIG_HOME/prek/prek.toml` when `XDG_CONFIG_HOME` is set)
- Windows: `%APPDATA%\prek\prek.toml`
This file stores user-level `prek` settings and does not define project hooks.
### Global `update`
User-level defaults for [`prek update`](../cli/#prek-update):
| Key | Type | Default | CLI override |
| ---------------------- | ----------------------------------- | ------- | ------------------------------------------------------------------- |
| `update.cooldown_days` | integer days, `0` to `255` | `0` | [`--cooldown-days `](../cli/#prek-update) |
| `update.freeze` | boolean | `false` | [`--freeze`](../cli/#prek-update--freeze), which forces freezing on |
| `update.include_tags` | glob string or list of glob strings | empty | [`--include-tag`](../cli/#prek-update--include-tag) |
| `update.exclude_tags` | glob string or list of glob strings | empty | [`--exclude-tag`](../cli/#prek-update--exclude-tag) |
```toml
[update]
cooldown_days = 7
freeze = true
include_tags = "v*"
exclude_tags = ["*-{alpha,beta,rc}*"]
```
Each field is resolved independently with this precedence:
1. the corresponding CLI option, when provided
1. [project `update`](#update)
1. user-level global config
1. the default shown above
The cooldown age is computed from the tag creation timestamp for annotated tags, or from the tagged commit timestamp for lightweight tags. A value of `0` disables the cooldown check.
Cooldowns never downgrade
If the current `rev` is newer than the latest cooldown-eligible tag, [`prek update`](../cli/#prek-update) keeps the current `rev` instead of downgrading it.
## Extension keys (`x-`)
Any key starting with `x-` (a lowercase `x` followed by a hyphen) is silently ignored by `prek` at any level of the configuration. This supports custom metadata without triggering unexpected key warnings.
## Top-level keys
### `repos` (required)
A list of hook repositories.
Each entry is one of:
- a remote repository (typically a git URL)
- `repo: local` for hooks defined directly in your repository
- `repo: meta` for built-in meta hooks
- `repo: builtin` for `prek`'s built-in fast hooks
See [Repo entries](#repo-entries).
### `priorities`
prek-only
Priority aliases are a `prek` extension and do not exist in upstream `pre-commit`.
An optional mapping that declares configuration-local aliases for non-negative integer priorities. A hook can use one of these aliases in its [`priority`](#priority) field instead of repeating the integer.
- Type: mapping from string to non-negative integer
- Default: empty mapping
- Scope: the current project configuration only
- Aliases: non-empty, case-sensitive strings without whitespace
Different aliases may map to the same integer. Unused declarations are allowed. Referencing an alias that is not declared in the current configuration is an error.
### `files`
Global *include* regex applied before hook-level filtering.
- Type: regex string (default, pre-commit compatible) **or** a prek-only glob pattern mapping
- Default: no global include filter
This is usually used to narrow down the universe of files in large repositories.
What path is matched? (workspace + nested projects)
`files` (and `exclude`) are matched against the file path **relative to the project root** — i.e. the directory containing the configuration file.
- For the root project, this is the workspace root.
- For a nested project, this is the nested project directory.
Example (workspace mode):
- Root project config: `./.pre-commit-config.yaml`
- Nested project config: `./nested/.pre-commit-config.yaml`
For a file at `nested/excluded_by_project`:
- Root project sees the path as `nested/excluded_by_project`
- Nested project sees the path as `excluded_by_project`
This matters most for anchored patterns like `^...$`.
Regex matching
When `files` / `exclude` are regex strings, they are matched with *search* semantics (the pattern can match anywhere in the path). Use `^` to anchor at the beginning and `$` at the end.
`prek` uses the Rust [`fancy-regex`](https://github.com/fancy-regex/fancy-regex) engine. Most typical patterns are portable to upstream `pre-commit`, but very advanced regex features may differ from Python’s `re`.
prek-only globs
In addition to regex strings, `prek` supports glob patterns via:
- `files: { glob: "..." }` (single glob)
- `files: { glob: ["...", "..."] }` (glob list)
This is a `prek` extension. Upstream `pre-commit` expects regex strings here.
For more information on the glob syntax, refer to the [globset documentation](https://docs.rs/globset/latest/globset/#syntax).
Examples:
```toml
# Regex (portable to pre-commit)
files = "\\.rs$"
# Glob (prek-only)
files = { glob = "src/**/*.rs" }
# Glob list (prek-only; matches if any glob matches)
files = { glob = ["src/**/*.rs", "crates/**/src/**/*.rs"] }
```
```yaml
# Regex (portable to pre-commit)
files: "\\.rs$"
# Glob (prek-only)
files:
glob: "src/**/*.rs"
# Glob list (prek-only; matches if any glob matches)
files:
glob:
- "src/**/*.rs"
- "crates/**/src/**/*.rs"
```
### `exclude`
Global *exclude* regex applied before hook-level filtering.
- Type: regex string (default, pre-commit compatible) **or** a prek-only glob pattern mapping
- Default: no global exclude filter
`exclude` is useful for generated folders, vendored code, or build outputs.
What path is matched?
Same as [`files`](#top-level-files): the pattern is evaluated against the file path **relative to the project root** (the directory containing the config).
prek-only globs
Like [`files`](#top-level-files), `exclude` supports `glob` (single glob or glob list) as a `prek` extension. For glob syntax details, see the [globset documentation](https://docs.rs/globset/latest/globset/#syntax).
Examples:
```toml
# Regex (portable to pre-commit)
exclude = "^target/"
# Glob (prek-only)
exclude = { glob = "target/**" }
# Glob list (prek-only)
exclude = { glob = ["target/**", "dist/**"] }
```
```yaml
# Regex (portable to pre-commit)
exclude: "^target/"
# Glob (prek-only)
exclude:
glob: "target/**"
# Glob list (prek-only)
exclude:
glob:
- "target/**"
- "dist/**"
```
Verbose regex example (useful for long allow/deny lists):
```toml
# `(?x)` enables "verbose" regex mode (whitespace and newlines are ignored).
exclude = """(?x)^(
docs/|
vendor/|
target/
)"""
```
```yaml
# `(?x)` enables "verbose" regex mode (whitespace and newlines are ignored).
exclude: |
(?x)^(
docs/|
vendor/|
target/
)
```
### `fail_fast`
Stop the run after the first failing hook.
- Type: boolean
- Default: `false`
This is a global default; individual hooks can also set `fail_fast`.
### `default_language_version`
Map a language name to the default [`language_version`](#language_version) used by hooks of that language. Each value can be a request string or an options map.
- Type: map
- Default: none (hooks fall back to `language_version: default`)
Example:
```toml
default_language_version.python = "3.12"
default_language_version.node = { request = "20", preference = "only-managed" }
```
```yaml
default_language_version:
python: "3.12"
node:
request: "20"
preference: only-managed
```
`prek` treats [`language_version`](#language_version) as a version request (often a semver-like selector) and may install toolchains automatically. See [Difference from pre-commit](../../diff/).
Defaults are applied field by field. For example, a hook can override only the `request` while retaining the default `preference` for its language.
### `default_stages`
Default [`stages`](#stages) used when a hook does not specify its own.
- Type: list of stage names
- Default: all stages
Allowed values:
- `manual`
- `commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-commit`
- `pre-merge-commit`
- `pre-push`
- `pre-rebase`
- `prepare-commit-msg`
See [Supported Git Hook Stages](#supported-git-hook-stages) for what each value means.
### `default_env`
prek-only
`default_env` is a `prek` extension and may not be recognized by upstream `pre-commit`.
Environment variables to apply when `prek` creates hook environments and runs hooks in this config. If a hook sets the same variable in [`env`](#prek-only-env), the hook-level value wins.
- Type: map of string to string
- Default: none
Example:
```toml
default_env = { UV_PYTHON = "", VIRTUAL_ENV = "" }
```
```yaml
default_env:
UV_PYTHON: ""
VIRTUAL_ENV: ""
```
### `default_install_hook_types`
Default Git shim name(s) installed by [`prek install`](../cli/#prek-install) when you don’t pass `--hook-type`.
- Type: list of `--hook-type` values
- Default: `[pre-commit]`
This controls which Git shims are installed (for example `pre-commit` vs `pre-push`). It is separate from a hook’s [`stages`](#stages), which controls when a particular hook is eligible to run.
Allowed values:
- `pre-commit`
- `pre-push`
- `commit-msg`
- `prepare-commit-msg`
- `post-checkout`
- `post-commit`
- `post-merge`
- `post-rewrite`
- `pre-merge-commit`
- `pre-rebase`
### `update`
prek-only
This top-level key is a `prek` extension and is not recognized by upstream `pre-commit`.
Project settings for [`prek update`](../cli/#prek-update):
| Key | Type | Default or behavior |
| ---------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------ |
| `update.cooldown_days` | integer days, `0` to `255` | Inherited from the global config, or `0`. |
| `update.freeze` | boolean | Inherited from the global config, or `false`. |
| `update.include_tags` | glob string or list of glob strings | Inherited from the global config, or empty. Only consider matching tags. |
| `update.exclude_tags` | glob string or list of glob strings | Inherited from the global config, or empty. Ignore matching tags. |
| `update.repos` | map from repo to tag-filter fields | Override tag filters for a repository whose configured `repo` value exactly matches the map key. |
```toml
[update]
cooldown_days = 7
freeze = false
include_tags = "v*"
exclude_tags = ["*-{alpha,beta,rc}*"]
[update.repos."https://github.com/example/hooks"]
include_tags = ["v1.*", "v2.*"]
[update.repos."https://github.com/lycheeverse/lychee"]
exclude_tags = ["nightly", "*-rc*", "*-dev*"]
```
```yaml
update:
cooldown_days: 7
freeze: false
include_tags: "v*"
exclude_tags: ["*-{alpha,beta,rc}*"]
repos:
"https://github.com/example/hooks":
include_tags: ["v1.*", "v2.*"]
"https://github.com/lycheeverse/lychee":
exclude_tags: ["nightly", "*-rc*", "*-dev*"]
```
Each project-level field overrides the corresponding [global `update`](#global-update) field. Within `update.repos`, `include_tags` and `exclude_tags` are resolved independently: an omitted field inherits the project default, a present field replaces it, and `[]` explicitly clears it. This allows one repository to override only `include_tags` while still inheriting `exclude_tags`.
CLI filters have the highest precedence. `--include-tag` and `--exclude-tag` replace the configured effective defaults; `--repo-include-tag` then replaces the include filters for its named repository, while `--repo-exclude-tag` adds excludes for its named repository.
In workspace mode, `update` is scoped to the project config file that defines it and is not inherited by nested projects. Sub-projects use their own `update`, then the user-level global config, then built-in defaults. Repositories shared by multiple projects are fetched once but evaluated with each project's cooldown, freeze, and tag-filter settings.
### `minimum_prek_version`
prek-only
This key is a `prek` extension. Upstream `pre-commit` uses `minimum_pre_commit_version`, which `prek` intentionally ignores.
Require a minimum `prek` version for this config.
- Type: string (version)
- Default: unset
If the installed `prek` is older than the configured minimum, `prek` exits with an error.
Example:
```toml
minimum_prek_version = "0.2.0"
```
```yaml
minimum_prek_version: "0.2.0"
```
### `orphan`
prek-only
`orphan` is a `prek` workspace-mode feature and is not recognized by upstream `pre-commit`.
Workspace-mode setting to isolate a nested project from parent configs.
- Type: boolean
- Default: `false`
When `orphan: true`, files under this project directory are handled only by this project’s config and are not “seen” by parent projects.
Example:
```toml
orphan = true
[[repos]]
repo = "https://github.com/astral-sh/ruff-pre-commit"
rev = "v0.8.4"
hooks = [{ id = "ruff" }]
```
```yaml
orphan: true
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
```
See [Orphan projects](../workspace/#orphan-projects) for details.
## Repo entries
Each item under `repos:` is a mapping that always contains a `repo:` key.
### Remote repository
Use this for hooks distributed in a separate repository.
Required keys:
- `repo`: repository location (commonly an https git URL)
- `rev`: version to use (tag, branch, or commit SHA)
- `hooks`: list of hook selections
Remote hook definitions live inside the hook repository itself in the `.pre-commit-hooks.yaml` manifest (at the repo root). Your config only selects hooks by `id` and optionally overrides options. See [Authoring Hooks](../../authoring-hooks/) if you maintain a hook repository.
#### `repo`
Where to fetch hooks from.
In most configs this is a git URL. `prek` also recognizes special values documented separately: `local`, `meta`, and `builtin`.
#### `rev`
The revision to use for the remote repository.
Use a full commit SHA when an immutable Git pin is required. Version tags are readable and conventional for releases, but a repository maintainer can move a tag. Branch names are moving targets, so runs may change over time.
#### `hooks`
The list of hooks to enable from that repository.
Each item must at least specify `id`. You can also add hook-level options (filters, args, stages, etc.) to customize behavior.
Example:
```toml
[[repos]]
repo = "https://github.com/astral-sh/ruff-pre-commit"
rev = "v0.8.4"
hooks = [{ id = "ruff", args = ["--fix"] }]
```
```yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
args: [--fix]
```
Notes:
- For reproducibility, prefer a versioned release tag or an immutable commit SHA.
- [`prek update`](../cli/#prek-update) can help update [`rev`](#rev) values.
### `repo: local`
Define hooks inline inside your repository.
Keys:
- `repo`: must be `local`
- `hooks`: list of **local hook definitions** (see [Local hook definition](#local-hook-definition))
Example:
```toml
[[repos]]
repo = "local"
hooks = [
{
id = "cargo-fmt",
name = "cargo fmt",
language = "system",
entry = "cargo fmt",
files = "\\.rs$",
},
]
```
```yaml
repos:
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
language: system
entry: cargo fmt
files: "\\.rs$"
```
### `repo: meta`
Use `pre-commit`-style meta hooks that validate and debug your configuration.
`prek` supports the following meta hook ids:
- `check-hooks-apply`
- `check-useless-excludes`
- `identity`
Restrictions:
- `id` is required.
- `entry` is not allowed.
- `language` (if set) must be `system`.
You may still configure normal hook options such as [`files`](#hook-files-exclude), [`exclude`](#hook-files-exclude), [`stages`](#stages), etc.
Example:
```toml
[[repos]]
repo = "meta"
hooks = [{ id = "check-useless-excludes" }]
```
```yaml
repos:
- repo: meta
hooks:
- id: check-useless-excludes
```
### `repo: builtin`
prek-only
`repo: builtin` is specific to `prek` and is not compatible with upstream `pre-commit`.
Use `prek`’s built-in fast hooks (offline, zero setup).
Restrictions:
- `id` is required.
- `entry` is not allowed.
- `language` (if set) must be `system`.
Example:
```toml
[[repos]]
repo = "builtin"
hooks = [
{ id = "trailing-whitespace" },
{ id = "check-yaml" },
]
```
```yaml
repos:
- repo: builtin
hooks:
- id: trailing-whitespace
- id: check-yaml
```
For available hooks and their arguments, see [Built-in Hooks](../built-in-hooks/). For setup examples and automatic fast-path behavior, see [Built-in Hooks](../../built-in-hooks/).
## Hook entries
Hook items under `repos[*].hooks` have slightly different shapes depending on the repo type.
### Remote hook selection
For a remote repo, the hook entry must include:
- `id` (required): selects the hook from the repository
All other hook keys are optional overrides (for example [`args`](#args), [`files`](#hook-files-exclude), [`exclude`](#hook-files-exclude), [`stages`](#stages), …).
Advanced overrides
`prek` also supports overriding `name`, `entry`, and `language` for remote hooks. This can be useful for experimentation, but it may reduce portability to the original `pre-commit`.
### Local hook definition
For `repo: local`, the hook entry is a full definition and must include:
- `id` (required): stable identifier used by [`prek run `](../cli/#prek-run) and selectors
- `name` (required): label shown in output
- `entry` (required): command to execute
- `language` (required): how `prek` sets up and runs the hook
### Builtin/meta hook selection
For `repo: builtin` and `repo: meta`, the hook entry must include `id`. You can optionally provide `name` and normal hook options (filters, [`stages`](#stages), etc), but not `entry`.
## Supported Git Hook Stages
`prek` follows upstream [`pre-commit` behavior](https://pre-commit.com/#supported-git-hooks) for Git hook stages. The [`stages`](#stages) option controls which hooks are eligible to run; the selected stage controls what input the hook receives.
Stages with no repository file input do not have candidate filenames for [`files`](#hook-files-exclude), [`exclude`](#hook-files-exclude), [`types`](#hook-types), [`types_or`](#hook-types), or [`exclude_types`](#hook-types). Hooks in those stages need [`always_run: true`](#always_run) to run automatically.
| Stage | When it runs | Hook input |
| -------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `manual` | Only when selected explicitly, for example with `prek run --hook-stage manual`. | Repository file paths selected by the `prek run` file mode. |
| `commit-msg` | During commit message validation. | Git's commit message file, not repository file paths. |
| `post-checkout` | After a checkout has occurred. | No repository file input. |
| `post-commit` | After a commit has already succeeded. | No repository file input. |
| `post-merge` | After a successful merge. | No repository file input. |
| `post-rewrite` | After a command rewrites history, such as amend or rebase. | No repository file input. |
| `pre-commit` | Before a commit is finalized. | Repository file paths from the staged contents; unstaged changes are temporarily stashed while hooks run. |
| `pre-merge-commit` | After a merge succeeds but before the merge commit is created. | Repository file paths from the staged merge result. |
| `pre-push` | During `git push`. | Repository file paths changed in the push range. |
| `pre-rebase` | Before a rebase starts. | No repository file input. |
| `prepare-commit-msg` | Before the commit message editor opens or before the commit message is finalized. | Git's commit message file, not repository file paths. |
## Common hook options
These keys can appear on hooks (remote/local/builtin/meta), subject to the restrictions above.
### `id`
The stable identifier of the hook.
- For remote hooks, this must match a hook id defined by the remote repository.
- For local hooks, you choose it.
`id` is also used for CLI selection (for example [`prek run `](../cli/#prek-run) and [`PREK_SKIP`](../environment-variables/#prek_skip)).
Hook ids containing `:`
If your hook id contains `:` (for example `id: lint:ruff`), `prek run lint:ruff` will not select that hook. `prek` interprets `lint:ruff` as the selector `:`, with project `lint` and hook `ruff`. To select the hook id `lint:ruff`, add a leading `:` and run `prek run :lint:ruff`.
### `name`
Human-friendly label shown in output.
- Required for `repo: local` hooks.
- Optional as an override for remote/meta/builtin hooks.
### `entry`
The command line to execute for the hook.
- Required for `repo: local` hooks.
- Optional override for remote hooks.
- Not allowed for `repo: meta` and `repo: builtin`.
The repository type, language, and optional `shell` setting determine how this value is interpreted. See [Hook entry resolution](../../internals/#hook-entry-resolution) for the command, path, and working-directory rules.
If [`pass_filenames`](#pass_filenames) is `true`, `prek` appends matching filenames to this command when running.
### `shell`
prek-only
`shell` is a `prek` extension and may not be recognized by upstream `pre-commit`.
Run `entry` through a predefined shell adapter.
- Type: one of `sh`, `bash`, `pwsh`, `powershell`, `cmd`
- Default: `null` (run `entry` directly without a shell)
When `shell` is omitted, `prek` preserves the default no-shell behavior: it parses `entry` into argv, invokes the command directly, and appends [`args`](#args) and matching filenames as process arguments.
When `shell` is set, `entry` is treated as source for that shell. `prek` writes the source to a temporary script file, runs it with the selected shell adapter, and passes hook [`args`](#args) followed by matching filenames as script arguments.
| `shell` | Adapter command | Script arguments |
| ------------ | ------------------------------------------------------ | ---------------- |
| `bash` | `bash --noprofile --norc -eo pipefail