Husky Git Hooks
Git hooks enforce code quality gates before commits and pushes reach the repository. Husky manages hook scripts in the .husky/ directory.
What It Checks
Git hooks enforce formatting and linting standards on every commit and push. The pre-commit hook formats staged files with Biome, and the pre-push hook runs both formatting and linting across the workspace.
What Hooks Do Not Cover
Hooks intentionally skip expensive operations:
- Tests are not run in pre-commit or pre-push (too slow for the feedback loop)
- Type checking is deferred to CI (cross-package type resolution requires full build)
- Contract compilation is not triggered (adaptive build handles this during development)
These checks run in CI via GitHub Actions workflows instead.
How It's Configured
Pre-Commit
The pre-commit hook runs lint-staged to format only staged files:
# .husky/pre-commit (simplified)
if command -v bun >/dev/null 2>&1; then
bunx lint-staged
elif command -v npm >/dev/null 2>&1; then
npx lint-staged
fi
lint-staged is configured in the root package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx,json}": [
"npx @biomejs/biome format --write"
]
}
}
This applies Biome formatting to all staged JavaScript/TypeScript/JSON files, excluding contract build artifacts (packages/contracts/out/).
Pre-Push
The pre-push hook runs formatting and linting checks:
# .husky/pre-push (simplified)
$RUNNER format:contracts # forge fmt
$RUNNER format # biome format
$RUNNER lint # oxlint + package linters
The pre-push hook auto-fixes formatting before checking lint. This ensures consistent formatting across the team without requiring developers to remember to run formatters manually.
Shell Compatibility
Both hooks are written for POSIX sh compatibility with careful handling of edge cases:
set -euenables strict mode (exit on error, undefined variables)pipefailis enabled only if the shell supports it (dash does not)nvmsourcing only runs under bash (nvm is not POSIX-sh safe)PATHis prepended with~/.bun/binand~/.local/binto find bun in non-interactive shells
Package Manager Detection
Hooks prefer bun but fall back to npm:
if command -v bun >/dev/null 2>&1; then
RUNNER="bun run"
elif command -v npm >/dev/null 2>&1; then
RUNNER="npm run"
else
echo "Error: Neither bun nor npm found."
exit 1
fi
Running & Troubleshooting
Hook Not Running
If hooks are not executing after a fresh clone:
bun install # Husky install runs as a postinstall script
chmod +x .husky/pre-commit .husky/pre-push
Biome Format Conflicts
If lint-staged fails because Biome disagrees with existing formatting:
bun format # Run the full formatter to fix everything
git add -u # Re-stage the fixed files
Skipping Hooks
Hooks should not be skipped in normal development. If a hook is failing, investigate and fix the underlying issue rather than bypassing with --no-verify. The pre-commit hook only formats staged files, so failures typically indicate a genuine formatting or lint issue.
Resources
- GitHub Actions -- CI pipeline that runs the checks hooks intentionally skip (tests, type checking)
- Regression Testing -- Regression suites that complement local hook checks
- Agentic Evaluation -- How AI agents enforce quality alongside git hooks
- Test Cases -- Test case strategy and coverage targets
Next best action
See the full CI/CD pipeline that runs tests, linting, and deployment on every push.
GitHub Actions