_private/qwestly-docs/Engineering/Git-Hooks-Auto-Install.md

Git Hooks Auto-Install With npm prepare

This guide shows a general pattern for auto-installing Git hooks when developers run npm install.

Why this works

  • Git hooks run automatically on Git events (pre-commit, pre-push, etc.).
  • Hook scripts are local files in the Git hooks directory.
  • npm runs the prepare lifecycle script after install, which is a good place to copy or configure hooks.
your-repo/
  hooks/
    pre-commit
    pre-push
  scripts/
    install-git-hooks.sh
  package.json

Step 1: Add a prepare script

In package.json:

{
  "scripts": {
    "prepare": "bash ./scripts/install-git-hooks.sh"
  }
}

Step 2: Add an install script

Create scripts/install-git-hooks.sh:

#!/usr/bin/env bash
set -euo pipefail

# Skip if this isn't a Git checkout (some CI/build contexts)
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "Skipping git hook install: not a git repo"
  exit 0
fi

HOOK_SRC_DIR="hooks"
HOOK_DST_DIR="$(git rev-parse --git-path hooks)"

mkdir -p "$HOOK_DST_DIR"

for hook in "$HOOK_SRC_DIR"/*; do
  [ -f "$hook" ] || continue
  cp "$hook" "$HOOK_DST_DIR/$(basename "$hook")"
  chmod +x "$HOOK_DST_DIR/$(basename "$hook")"
done

echo "Installed git hooks from $HOOK_SRC_DIR -> $HOOK_DST_DIR"

Make it executable once:

chmod +x scripts/install-git-hooks.sh

Step 3: Add your hook scripts

Example hooks/pre-commit:

#!/usr/bin/env bash
set -euo pipefail

npm run lint
npm test

Make each hook executable:

chmod +x hooks/pre-commit

Notes

  • If someone installs with npm install --ignore-scripts, prepare will not run.
  • Hooks are still local files; this pattern makes installation reproducible per clone.
  • Alternative: use Husky (core.hooksPath) instead of copying into .git/hooks.