Skip to main content

Husky Setup

1

Install Husky

npm install --save-dev husky
npx husky init
2

Add pre-commit hook

Create .husky/pre-commit:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Run React Doctor on changed files only
npx -y react-doctor@latest . --diff HEAD --fail-on error
Make it executable:
chmod +x .husky/pre-commit
3

Test the hook

Make a change and commit:
git add .
git commit -m "test: verify pre-commit hook"
React Doctor will run automatically before the commit completes.

Pre-Push Hook

For longer-running scans, use a pre-push hook instead:
1

Create pre-push hook

Create .husky/pre-push:
.husky/pre-push
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Full scan before push
npx -y react-doctor@latest . --verbose --fail-on error
Make it executable:
chmod +x .husky/pre-push
2

Test the hook

git push
React Doctor will run before the push completes.

Lint-Staged Integration

Run React Doctor only on staged files for faster commits:
1

Install lint-staged

npm install --save-dev lint-staged
2

Configure lint-staged

Add to package.json:
package.json
{
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "npx -y react-doctor@latest . --diff HEAD --fail-on error"
    ]
  }
}
Or create .lintstagedrc.json:
.lintstagedrc.json
{
  "*.{ts,tsx,js,jsx}": [
    "npx -y react-doctor@latest . --diff HEAD --fail-on error"
  ]
}
3

Update pre-commit hook

Modify .husky/pre-commit:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

Monorepo Hooks

Detect Changed Project

Run React Doctor only on the affected workspace project:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Get changed files
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)

# Determine which project changed
if echo "$CHANGED_FILES" | grep -q "^apps/web/"; then
  npx -y react-doctor@latest . --project web --diff HEAD --fail-on error
elif echo "$CHANGED_FILES" | grep -q "^apps/admin/"; then
  npx -y react-doctor@latest . --project admin --diff HEAD --fail-on error
fi

Scan All Projects

.husky/pre-push
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Scan all workspace projects
npx -y react-doctor@latest . --yes --fail-on error

Conditional Hooks

Skip on WIP Commits

Allow WIP commits to skip the hook:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Skip hook if commit message starts with "WIP"
COMMIT_MSG_FILE=$1
if [ -n "$COMMIT_MSG_FILE" ]; then
  COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
  if echo "$COMMIT_MSG" | grep -q "^WIP"; then
    echo "Skipping React Doctor for WIP commit"
    exit 0
  fi
fi

npx -y react-doctor@latest . --diff HEAD --fail-on error

Skip with Environment Variable

Bypass the hook when needed:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

if [ "$SKIP_DOCTOR" = "1" ]; then
  echo "Skipping React Doctor (SKIP_DOCTOR=1)"
  exit 0
fi

npx -y react-doctor@latest . --diff HEAD --fail-on error
Usage:
SKIP_DOCTOR=1 git commit -m "emergency fix"

Performance Optimization

Cache npx Downloads

Speed up hook execution by caching React Doctor:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Use cached version with faster startup
npx react-doctor@latest . --diff HEAD --fail-on error

Skip Linting for Speed

Run only dead code detection:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx -y react-doctor@latest . --no-lint --diff HEAD --fail-on error

Quick Score Check

Just verify the score hasn’t dropped:
.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

SCORE=$(npx -y react-doctor@latest . --score --diff HEAD)
MIN_SCORE=70

if [ "$SCORE" -lt "$MIN_SCORE" ]; then
  echo "Error: Health score $SCORE is below minimum $MIN_SCORE"
  exit 1
fi

echo "Health score: $SCORE"

Git Bypass

Users can always bypass hooks if needed:
# Skip all hooks
git commit --no-verify -m "urgent fix"

# Skip pre-push hook
git push --no-verify
Git hooks run locally and can be bypassed. For enforced checks, use CI/CD pipelines.

Complete Workflow Example

Here’s a complete setup with both pre-commit and pre-push hooks:
1

Install dependencies

npm install --save-dev husky lint-staged
npx husky init
2

Configure lint-staged

package.json
{
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "npx -y react-doctor@latest . --diff HEAD --fail-on error"
    ]
  }
}
3

Create pre-commit hook

.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Fast check on staged files
npx lint-staged
chmod +x .husky/pre-commit
4

Create pre-push hook

.husky/pre-push
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Full scan before push to remote
npx -y react-doctor@latest . --verbose --fail-on warning
chmod +x .husky/pre-push
5

Test the setup

# Make a change
echo "export const test = 1;" > test.ts
git add test.ts

# Pre-commit hook runs
git commit -m "test: add test file"

# Pre-push hook runs
git push

Troubleshooting

Hook Not Running

Ensure the hook is executable:
chmod +x .husky/pre-commit
chmod +x .husky/pre-push

npx Takes Too Long

Cache React Doctor globally:
npm install -g react-doctor@latest
Then use in hooks:
react-doctor . --diff HEAD --fail-on error

Hook Fails in CI

Git hooks only run locally. For CI, use CI/CD Integration.

Build docs developers (and LLMs) love