Skip to content

feat(install): warn about hooks that won't run with the installed shims - #2205

Open
BitWeaverDev wants to merge 7 commits into
j178:masterfrom
BitWeaverDev:feat/warn-unmatched-install-stages
Open

feat(install): warn about hooks that won't run with the installed shims#2205
BitWeaverDev wants to merge 7 commits into
j178:masterfrom
BitWeaverDev:feat/warn-unmatched-install-stages

Conversation

@BitWeaverDev

Copy link
Copy Markdown
Contributor

Closes #2056

What

prek install only installs shims for the hook types you ask for — --hook-type, or default_install_hook_types, falling back to pre-commit. If the config has hooks pinned to a different stage (the classic case being a slower stages: [pre-push] hook), those hooks just silently never run after a plain prek install, and it's easy not to notice.

This adds a warning at install time that names the hooks whose stages aren't covered and points at the fix:

warning: The following hooks won't run automatically because their stages aren't being installed:
  - `push-only` (pre-push)
hint: install the missing hook type(s) with `prek install --hook-type <type>`, or set `default_install_hook_types` in your config.

Notes on the approach

  • Config only, no hook init. Each hook's stages are resolved straight from config (stagesdefault_stages → all), so install stays offline and fast. The trade-off is that a remote hook narrowed only by its manifest (not by the project config) won't be flagged — that's the conservative choice: no false positives, no new network I/O, and it covers the case from the issue.
  • manual is skipped, since manual-only hooks have no Git shim and aren't meant to run automatically.
  • Pulled the hook-stage resolution into Stages::resolve so install and HookSpec::apply_project_defaults share one implementation instead of duplicating the fallback rules.
  • No behaviour change to anything that runs — it's purely an extra warning.

Tests

Added integration coverage in tests/install.rs: an unmatched hook warns (while an all-stages sibling does not), installing the matching --hook-type silences it, manual-only never warns, and default_stages inheritance is taken into account.

@BitWeaverDev
BitWeaverDev requested a review from j178 as a code owner June 11, 2026 20:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ada96bec03

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/prek/src/cli/install.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc3a27032d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/prek/src/cli/install.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eec0f0e94c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/prek/src/cli/install.rs Outdated
Comment thread crates/prek/src/cli/install.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eec0f0e94c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/prek/src/cli/install.rs Outdated
@j178 j178 added the enhancement New feature or request label Jun 12, 2026
@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.02128% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.38%. Comparing base (cccc61b) to head (0611e46).
⚠️ Report is 55 commits behind head on master.

Files with missing lines Patch % Lines
crates/prek/src/cli/install.rs 95.89% 6 Missing ⚠️
crates/prek/src/cli/run/selector.rs 81.25% 6 Missing ⚠️
crates/prek/src/config.rs 66.66% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2205      +/-   ##
==========================================
+ Coverage   93.16%   93.38%   +0.21%     
==========================================
  Files         127      129       +2     
  Lines       28182    27681     -501     
==========================================
- Hits        26257    25849     -408     
+ Misses       1925     1832      -93     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@prek-ci-bot

prek-ci-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

📦 Cargo Bloat Comparison

