Add quality gates to every commit
Husky runs Git hooks for you, so linting, commit-message validation, and tests fire automatically at the right moment instead of relying on memory. This builder generates the three most useful hooks — pre-commit, commit-msg, and pre-push — along with the matching lint-staged config and the exact setup commands.
How it works
Husky installs a Git core.hooksPath pointing at a .husky folder. In Husky v9 each hook is a plain shell script containing just the command to run.
- pre-commit runs
lint-staged, which lints and formats only the files you staged. Thelint-stagedconfig maps a glob like*.{js,jsx,ts,tsx}to commands such aseslint --fixandprettier --write; matched files are auto-fixed and re-staged. - commit-msg runs
commitlint --edit "$1", where$1is the path to the file holding the in-progress commit message. If the message violates your convention, the commit aborts. - pre-push runs your test command so broken code never reaches the remote.
The setup commands install husky, lint-staged, and commitlint, run npx husky init, and write each hook file.
What the generated files look like
A typical pre-commit hook in .husky/pre-commit:
npx lint-staged
A commit-msg hook in .husky/commit-msg:
npx --no-install commitlint --edit "$1"
A pre-push hook in .husky/pre-push:
npm test
The lint-staged configuration in package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,css}": "prettier --write"
}
}
Husky v9 vs older versions
If you find .husky/_/husky.sh source lines in existing hooks, those are from Husky v4/v5. Husky v9 removed the boilerplate entirely — each hook is a minimal shell script with no shebang required (Husky adds the shell automatically). The setup also changed: instead of "prepare": "husky install" in package.json, you now run npx husky init once and Husky handles the rest.
Setting up in a new repository
The builder produces a shell command block you can paste into your terminal:
npm install --save-dev husky lint-staged @commitlint/cli @commitlint/config-conventional
npx husky init
echo "npx lint-staged" > .husky/pre-commit
echo 'npx --no-install commitlint --edit "$1"' > .husky/commit-msg
echo "npm test" > .husky/pre-push
That sequence installs the tools, initialises Husky, and writes all three hook files. The builder customises the file globs, lint commands, and test command based on your choices.
Tips and notes
- lint-staged keeps pre-commit fast by only touching staged files.
- Hooks can be bypassed with
--no-verify, so re-run the same checks in CI for genuine enforcement. - Use
npx --no-installin the commit-msg hook so it fails loudly if commitlint is missing rather than fetching it silently. - Keep the pre-push command lightweight — a fast smoke test or type-check is ideal; a full slow test suite belongs in CI where it can run in parallel.
- Commit your
.huskyfolder and thelint-stagedconfig so the whole team shares the same gates without any manual setup.