Introduction
Husky is a lightweight tool that makes Git hooks accessible and maintainable in JavaScript and TypeScript projects. It installs hooks directly into your repository so every developer on the team runs the same checks before committing or pushing code. This catches linting errors, failing tests, and malformed commit messages before they reach the remote.
What Husky Does
- Installs Git hooks that run automatically on commit, push, and other Git events
- Integrates with lint-staged to run linters only on staged files for fast feedback
- Works with commitlint to enforce conventional commit message formats
- Shares hook configuration through the repository so all contributors use the same rules
- Supports any shell command or script as a hook action
Architecture Overview
Husky configures Git's core.hooksPath to point to a .husky/ directory in your project root. Each hook is a plain shell script file named after the Git hook event (e.g., pre-commit, commit-msg). When Git triggers a hook, it executes the corresponding script. Husky v9 simplified this to zero-dependency shell scripts, removing the previous Node.js hook runner entirely.
Self-Hosting & Configuration
- Install as a dev dependency with
npm install --save-dev husky - Run
npx husky initto create the.husky/directory and set up a sample pre-commit hook - Add hook scripts as files in
.husky/named after the Git event (pre-commit, commit-msg, pre-push) - Combine with lint-staged by adding
npx lint-stagedto.husky/pre-commit - The
preparenpm script ensures hooks are installed automatically afternpm install
Key Features
- Zero JavaScript runtime dependency in v9: hooks are plain shell scripts
- Native support for npm, yarn, pnpm, and bun package managers
- Monorepo compatible with hooks defined at the root or in sub-packages
- Built-in support for all Git hook events including pre-rebase and post-merge
- Lightweight footprint with no background processes or daemons
Comparison with Similar Tools
- lint-staged — Runs linters on staged files; commonly used together with Husky as the hook trigger
- pre-commit (Python) — Language-agnostic hook framework with a plugin ecosystem; heavier setup than Husky
- Lefthook — Go-based Git hooks manager with parallel execution; faster for large hook configurations
- simple-git-hooks — Minimal alternative storing hooks in package.json; less flexible than Husky's file-based approach
- overcommit — Ruby-based hook manager with built-in checks; primarily used in Ruby projects
FAQ
Q: Does Husky work in CI environments? A: Husky hooks are local Git hooks and do not run in CI by default. CI should run linters and tests directly via npm scripts.
Q: Can I skip hooks temporarily?
A: Yes, use git commit --no-verify or HUSKY=0 git push to bypass hooks for a single operation.
Q: Is Husky compatible with monorepos?
A: Yes. Place the .husky/ directory at the repository root and reference scripts from any package in the monorepo.
Q: What changed between Husky v4 and v9? A: Husky v5+ switched from a Node.js-based hook runner to plain shell scripts, removing the need for a JavaScript runtime at hook execution time.