Binary size change: +0.00% (29.1 MiB → 29.1 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text     Size             Crate Name
 1.1%   2.3% 332.0KiB        aws_lc_sys aws_lc_0_42_0_aes_gcm_encrypt_avx512
 1.1%   2.3% 332.0KiB        aws_lc_sys aws_lc_0_42_0_aes_gcm_decrypt_avx512
 0.3%   0.6%  79.3KiB              prek <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.4%  56.1KiB              prek <<prek::config::Config as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.2%   0.3%  49.4KiB annotate_snippets annotate_snippets::renderer::render::render
 0.2%   0.3%  47.8KiB              prek prek::run::{closure#0}
 0.1%   0.3%  42.1KiB              prek prek::cli::run::run::run::{closure#0}
 0.1%   0.2%  33.5KiB              prek prek::archive::unpack::<fs_err::tokio::file::File, &std::path::PathBuf>::{closure#0}
 0.1%   0.2%  32.1KiB              prek <prek::cli::RunOptions as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  30.1KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  28.6KiB    cargo_metadata <&mut serde_json::de::Deserializer<serde_json::read::StrRead> as serde_core::de::Deserializer>::deserialize_struct::<<cargo_metadata::Package as serde_core::de::Deserialize>::deserialize::__Visitor>
 0.1%   0.2%  28.4KiB              prek <<prek::config::RemoteHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_42_0_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_42_0_edwards25519_scalarmuldouble
 0.1%   0.2%  25.9KiB              prek prek::cli::try_repo::try_repo::{closure#0}
 0.1%   0.2%  25.2KiB              prek <<prek::config::LocalHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  24.9KiB               xml <xml::reader::parser::PullParser>::dispatch_token
 0.1%   0.2%  24.3KiB              prek <<prek::config::UpdateOptions as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  24.0KiB     granit_parser <granit_parser::scanner::Scanner<serde_saphyr::de::buffered_input::ReaderInput>>::fetch_more_tokens
 0.1%   0.2%  23.7KiB              prek <prek::languages::node::installer::NodeInstaller>::install::{closure#0}
42.0%  88.0%  12.2MiB                   And 25796 smaller methods. Use -n N to show more.
47.8% 100.0%  13.9MiB                   .text section size, the file size is 29.1MiB

Base Branch Results

 File  .text     Size             Crate Name
 1.1%   2.3% 332.0KiB        aws_lc_sys aws_lc_0_42_0_aes_gcm_encrypt_avx512
 1.1%   2.3% 332.0KiB        aws_lc_sys aws_lc_0_42_0_aes_gcm_decrypt_avx512
 0.3%   0.6%  79.3KiB              prek <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.4%  58.0KiB              prek <<prek::config::Config as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.2%   0.3%  49.4KiB annotate_snippets annotate_snippets::renderer::render::render
 0.1%   0.3%  40.8KiB              prek prek::cli::run::run::run::{closure#0}
 0.1%   0.3%  39.5KiB              prek prek::run::{closure#0}
 0.1%   0.2%  33.2KiB              prek prek::archive::unpack::<fs_err::tokio::file::File, &std::path::PathBuf>::{closure#0}
 0.1%   0.2%  32.1KiB              prek <prek::cli::RunOptions as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  30.5KiB              prek prek::cli::update::update::{closure#0}
 0.1%   0.2%  30.1KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  29.3KiB              prek <<prek::config::RemoteHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  28.6KiB    cargo_metadata <&mut serde_json::de::Deserializer<serde_json::read::StrRead> as serde_core::de::Deserializer>::deserialize_struct::<<cargo_metadata::Package as serde_core::de::Deserialize>::deserialize::__Visitor>
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_42_0_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_42_0_edwards25519_scalarmuldouble
 0.1%   0.2%  25.8KiB              prek prek::cli::try_repo::try_repo::{closure#0}
 0.1%   0.2%  25.6KiB              prek <<prek::config::LocalHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  25.2KiB              prek <<prek::config::UpdateOptions as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  24.9KiB               xml <xml::reader::parser::PullParser>::dispatch_token
 0.1%   0.2%  24.4KiB              prek <prek::languages::node::installer::NodeInstaller>::install::{closure#0}
42.1%  88.0%  12.3MiB                   And 25812 smaller methods. Use -n N to show more.
47.8% 100.0%  13.9MiB                   .text section size, the file size is 29.1MiB

@prek-ci-bot

prek-ci-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

⚡️ Hyperfine Benchmarks

Summary: 1 regressions, 0 improvements above the 10% threshold.

Environment
  • OS: Linux 6.17.0-1020-azure
  • CPU: 4 cores
  • prek version: prek 0.4.10+14 (fd36e34 2026-07-21)
  • Rust version: rustc 1.97.1 (8bab26f4f 2026-07-14)
  • Hyperfine version: hyperfine 1.20.0
CLI Commands

Benchmarking basic commands in the main repo:

prek --version

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base --version 2.6 ± 0.1 2.5 2.9 1.09 ± 0.04
prek-head --version 2.4 ± 0.1 2.3 2.6 1.00

prek list

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base list 10.7 ± 0.3 10.1 11.3 1.00
prek-head list 11.1 ± 1.2 10.3 18.0 1.04 ± 0.11

prek validate-config .pre-commit-config.yaml

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base validate-config .pre-commit-config.yaml 3.8 ± 0.1 3.7 4.1 1.10 ± 0.04
prek-head validate-config .pre-commit-config.yaml 3.5 ± 0.1 3.3 3.6 1.00

prek sample-config

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base sample-config 2.9 ± 0.1 2.7 3.2 1.07 ± 0.04
prek-head sample-config 2.7 ± 0.1 2.6 2.8 1.00
Cold vs Warm Runs

Comparing first run (cold) vs subsequent runs (warm cache):

prek run --all-files (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 77.9 ± 2.3 74.1 82.3 1.00
prek-head run --all-files 78.9 ± 2.9 74.4 83.5 1.01 ± 0.05

prek run --all-files (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 78.8 ± 2.7 75.2 85.2 1.00
prek-head run --all-files 80.0 ± 2.4 75.8 85.5 1.02 ± 0.05
Full Hook Suite

Running the builtin hook suite on the benchmark workspace:

prek run --all-files (full builtin hook suite)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 79.7 ± 3.5 75.2 92.6 1.00
prek-head run --all-files 81.1 ± 3.8 75.7 95.6 1.02 ± 0.07
Individual Hook Performance

Benchmarking each hook individually on the test repo:

prek run trailing-whitespace --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run trailing-whitespace --all-files 22.2 ± 0.4 21.6 23.1 1.00 ± 0.03
prek-head run trailing-whitespace --all-files 22.2 ± 0.4 21.5 23.3 1.00

prek run end-of-file-fixer --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run end-of-file-fixer --all-files 28.2 ± 2.2 25.7 34.7 1.00
prek-head run end-of-file-fixer --all-files 28.6 ± 2.2 25.4 34.1 1.01 ± 0.11

prek run check-json --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-json --all-files 9.0 ± 0.3 8.4 9.9 1.04 ± 0.05
prek-head run check-json --all-files 8.7 ± 0.3 8.2 9.4 1.00

prek run check-yaml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-yaml --all-files 8.8 ± 0.1 8.6 9.0 1.00 ± 0.02
prek-head run check-yaml --all-files 8.8 ± 0.2 8.5 9.2 1.00

prek run check-toml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-toml --all-files 9.2 ± 0.3 8.5 9.9 1.05 ± 0.05
prek-head run check-toml --all-files 8.7 ± 0.3 8.2 9.4 1.00

prek run check-xml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-xml --all-files 8.6 ± 0.3 8.1 9.6 1.01 ± 0.05
prek-head run check-xml --all-files 8.5 ± 0.3 7.8 9.1 1.00

prek run detect-private-key --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run detect-private-key --all-files 14.5 ± 1.0 13.0 16.8 1.00
prek-head run detect-private-key --all-files 15.0 ± 1.3 12.9 17.7 1.03 ± 0.11

prek run fix-byte-order-marker --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run fix-byte-order-marker --all-files 19.7 ± 0.8 18.3 21.1 1.04 ± 0.07
prek-head run fix-byte-order-marker --all-files 19.0 ± 0.9 17.5 21.2 1.00
Installation Performance

Benchmarking hook installation (fast path hooks skip Python setup):

prek install-hooks (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 5.3 ± 0.1 5.2 5.3 1.06 ± 0.02
prek-head install-hooks 5.0 ± 0.1 4.9 5.1 1.00

prek install-hooks (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 5.3 ± 0.1 5.3 5.4 1.06 ± 0.02
prek-head install-hooks 5.0 ± 0.1 4.9 5.1 1.00
File Filtering/Scoping Performance

Testing different file selection modes:

prek run (staged files only)