mrkeyoor.com_
Sun 20 Sept 06:59 UTC
PyPICLI & Toolingupdated 20 Sept 2026

pre-commit review

pre-commit 4.6.2 reads `.pre-commit-config.yaml`, installs pinned hook repositories into isolated language environments, selects files for a Git hook stage, and runs each hook before Git continues. It supports stages such as `pre-commit`, `commit-msg`, `pre-push`, and `manual`, plus local commands when no published hook exists. The framework supplies orchestration, caching, filtering, and environment setup; linters and formatters come from the configured repositories. Our `import pre_commit` check took 0.02 seconds, although normal use is through the CLI. Version 4.6.2 fixes Node hooks whose `package.json` contains a build script under npm 11, repairing a regression introduced by 4.6.1.

Verdict

pre-commit 4.6.2 installed in 0.3 seconds, occupied 12 MB across 10 packages, imported in 0.02 seconds, and had 0 audit findings in our sandbox. Install it for quick, pinned checks across mixed toolchains; leave networked and slow jobs in CI, and budget for hook-environment downloads on every uncached machine.

We installed it

Lab card: what happened when we installed pre-commitScreenshot of pre-commit documentation
Install✓ · 0.3s10 packages on disk · 12 MB
Importimport pre_commit in 0.02s · pure Python · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does pre-commit install cleanly?

Yes. In a fresh container with an empty cache, pip install pre-commit finished in 0.3s, leaving 10 packages and 12 MB on disk. pip-audit reported no known vulnerabilities.

What does pre-commit need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import pre_commit succeeded in 0.02s.

pre-commit or prek: which should you use?

prek: Use it when a Rust implementation and broad pre-commit configuration compatibility are the priority. pre-commit 4.6.2 installed in 0.3 seconds, occupied 12 MB across 10 packages, imported in 0.02 seconds, and had 0 audit findings in our sandbox.

When should you not use pre-commit?

Contributors will not install hooks and CI already enforces one fast task command. Another YAML layer may add setup without changing what gets caught.

API stability4/5The configuration still revolves around `repos`, immutable `rev` values, hook IDs, stages, file filters, arguments, and language environments, while commands such as `install`, `run`, `autoupdate`, and `clean` remain recognizable. Major 4 removed the old `python_venv` language and renamed legacy stage values, with `migrate-config` available for updates. Version 4.6.2 is a targeted npm 11 repair, showing that external language installers remain a compatibility boundary.
Docs5/5pre-commit.com documents every configuration key, supported hook language, stage, filtering expression, local repository mode, cache location, CI recipe, command, and hook-authoring requirement. It explains staged-file behavior and includes copyable YAML for ordinary and advanced cases. The GitHub README itself is only a pointer, so users must follow the official site rather than expect repository-front-page examples.
Maintenance5/5Version 4.6.2 shipped on 2026-08-10, the repository was pushed on 2026-08-17, and GitHub reports 26 open issues and pull requests in an unarchived project. The release notes identify the exact npm 11 failure, the 4.6.1 regression that caused it, and the affected Node build-script case. Recent maintenance also tracks Git and language toolchain changes, which is central to a manager that bootstraps many ecosystems.
Ecosystem5/5PyPI Stats counted 42,454,729 downloads in the latest week, and GitHub shows 15,537 stars. Public hook repositories cover formatting, linting, secret detection, and file hygiene across many languages, while `repo: local` can wrap project-owned executables. The same YAML can run on laptops, ordinary CI, and pre-commit.ci, although each remote hook remains a separate dependency with its own revision and runtime.

Discussed on

  1. hnPrek: A better, faster, drop-in pre-commit replacement, engineered in Rust291 points
  2. hnPre-commit hooks are broken212 points
  3. hnYipit Django Blog: Why You Need a Git Pre-Commit Hook108 points
  4. hnPre-commit: framework for managing/maintaining multi-language pre-commit hooks84 points
  5. hnShow HN: Pre-commit – A framework for managing multi-language pre-commit hooks73 points

Use it if

  • One repository needs pinned, repeatable formatters and validators across Python, Node, Go, Ruby, Rust, or other supported hook languages.
  • Fast checks should receive only staged filenames during a commit and run over every file in CI.
  • Developers should get the same hook revision without installing each linter globally.
  • Commit messages, pushes, merges, or an explicit manual stage need checks beyond the ordinary pre-commit event.
Skip it if

Setup reality

We installed pre-commit 4.6.2 in a fresh Python 3.12 Bookworm sandbox in 0.3 seconds. It left 10 packages and 12 MB on disk. pip-audit found 0 known vulnerabilities. The pure-Python distribution has 5 direct dependencies, requires Python 3.10 or newer, uses the MIT license, and does not include py.typed. import pre_commit succeeded in 0.02 seconds, but the supported user interface is the pre-commit command and its YAML file.

