Git hooks help teams enforce code quality by automating checks at key stages like commits and pushes. Lefthook is a modern Git hook manager built for speed and collaboration. In this guide, you’ll learn how to use Lefthook with npm to streamline your Git workflow.
What Is Lefthook and Why Is It Used in Git Workflows?
Lefthook is a fast Git hook manager that allows you to define and run custom scripts during Git events such as pre-commit
, pre-push
, and commit-msg
. It improves workflow consistency by automating code formatting, linting, and testing.
Unlike legacy hook tools that write scripts per hook, Lefthook uses a central runner that simplifies setup and improves performance. It supports multiple programming environments including Node.js, Go, and Ruby.
Lefthook is widely used in teams to:
- Prevent bad code from being committed
- Enforce consistent styling and linting
- Run tests before pushes or pull requests
- Reduce manual errors in CI/CD pipelines
The central configuration and cross-platform compatibility make it a preferred choice for scalable engineering teams.
How Do Git Hooks Work in a Version Control System?
Git hooks are executable scripts placed in the .git/hooks
directory. They are triggered by Git actions like committing or pushing code.
Each Git hook has a specific purpose:
pre-commit
: Runs before a commit is createdcommit-msg
: Runs after a commit message is writtenpre-push
: Runs before pushing code to a remote
These hooks can enforce standards, run tests, or prevent unsafe code from reaching the main branch. Without a hook manager, they must be created and maintained manually. Tools like Lefthook automate this process and enforce uniform behavior across developers.
How Do You Install Lefthook Using npm?
The recommended package for Lefthook is lefthook
, published and maintained by Evil Martians.
Install it as a dev dependency:
npm install --save-dev lefthook
After installation, set up the Git hook scripts by running:
npx lefthook install
This command links Lefthook to the .git/hooks
folder and prepares your project to run the configured hooks. You should commit this setup to ensure that all team members share the same hook configuration.
For teams, it’s best to add this to your prepare
script so hooks are installed automatically after running npm install
:
"scripts": {
"prepare": "lefthook install"
}
This ensures hooks are always set up, even on fresh clones or new environments.
How Do You Configure Lefthook for a Project?
Lefthook reads its configuration from a lefthook.yml
file placed in the project root. This file defines what commands run during Git events and how.
A basic example to lint and format code before a commit:
pre-commit:
parallel: true
commands:
eslint:
run: npm run lint
prettier:
run: npm run format
You can run commands on only staged files using {staged_files}
:
pre-commit:
commands:
lint-js:
run: npx eslint {staged_files}
files: "*.js"
Lefthook supports:
- Parallel and sequential execution
- File globbing
- Conditional execution
- Environment variable support
This config file should be committed to version control so everyone on the team uses the same hook logic.
How Do You Connect Lefthook with npm Scripts?
npm and Lefthook work well together because Lefthook can run any command, including npm scripts. It’s a good practice to define hook logic in package.json
and call it from lefthook.yml
.
Example package.json
:
"scripts": {
"lint": "eslint .",
"format": "prettier --write .",
"test": "jest"
}
In lefthook.yml
, you can then run these scripts:
pre-commit:
commands:
lint:
run: npm run lint
format:
run: npm run format
pre-push:
commands:
test:
run: npm run test
This separation keeps your YAML config clean and makes it easier to reuse commands across hooks or CI steps.
For CI environments, Git hooks don’t trigger automatically. Instead, use:
npx lefthook run pre-commit
This ensures the same checks run during pull requests or automated pipelines.
What Are Common Use Cases for Lefthook Git Hooks?
Lefthook is typically used for:
- Linting only staged files before commits to avoid full project scans.
- Running tests before pushes to prevent broken code from reaching shared branches.
- Enforcing commit message conventions using
commit-msg
hooks.
Example to check commit messages:
commit-msg:
scripts:
validate:
run: commitlint -E HUSKY_GIT_PARAMS
In monorepos, you can scope hooks to specific packages or apps. For example, lint only changed files in a particular folder:
pre-commit:
commands:
lint-app:
run: npm run lint
include: "apps/app-a/**/*"
This makes Lefthook suitable for large codebases with multiple subprojects or technologies.
How Do You Troubleshoot Lefthook with npm or Git?
If Lefthook doesn’t work, check these:
- Hooks Not Installed: Run
npx lefthook install
again and check.git/hooks
contains Lefthook scripts. - Script Failures: Run commands manually to debug. Example: bashCopyEdit
npx lefthook run pre-commit
- File Permissions: Ensure hook files are executable. On Unix: bashCopyEdit
chmod +x .git/hooks/*
- Environment Issues: Use
DEBUG=lefthook
for verbose output to trace execution problems.
You can also add fail_text
in your config for custom error messages:
pre-commit:
commands:
lint:
run: npm run lint
fail_text: "Linting failed. Please fix before committing."
This improves clarity for teammates and reduces friction during development.
What Are Best Practices for Using Lefthook in Teams?
- Commit your
lefthook.yml
file so all developers share the same logic. - Use npm scripts for any hook logic. Avoid inline shell commands when possible.
- Install Lefthook during
npm install
via theprepare
script. - Use
{staged_files}
to limit tools to changed files only. - Run hooks in CI explicitly to enforce checks, since Git hooks don’t auto-trigger in CI/CD.
Teams benefit most when Lefthook acts as a shared enforcement tool. It replaces tribal knowledge with automation.
How Does Lefthook Compare to Other Git Hook Managers?
Feature | Lefthook | Husky |
---|---|---|
Language Support | Node.js, Ruby, Go | Node.js only |
Speed | Fast, parallel execution | Slower, sequential by default |
Monorepo Support | Native with includes | Requires extra config |
CI Compatibility | Manual run supported | Manual run supported |
Setup Simplicity | Central config | Multiple scripts |
Lefthook is better suited for polyglot and large-scale projects. It also outperforms Husky in execution time and configuration clarity.
FAQs about Lefthook with npm
Is Lefthook compatible with Windows?
Yes. Lefthook works across all major platforms, including Windows, macOS, and Linux. It’s built to be cross-platform out of the box, so no additional setup is required for Windows environments.
Can you use Lefthook without Node.js?
Yes. Although Lefthook is commonly used with npm in JavaScript projects, it also supports Go and Ruby environments. You’re not locked into Node.js, making Lefthook suitable for polyglot or backend-heavy stacks.
Does Lefthook support monorepos?
Yes. Lefthook is built with monorepos in mind. You can scope hook logic using include
and exclude
patterns in the config file. This allows you to run specific checks on individual apps or packages inside a larger codebase.
How do you run Lefthook in CI environments?
Git hooks don’t trigger automatically in CI pipelines, but you can run Lefthook manually using npx lefthook run <hook>
. This ensures that the same validation steps run in both developer machines and CI builds.
Is Lefthook faster than Husky?
Yes. Lefthook is optimized for performance. It executes commands in parallel by default and avoids redundant work by limiting scope to staged files. Teams migrating from Husky often report noticeable speed improvements in large projects.
Summary: How to Use Lefthook with npm Effectively
Use Lefthook by installing the lefthook
npm package, linking it to your Git hooks with npx lefthook install
, and defining hook logic in lefthook.yml
. Combine it with npm scripts for clean integration. Use it in CI with npx lefthook run
. Version your config, use {staged_files}
for efficiency, and automate installation with a prepare
script.
Lefthook gives you full control over Git workflows, with better performance and fewer edge cases than other tools.