Current behavior
prek follows the pre-commit model of installing each hook and its additional_dependencies into a dedicated, cacheable environment. The hook then runs from the project working directory and receives project files.
This model treats three things separately:
- the hook tool and its runtime dependencies,
- the project source and configuration,
- the project's dependency environment.
prek provides the first two. The third remains outside the hook environment.
That boundary works for self-contained formatters and source-level checks. It breaks down for project-aware tools whose behavior depends on packages installed for the project.
Symptoms across ecosystems
Node
A Stylelint hook can be installed and executed from its isolated Node environment, while the project's stylelint.config.js references shared configs and plugins from the project dependency graph. Installing those packages as hook additional_dependencies does not necessarily make them visible to resolution originating from the project configuration. See #2128.
Python
mypy, ty, and similar type checkers can run from an isolated Python environment, but accurate analysis may require the project's complete dependency closure, including PEP 561 packages, stubs, plugins, editable installs, and local workspace packages.
Installing only the type checker isolates it from those semantic inputs. Repeating the project dependencies in additional_dependencies creates a separate dependency graph that can drift from the project. This is discussed across #780, #1485, and #1675.
The same class of problem can affect framework-aware linters, test runners, code generators, and other hooks that import or inspect project dependencies.
Root cause
The hook isolation model assumes that the project is input data, not part of the hook's runtime dependency graph.
For project-aware hooks, that assumption does not hold: the project's installed dependencies are semantic inputs to configuration loading or analysis. Running the hook from the project directory exposes source files and configuration, but package resolution still follows the hook's interpreter and environment.
The current mechanisms cover different sides of the boundary but do not connect them:
additional_dependencies extends the hook environment, but does not derive a complete dependency graph from project metadata or lockfiles.
language: system, local hooks, and commands such as uv run can use the project environment, but bypass part of prek's isolation and environment caching model.
- Reusing an active environment introduces ambient state and can produce different results across developers and CI.
- Creating another isolated environment from project dependencies requires project manifests, lockfiles, dependency groups, workspaces, and local packages to participate in environment construction and cache invalidation.
This is not specific to Node module resolution or Python virtual environments. It is a general mismatch between isolated hook installation and tools whose correct execution depends on the project's dependency environment.
Related issues
Current behavior
prek follows the pre-commit model of installing each hook and its
additional_dependenciesinto a dedicated, cacheable environment. The hook then runs from the project working directory and receives project files.This model treats three things separately:
prek provides the first two. The third remains outside the hook environment.
That boundary works for self-contained formatters and source-level checks. It breaks down for project-aware tools whose behavior depends on packages installed for the project.
Symptoms across ecosystems
Node
A Stylelint hook can be installed and executed from its isolated Node environment, while the project's
stylelint.config.jsreferences shared configs and plugins from the project dependency graph. Installing those packages as hookadditional_dependenciesdoes not necessarily make them visible to resolution originating from the project configuration. See #2128.Python
mypy, ty, and similar type checkers can run from an isolated Python environment, but accurate analysis may require the project's complete dependency closure, including PEP 561 packages, stubs, plugins, editable installs, and local workspace packages.
Installing only the type checker isolates it from those semantic inputs. Repeating the project dependencies in
additional_dependenciescreates a separate dependency graph that can drift from the project. This is discussed across #780, #1485, and #1675.The same class of problem can affect framework-aware linters, test runners, code generators, and other hooks that import or inspect project dependencies.
Root cause
The hook isolation model assumes that the project is input data, not part of the hook's runtime dependency graph.
For project-aware hooks, that assumption does not hold: the project's installed dependencies are semantic inputs to configuration loading or analysis. Running the hook from the project directory exposes source files and configuration, but package resolution still follows the hook's interpreter and environment.
The current mechanisms cover different sides of the boundary but do not connect them:
additional_dependenciesextends the hook environment, but does not derive a complete dependency graph from project metadata or lockfiles.language: system, local hooks, and commands such asuv runcan use the project environment, but bypass part of prek's isolation and environment caching model.This is not specific to Node module resolution or Python virtual environments. It is a general mismatch between isolated hook installation and tools whose correct execution depends on the project's dependency environment.
Related issues
pyproject.tomldependency group #1462 — Python hook dependencies from apyproject.tomldependency grouplanguage: pythonhooks in the project's active venv #1485 — running Python hooks in the project's active virtual environmentuv runnpm installas a local hook before a hook that needs to import dependencies #2128 — Stylelint configs and plugins installed outside the project dependency environment