git-hook-installer

Crates.iogit-hook-installer
lib.rsgit-hook-installer
version3.0.1
created_at2026-01-11 21:33:08.63629+00
updated_at2026-01-13 15:16:43.931649+00
descriptionInstall basic premade git hooks into the current repository.
homepagehttps://github.com/pRizz/git-hook-installer
repositoryhttps://github.com/pRizz/git-hook-installer
max_upload_size
id2036487
size121,423
Peter Ryszkiewicz (pRizz)

documentation

https://docs.rs/git-hook-installer

README

git-hook-installer

A small Rust CLI that installs premade git hooks into the current repository.

crates.io Downloads docs.rs License: MIT Rust dependency status

Install

From crates.io:

cargo install git-hook-installer

Or from source (this repo):

cargo install --path .

Usage

Run with no arguments to offer to install/update the managed pre-commit hook:

git-hook-installer

Recursively install/update the managed pre-commit hook across many repos under a directory:

# scans current directory
git-hook-installer install-recursive

# or pass an explicit directory to scan
git-hook-installer install-recursive ~/src

# increase scan depth (default is 1)
git-hook-installer install-recursive --max-depth 3 ~/src

# skip the confirmation prompt
git-hook-installer --yes install-recursive ~/src

Inspect the current hook state:

git-hook-installer status

Install/update the managed pre-commit hook directly:

git-hook-installer install pre-commit

Disable the managed pre-commit block (without removing it):

git-hook-installer disable

Uninstall the managed pre-commit block (preserves any other pre-commit logic you already had):

git-hook-installer uninstall

If your repo has multiple Cargo.toml files (monorepo), pick which one the hook should use:

git-hook-installer install pre-commit --manifest-dir crates/my-crate

Behavior

  • git repo detection: walks up parent directories looking for .git (supports worktrees where .git is a file).
  • recursive install: install-recursive [DIR] scans for git repos under a directory and runs the installer in each repo (shows a count + directory preview and asks for confirmation unless --yes). The default scan depth is 1, configurable via --max-depth.
  • safe overwrites: if a hook already exists, it will prompt before backing it up (or use --force / --yes).
  • hook installed: .git/hooks/pre-commit contains a managed block (marked with git-hook-installer begin/end markers) which can run a set of formatters/linters and re-stage changes.
  • no repo config: all settings are stored inside the hook file in .git/hooks/ (nothing is written to your repository).
  • proof-based language enabling (to avoid surprises):
    • At install time, git-hook-installer tries to determine which languages your repo actually uses.
    • The generated hook only includes language sections when there is positive evidence (“proof”) that the repo uses that language. This prevents, for example, adding JS/TS lints to a non-JS repo.
    • If you later add a new language to the repo (or add config files), re-run git-hook-installer install pre-commit to re-detect and regenerate the hook.
    • Monorepos are supported: detection includes a bounded shallow scan so nested packages can still be detected without doing an expensive full repo walk.
  • toolchain auto-selection:
    • For languages that are enabled (proven), the installer auto-selects the most likely toolchain (e.g. Biome vs Prettier+ESLint, Ruff vs Black, Spotless vs ktlint) based on common config signals.
    • In interactive installs it prints a short “auto-selected/defaulting” summary; in --non-interactive mode it stays quiet.
  • what counts as “proof” (high-level):
    • JS/TS: package.json / lockfiles / tsconfig.json / jsconfig.json / Biome / ESLint / Prettier config, or a shallow scan that finds JS/TS source files.
      • Note: Prettier-based formatting for Markdown/YAML is tied to JS/TS being enabled (since it uses the same toolchain).
      • If the repo is detected as TypeScript, the hook also runs a tsc --noEmit typecheck when staged changes include *.ts/*.tsx or tsconfig.json (uses tsc on PATH or npx --yes tsc).
    • Python: pyproject.toml, requirements/setup files, common lockfiles, or a shallow scan that finds .py files.
    • Java/Kotlin: Gradle/Maven files, or a shallow scan that finds .java/.kt/.kts files.
    • Go: go.mod/go.work/go.sum, or a shallow scan that finds .go files.
    • Ruby: Gemfile / .ruby-version / Rakefile, or a shallow scan that finds .rb files.
    • Shell: .shellcheckrc / .shfmt, or a shallow scan that finds shell scripts.
    • Terraform: .terraform.lock.hcl, or a shallow scan that finds .tf/.tfvars files.
    • C/C++: .clang-format, or a shallow scan that finds common C/C++ file extensions.
    • Rust: cargo fmt only runs when a Cargo manifest directory was resolved (or passed via --manifest-dir).
  • auto-fix safety:
    • If you have unstaged/untracked changes, the hook stashes them with git stash push --keep-index --include-untracked, runs auto-fix on the staged files, re-stages, and then restores the stash.
    • If a formatting step errors, the hook attempts a best-effort rollback (reset + re-apply saved staged diff, plus stash restore if used).
  • snapshots before edits: before git-hook-installer modifies .git/hooks/pre-commit, it snapshots the current file to .git/hooks/pre-commit.snapshot-YYYY-MM-DD-HH-MM-SS and keeps the newest 10 snapshots by default.

Options

  • -y, --yes: auto-confirm prompts
  • --non-interactive: never prompt (fails on ambiguity or existing hooks unless --force)
  • -f, --force: overwrite existing hook (backs it up first)

Links

Commit count: 22

cargo fmt