logoNavigate back to the homepage




July 1st, 2020 · 2 min read


Have you ever come across a situation where your code indentation is not following the project’s style or unit tests breaking in master branch? These usually happen due to oversight of developers missing to test them before raising a pull request. Thanks to git hooks these checks can be easily performed before commits or pushing the code to the VCS!

Behold Husky, a tiny JS package for defining and executing git hooks - scripts in a NodeJS project. Inherently, it supports all the basic git hooks (defined here) except for the server side hooks. The configs for the package are simple and are defined inside the package.json of the project.

Thus, Husky is a simple way to enforce project wide git hooks, helping ensure coding standards checks and automating house keeping tasks.


The package expects a simple config, basically a JSON with the key husky inside the package.json. The object with the hooks key inside this contains the definition of scripts for each of the hooks to be implemented. Let’s look at a simple example for executing unit tests before commit and end-to-end tests before allowing to push the code to the VCS:

1"husky": {
2 "hooks": {
3 "pre-commit": "npm run test:unit",
4 "pre-push": "npm run test:e2e"
5 }

Though Husky allows a single command to be run for a hook, command chaining by using &&, similar to shell scripts is supported. If multiple commands need to be executed, an array containing the commands inside a husky.config.js or .huskyrc.js file at the project root, provided as the action script is the simplest way to achieve this:

1const tasks = commandsArray => commandsArray.join(' && ')
2module.exports = {
3 'hooks': {
4 'pre-push': tasks([
5 'npm run test:unit',
6 'npm run test:e2e'
7 ])
8 }

If some local commands are to be executed before Husky’s actions are executed, a .huskyrc file can be defined at the home directory containing the same.

Though Husky runs on all platforms, care has to be enforced while running scripts that need different configs based on the platform they are being run, as a part of the hooks!

The actions being executed for the hooks can get parameters via command-line arguments and stdin. It is accessible via HUSKY_GIT_PARAMS and HUSKY_GIT_STDIN environment variables.

1"husky": {
2 "hooks": {
3 "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
4 }
5 },
6 "commitlint": {
7 "extends": [
8 "@commitlint/config-conventional"
9 ]
10 },

The above example lets us pass our commit message to commitlint package, as a part of pre-commit checks, for evaluating whether the message is following the structure defined in the project’s commitlint.config.js file.

In addition to those environment variables, setting HUSKY_SKIP_INSTALL environment variable to 1, skips the installation of the git hooks and setting HUSKY_SKIP_HOOKS to 1 allows skipping the execution of the scripts for that command run.

The following example shows how we can skip any commit related hooks:

1HUSKY_SKIP_HOOKS=1 git commit -m "temp: checking husky's hooks skip feature"

Evaluation metrics

Ease of useGoodSimple syntax, cross platform support, extensible feature set
CommunityGoodMore than 30 financial contributors, frequent updates, simple upgrade steps for major version changes, few major issues pending resolution
Active usageGoodMore that 3M weekly downloads at the time of writing, more than 1K dependent packages on npm
VulnerabilitiesGoodNo vulnerabilities reported by npm audit
Docs and TrainingsAverageOfficial docs lack detailed examples for many scenarios and extensive details of how to use various features, external resources are available but most lack details of implementation

Check out the package and some reading materials

https://www.npmjs.com/package/husky https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks https://githooks.com/

Video review of the package

Video review of the package with interesting use cases and in-depth exploration of the features coming soon!


The content and evaluation scores mentioned in this article/review is subjective and is the personal opinion of authors at Unpackaged Reviews based on everyday usage and research on popular developer forums. They do not represent any company’s views and is not impacted by any sponsorships/collaboration.

Header Photo by Simon Rae on Unsplash

More articles from Unpackaged Reviews


Adding unique identities made easy!

June 25th, 2020 · 3 min read


A well defined, declarative way of managing CSS classes.

June 19th, 2020 · 2 min read
© 2020-2021 Unpackaged Reviews
Link to $https://twitter.com/unpakgd_reviewsLink to $https://unpackaged-reviews.medium.com