A Git hooks manager for Node.js, Ruby, Python and many other types of projects.
- Fast. It is written in Go. Can run commands in parallel.
 - Powerful. It allows to control execution and files you pass to your commands.
 - Simple. It is single dependency-free binary which can work in any environment.
 
With Go (>= 1.25):
go install github.com/evilmartians/lefthook/[email protected]- or as a go tool
 
go get -tool github.com/evilmartians/lefthookWith NPM:
npm install lefthook --save-devFor Ruby:
gem install lefthookFor Python:
pip install lefthookInstallation guide with more ways to install lefthook: apt, brew, winget, and others.
Configure your hooks, install them once and forget about it: rely on the magic underneath.
# Configure your hooks
vim lefthook.yml
# Install them to the git project
lefthook install
# Enjoy your work with git
git add -A && git commit -m '...'- Configuration for 
lefthook.ymlconfig options. - Usage for lefthook CLI options, and features.
 - Discussions for questions, ideas, suggestions.
 
Gives you more speed. docs
pre-push:
  parallel: trueIf you want your own list. Custom and prebuilt examples.
pre-commit:
  jobs:
    - name: lint frontend
      run: yarn eslint {staged_files}
    - name: lint backend
      run: bundle exec rubocop --force-exclusion {all_files}
    - name: stylelint frontend
      files: git diff --name-only HEAD @{push}
      run: yarn stylelint {files}If you want to filter list of files. You could find more glob pattern examples here.
pre-commit:
  jobs:
    - name: lint backend
      glob: "*.rb" # glob filter
      exclude:
        - "*/application.rb"
        - "*/routes.rb"
      run: bundle exec rubocop --force-exclusion {all_files}If you want to execute the commands in a relative path
pre-commit:
  jobs:
    - name: lint backend
      root: "api/" # Careful to have only trailing slash
      glob: "*.rb" # glob filter
      run: bundle exec rubocop {all_files}If oneline commands are not enough, you can execute files. docs
commit-msg:
  jobs:
    - script: "template_checker"
      runner: bashIf you want to control a group of commands. docs
pre-push:
  jobs:
    - name: audit packages
      tags:
        - frontend
        - linters
      run: yarn lint
    - name: audit gems
      tags:
        - backend
        - security
      run: bundle auditIf you are in the Docker environment. docs
pre-commit:
  jobs:
    - script: "good_job.js"
      runner: docker run -it --rm <container_id_or_name> {cmd}If you are a frontend/backend developer and want to skip unnecessary commands or override something in Docker. docs
# lefthook-local.yml
pre-push:
  exclude_tags:
    - frontend
  jobs:
    - name: audit packages
      skip: trueIf you want to run hooks group directly.
$ lefthook run pre-commitIf you want to run specific group of commands directly.
fixer:
  jobs:
    - run: bundle exec rubocop --force-exclusion --safe-auto-correct {staged_files}
    - run: yarn eslint --fix {staged_files}$ lefthook run fixerYou can control what lefthook prints with output option.
output:
  - execution
  - failure- Install with Node.js
 - Install with Ruby
 - Install with Homebrew
 - Install with Winget
 - Install for Debian-based Linux
 - Install for RPM-based Linux
 - Install for Arch Linux
 - Install for Alpine Linux
 - Usage
 - Configuration
 
Check examples
- 5 cool (and surprising) ways to configure Lefthook for automation joy
 - Lefthook: Knock your team’s code back into shape
 - Lefthook + Crystalball
 - Keeping OSS documentation in check with docsify, Lefthook, and friends
 - Automatically linting docker containers
 - Smooth PostgreSQL upgrades in DockerDev environments with Lefthook
 - Lefthook for React/React Native apps