evilmartians /lefthook

Fast and powerful Git hooks manager for any type of projects.

★ 8,990⑂ 333👁 30⑃ 789● 493▤ 228
GoCreated 2019-02-05lefthook.dev/
8,990
stars
+0+11+98
333
forks
30
watchers
789
prs
493
issues
228
releases
–
discussions

README

!Build Status


 Lefthook



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.

📖 Introduction post

 Lefthook is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.

 Install

With Go (= 1.27):

bash
go install github.com/evilmartians/lefthook/[email protected]


 or as a go tool

bash
go get -tool github.com/evilmartians/lefthook/[email protected]


With NPM:

bash
npm install lefthook --save-dev


For Ruby:

bash
gem install lefthook


For Python:

bash
pipx install lefthook


[Installation guide][installation] with more ways to install lefthook: [apt][install-apt], [brew][install-brew], [winget][install-winget], and others.

 Usage

Configure your hooks, install them once and forget about it: rely on the magic underneath.

 TL;DR

bash
 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 '...'


 More details

- [Configuration][configuration] for lefthook.yml config options.
- [Usage][usage] for lefthook CLI options, and features.
- [Discussions][discussion] for questions, ideas, suggestions.


 Why Lefthook

  Parallel execution
Gives you more speed. [docs][config-parallel]

yml
pre-push:
  parallel: true


  Flexible list of files
If you want your own list. [Custom][config-files] and [prebuilt][config-run] examples.

yml
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}


  Glob and regexp filters
If you want to filter list of files. You could find more glob pattern examples here.

yml
pre-commit:
  jobs:
    - name: lint backend
      glob: ".rb"  glob filter
      exclude:
        - "/application.rb"
        - "/routes.rb"
      run: bundle exec rubocop --force-exclusion -- {all_files}


  Execute in sub-directory
If you want to execute the commands in a relative path

yml
pre-commit:
  jobs:
    - name: lint backend
      root: "api/"  Careful to have only trailing slash
      glob: ".rb"  glob filter
      run: bundle exec rubocop -- {all_files}


  Run scripts

If oneline commands are not enough, you can execute files. [docs][config-scripts]

yml
commit-msg:
  jobs:
    - script: "template_checker"
      runner: bash


  Tags
If you want to control a group of commands. [docs][config-tags]

yml
pre-push:
  jobs:
    - name: audit packages
      tags:
        - frontend
        - linters
      run: yarn lint

    - name: audit gems
      tags:
        - backend
        - security
      run: bundle audit


  Support D

Snapshot: 2026-11-04T14:00:00Z · Data license Apache-2.0 · JSON