Skip to content

Feature request: Support installing hooks from pypi #1925

Description

@stephenfin

prek, like pre-commit, uses git repos as the main "distribution mechanism" for .pre-commit-hooks.yaml files. The main disadvantage of this approach is that git repos don't generally contain built source. Instead, you must build the binary yourself. How this is achieved varies depending on the package.

Python packages on PyPI can be used to distribute non-Python binaries (e.g. cmake). This appears to be specific to PyPI and the likes of Cargo or Maven don't appear to support this. Binaries provided this way don't need to be built, avoiding the need for hacks like https://github.com/astral-sh/ruff-pre-commit/. In addition, Python packages provide the ability to distribute files like .pre-commit-hooks.yaml (via data files).

Would it be possible to support installation of hooks from PyPI, perhaps with changes to prek.toml like below?

[[plugins]]
type = "repo"
repo = "https://github.com/pre-commit/pre-commit-hooks"
hooks = [{ id = "trailing-whitespace" }]

[[plugins]]
type = "pypi_package"
package = "ruff"
hooks = [{ id = "ruff-format" }]

[[plugins]]
type = "local"
hooks = [
  {
    id = "cargo-fmt",
    name = "cargo fmt",
    language = "system",
    entry = "cargo fmt",
    files = "\\.rs$",
  },
]

[[plugins]]
type = "meta"
hooks = [{ id = "check-useless-excludes" }]

We may wish to build on this further to add support for distributing plugins via other mechanisms that are well suited to binary distribution (GitHub Releases?) but that's out-of-scope for here.

Activity

  1. j178 commented on Apr 10, 2026

    @j178
    Owner

    Interesting idea, but it’d take a fair bit of refactoring. I’ll think it through.

  2. stephenfin commented on Apr 11, 2026

    @stephenfin
    Author

    Thanks for taking a look at this 🙏 Would you be open to a PR (or rather, series of PRs) that attempted to tackle this? My rust-fu is still so-so, but I believe virtually all of the required functionality (mainly creating and caching Python venvs) is already implemented or would be easy to do with the uv wrappers (inspecting data files), meaning this would mainly be a refactoring exercise. I think this could be broken up into a few steps:

    1. Rename the Repo enum in crates/prek/src/hook.rs to Plugin, then rename the Remote variant to Git and RemoteRepo struct to GitPlugin. Also rename the other *Repo structs to *Plugin.
    2. Add a new helper to install a package and extract the hooks.
      I don't know if this should go in e.g. crates/prek/src/languages/python/pypi_package.rs alongside other Python/uv'y things or in the root src dir at crates/prek/src/pypi.rs like git.rs. We could also create a new directory like crates/prek/src/plugin_loaders and move git.rs here?
    3. Add a new Plugin::PypiPackage(PypiPackagePlugin) variant. To avoid reworking existing .pre-commit-config.yaml / pryk.toml files this could initially be exposed via a new pypi_package: prefix, e.g.
      - repo: pypi_package:ruff
        rev: "0.16.0"
        hooks:
        - id: ruff-format
      Note that we'll only accept exact package versions to ease caching and make things deterministic.
    4. Add caching support. We can cache on the package name and rev. Ditto for auto-update, which can be implemented using uv.

    I believe the changes to pryk.yaml (and .pre-commit-hooks.yaml? I'm not sure if we plan to evolve this in the long-term) could be done in parallel/isolation.

  3. Repository owner locked and limited conversation to collaborators on Aug 9, 2026
  4. converted this issue into a discussion #2520 on Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ideaJust an idea

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions