Husky: Git Hooks for Node.js Projects Using core.hooksPath
Git hooks made easy 🐶 woof!
At a glance
- What is it?
- Husky is a 2 kB MIT-licensed npm package that wires up Git client-side hooks in Node.js projects without symbolic links or shell configuration. It uses Git's core.hooksPath setting to point Git at a .husky/ directory of your own hooks, keeping hook management in version control alongside the code.
- Who is it for?
- Husky is a reasonable choice for Node.js projects already using npm that want to enforce pre-commit checks with zero runtime dependencies and a minimal install footprint. Teams upgrading from Husky v4 must follow the migration guide at typicode.github.io/husky, because the v9 model is incompatible with the v4 configuration format.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Husky Does and Who Uses It
Every Git repository supports client-side hooks: shell scripts that Git invokes at specific points in the workflow. A pre-commit hook can run a linter before every commit; a commit-msg hook can validate that commit messages match a team format; a pre-push hook can run tests before code reaches the remote. Git creates these hooks as executable files in .git/hooks/, a directory that is not tracked by version control.
The problem Husky solves is distribution. Because .git/hooks/ is not committed, every developer on a project must manually set up their own hooks after cloning. Husky takes care of this by storing hooks in a .husky/ directory that is committed to the repository and using Git's core.hooksPath setting to redirect Git to that directory. When a new developer clones the repository and installs npm dependencies, the prepare lifecycle script runs Husky's setup automatically.
Husky targets Node.js project teams. The primary audience is frontend and backend JavaScript and TypeScript developers who want to enforce code style, run type checks, or prevent commits that break tests, with no manual setup step for new contributors.
How core.hooksPath Replaces the Old Symlink Model
Before Git 2.9, tools like the original Husky created symbolic links from .git/hooks/ to a tracked directory. This required write access to .git/ and broke in certain CI and Git GUI environments. Git 2.9 introduced core.hooksPath, a config key that tells Git to look for hooks in a specified directory instead of .git/hooks/.
Husky v9 sets core.hooksPath to .husky/ during setup. This means the hooks are plain shell scripts in a versioned directory, with no symbolic links and no Git internals manipulation. Removing Husky from a project requires only unsetting core.hooksPath and deleting the .husky/ directory. The README notes that this approach "adheres to Git's native hook organization."
The consequence is also portability. Because core.hooksPath is a standard Git feature, it works across macOS, Linux, and Windows, in Git GUIs that respect Git configuration, and with Node version managers that change the environment around npm commands.
Setting Up Husky in a Project
The documentation for installation is at typicode.github.io/husky. The package is published to npm under the name husky at version 9.1.7. It ships as an ECMAScript module with no runtime dependencies. The package.json in the repository shows engines: node >=18, so Node.js 18 or later is required.
The standard pattern for setup, documented on the Husky site, uses npm's prepare lifecycle hook. Adding husky to the prepare script ensures that any developer who runs npm install also runs Husky's setup automatically. The .husky/ directory that Husky creates during setup is then committed to version control, so each hook file (pre-commit, commit-msg, pre-push, and so on) travels with the repository.
Branch-specific hooks are a supported feature listed in the README. These allow different hook behavior on different branches, which is useful when a main branch has stricter checks than a feature branch. The README also notes support for nested projects and monorepos, where multiple package.json files coexist in a single repository.
Hook Scope and POSIX Shell Scripting
Husky supports all 13 client-side Git hooks: applypatch-msg, pre-applypatch, post-applypatch, pre-commit, pre-merge-commit, prepare-commit-msg, commit-msg, post-commit, pre-rebase, post-checkout, post-merge, pre-push, and pre-auto-gc. Each hook is a POSIX shell script stored in the .husky/ directory.
Because hooks are plain POSIX scripts, they can call any CLI tool that is installed. A typical pre-commit hook might invoke a linter like ESLint or a formatter like Prettier on staged files, often combined with lint-staged to avoid re-checking unchanged files. A commit-msg hook might use commitlint to validate the message format. The actual commands in the hook files are not part of Husky's configuration: Husky only handles the plumbing that ensures Git calls the scripts.
The opt-in and opt-out options mentioned in the README allow developers to skip hooks in specific situations, for example when a CI environment handles the same checks and running them again would slow down automated pipelines.
Maintenance Status, v4 Migration, and Real Limitations
The last code push to the Husky repository was on 2026-03-19 and the most recent release is v9.1.7, published in November 2024. The gap between the last release and the last push suggests the repository received maintenance-only commits since the v9.1.7 release, with no new feature work.
For teams upgrading from v4 to v9, the README explicitly warns that migration is required. The v9 model stores hooks in .husky/ and relies on core.hooksPath, which is incompatible with the v4 approach of using symlinks to a hooks directory specified in package.json configuration. The migration guide is at the documentation site.
Husky's scope is narrow by design. It is a hook runner, not a task runner. The hooks themselves must call other tools: a linter, a test runner, a commit message checker. Teams that want a more integrated workflow with parallel task execution or hook dependencies will find Husky too minimal, because it provides no coordination beyond executing the shell script for each hook event.
The 2 kB size and zero-dependency constraint mean there are no security patching concerns for transitive dependencies, but there is also no path for adding features that would require new dependencies.
How Husky Compares to Lefthook
Lefthook is an alternative Git hooks manager written in Go. It installs as a standalone binary with no Node.js requirement, runs hooks in parallel by default, and works with any language ecosystem rather than just Node.js projects. The trade-off is configuration format: Lefthook uses a YAML file to define hooks and tasks, while Husky uses individual shell scripts in the .husky/ directory.
For a Node.js project that already uses npm and npm's prepare lifecycle, Husky's integration is simpler: one npm package, no extra binary to install, hooks stored as plain shell scripts. For a polyglot monorepo or a project where not everyone installs Node.js, Lefthook's language independence makes it the more practical choice.
The maintenance difference is relevant to the decision: Lefthook is under ongoing development. Husky's last push was in March 2026 with no new releases since November 2024. Teams that want a Git hooks tool with an active development trajectory should weigh this against the simplicity advantage Husky offers in pure Node.js environments.
Editorial conclusion
Husky is a reasonable choice for Node.js projects already using npm that want to enforce pre-commit checks with zero runtime dependencies and a minimal install footprint. Teams upgrading from Husky v4 must follow the migration guide at typicode.github.io/husky, because the v9 model is incompatible with the v4 configuration format. The last code push was on 2026-03-19 and the most recent release is v9.1.7 from November 2024. Teams that need ongoing maintenance or new features should evaluate Lefthook or plain Git hooks managed in a shell script, as both remain actively maintained.
Frequently asked questions
What does Husky do for a Node.js project?
Husky sets Git's core.hooksPath to a .husky/ directory in the repository and installs its setup step as an npm prepare script. This means any developer who runs npm install automatically gets the hooks, and the hook scripts live in version control alongside the code.
Does Husky work with Git GUIs and Node version managers?
The README lists Git GUIs, Node version managers, custom hooks directories, nested projects, and monorepos as supported configurations. Because Husky uses Git's core.hooksPath setting rather than symbolic links, it is compatible with environments where .git/hooks/ manipulation would fail.
What changed between Husky v4 and v9?
Husky v9 replaces the v4 model of symlinking hooks via a package.json configuration key with a core.hooksPath-based approach that stores plain shell scripts in a committed .husky/ directory. The README warns that upgrading requires migrating the previous configuration, with instructions at the Husky documentation site.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typicode-husky)
Community notes