Each clone needs pre-commit install to place scripts under .git/hooks; CI can call pre-commit run --all-files without installing those scripts. A configured rev should be an immutable tag or commit. pre-commit autoupdate edits revisions, so review that diff and the resulting formatter changes together. Installing the framework alone supplies no checks. Every hook ID must come from a configured remote repository or repo: local.

Cold hook execution is slower than the 0.3-second framework install. pre-commit clones every remote hook and creates a cached environment for its language and revision. Python hooks build virtual environments, while Node hooks can install their own runtime and npm packages. Cache PRE_COMMIT_HOME in CI with the Python version and config hash in the cache key. language: system skips isolation but depends on whatever executable happens to be on PATH.

During pre-commit, the framework targets staged files and stashes conflicting unstaged edits. A formatter can modify a file and fail the commit so the new bytes can be reviewed and staged. Hooks receive filename batches unless pass_filenames: false changes the contract; require_serial: true prevents parallel batches. Extra stages need both YAML configuration and the matching pre-commit install --hook-type ... call. Local SKIP=id exceptions should not disable the equivalent CI requirement.

Patterns

Attach the hook to one clone install-pre-commit-hook

pre-commit install

`pre-commit install` writes the Git hook for the current clone. Other clones and CI jobs do not inherit that `.git/hooks` file.

Configure immutable hook revisions pin-remote-hooks

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: check-yaml
      - id: end-of-file-fixer
      - id: trailing-whitespace

A hook `rev` should resolve to an immutable tag or commit. The framework installs the listed hook repository; it does not bundle these checks itself.

Check every tracked file run-entire-repository

pre-commit run --all-files

`--all-files` is the usual CI invocation and the right verification after adding or updating hooks. A normal commit run selects staged files instead.

Execute one hook on named files run-selected-hook

pre-commit run check-yaml --files config/app.yaml deploy/service.yml

The positional name is the configured hook ID. `--files` bypasses staged-file selection and passes only the paths that match the hook's filters.

Update revisions and test the result review-hook-updates

pre-commit autoupdate
git diff -- .pre-commit-config.yaml
pre-commit run --all-files

`autoupdate` edits the config. Review revision changes before accepting any repository-wide formatting or rule changes produced by the new hook versions.

Target one directory and file type filter-hook-files

repos:
  - repo: local
    hooks:
      - id: validate-api
        name: validate API schemas
        entry: python scripts/validate_api.py
        language: python
        files: ^api/.*\.ya?ml$
        exclude: ^api/generated/

`files` and `exclude` are regular expressions searched against repository-relative paths. pre-commit applies them before invoking the hook.

Give a local Python hook its own dependencies define-isolated-local-hook

repos:
  - repo: local
    hooks:
      - id: validate-toml
        name: validate project TOML
        entry: python scripts/check_toml.py
        language: python
        additional_dependencies:
          - tomli==2.2.1
        types: [toml]

`language: python` creates an isolated environment and installs `additional_dependencies`. Pin those packages because they are outside the project's main environment.

Disable filename arguments for a test command run-whole-project-command

repos:
  - repo: local
    hooks:
      - id: unit-smoke
        name: unit smoke tests
        entry: python -m pytest -q tests/smoke
        language: system
        pass_filenames: false

`pass_filenames: false` stops pre-commit from appending selected paths. `language: system` uses the caller's PATH and gives up an isolated tool environment.

Enable commit and message hooks install-commit-message-stage

pre-commit install \
  --hook-type pre-commit \
  --hook-type commit-msg

Listing `stages: [commit-msg]` in YAML does not create `.git/hooks/commit-msg`. Install every required Git hook type in each clone.

Move an expensive job to a manual stage configure-manual-check

repos:
  - repo: local
    hooks:
      - id: integration
        name: integration tests
        entry: ./scripts/integration.sh
        language: system
        pass_filenames: false
        stages: [manual]

# Explicit invocation:
# pre-commit run integration --hook-stage manual --all-files

A manual-stage hook never runs during an ordinary commit. CI or the release process must invoke it explicitly if passing it is required.

Use a stable CI cache directory cache-hook-environments

export PRE_COMMIT_HOME="$CI_PROJECT_DIR/.cache/pre-commit"
pre-commit run --all-files

Cache this directory with keys that include the Python version and a hash of `.pre-commit-config.yaml`. Hook revisions and language runtimes affect compatibility.

Record an exceptional local skip skip-local-hook-once

SKIP=validate-api git commit -m 'Update generated schema fixture'

`SKIP` accepts comma-separated hook IDs for that process. Required CI checks should still run so a workstation exception cannot become repository policy.

Alternatives

PackageRegistryPick it when
prekPyPIUse it when a Rust implementation and broad pre-commit configuration compatibility are the priority.
huskynpmUse it for lightweight native Git hook scripts in a repository already centered on Node.
lint-stagednpmUse it to feed staged files into package commands, commonly from a Husky hook.

More cli & tooling guides

commander · chalk · typescript · esbuild · yargs · click · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.