documentation

Git Hooks

Push bundle stats automatically using git hooks, Husky, or Lefthook

Note: Git hooks don't run in most CI environments — CI runners clone repos without executing hooks. For automated tracking on every push, see CI Integration instead. Git hooks are best suited for local workflows or small teams that don't use a CI pipeline.

Approach 1: Post-build npm script

The most reliable approach — run the snapshot upload as part of the build script, not a git hook. This fires on every build regardless of git state, which is usually what you want for CI compatibility too.

Commit the Quick Start push script as scripts/push-bundle.sh, then chain it after the build:

{
  "scripts": {
    "build": "webpack --json=stats.json && ./scripts/push-bundle.sh"
  }
}

No hook configuration needed. Works in CI, local development, and any environment that calls npm run build.

Approach 2: Manual git pre-push hook

Runs before git push. Use this when you want to capture stats only on pushes to a remote, not on every local build.

Create .git/hooks/pre-push and make it executable:

chmod +x .git/hooks/pre-push

.git/hooks/pre-push:

#!/bin/sh
set -e

# Only run on pushes to main/master
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "master" ]; then
  exit 0
fi

# Build and capture stats
npm run build -- --json=stats.json

# Submit the snapshot to dendrobundle
curl -s -X POST "https://dendrobundle.com/api/push?branch=$BRANCH&commit=$(git rev-parse HEAD)" \
  -H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
  -H "Content-Type: application/json" \
  --data @stats.json

Limitation: Files inside .git/ are not committed to the repository. Each developer must install the hook manually. Use Husky or Lefthook (below) to share hooks with the team via version control.

Approach 3: Husky

Husky installs git hooks as files in .husky/, which are committed to the repo and automatically installed for anyone who runs npm install.

Install:

npx husky init

.husky/pre-push:

#!/bin/sh
npm run build -- --json=stats.json
curl -s -X POST "https://dendrobundle.com/api/push?branch=$(git branch --show-current)&commit=$(git rev-parse HEAD)" \
  -H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
  -H "Content-Type: application/json" \
  --data @stats.json

Add the prepare script so Husky installs hooks on npm install:

{
  "scripts": {
    "prepare": "husky"
  }
}

Approach 4: Lefthook

Zero-dependency alternative to Husky. Configuration lives in lefthook.yml at the repo root.

npx lefthook install

lefthook.yml:

pre-push:
  commands:
    push-bundle:
      run: |
        npm run build -- --json=stats.json
        curl -s -X POST "https://dendrobundle.com/api/push?branch={push_remote_branch}&commit=$(git rev-parse HEAD)" \
          -H "Authorization: Bearer $DENDROBUNDLE_TOKEN" \
          -H "Content-Type: application/json" \
          --data @stats.json

Lefthook uses {push_remote_branch} as a built-in placeholder for the branch being pushed.

Environment variables

All approaches require DENDROBUNDLE_TOKEN to be available in the shell environment when the hook runs.

Locally — add to your shell profile or a .env file (sourced by your shell, not automatically by git hooks):

export DENDROBUNDLE_TOKEN=eyJhbGciOiJIUzI1NiJ9…   # the token shown once on creation

If you use a .env file, source it explicitly at the top of the hook script:

#!/bin/sh
set -a
. "$(git rev-parse --show-toplevel)/.env"
set +a

In CI — set DENDROBUNDLE_TOKEN as a CI/CD secret variable. See CI Integration for pipeline-specific instructions.

Never commit the token to the repo. Add .env to .gitignore.