evilmartians
lefthook
Go

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

Last updated Jul 8, 2026
8.5k
Stars
276
Forks
68
Issues
+49
Stars/day
Attention Score
93
Language breakdown
No language data available.
Files click to expand
README

Build Status codecov

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

Sponsored by Evil Martians

Install

With Go (>= 1.26):

go install github.com/evilmartians/lefthook/v2@v2.1.10
  • or as a go tool
go get -tool github.com/evilmartians/lefthook/v2@v2.1.10

With NPM:

npm install lefthook --save-dev

For Ruby:

gem install lefthook

For Python:

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

# 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]
pre-push:
  parallel: true
  • ### Flexible list of files
If you want your own list. [Custom][config-files] and [prebuilt][config-run] 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}

  • ### Glob and regexp filters
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}
  • ### Execute in sub-directory
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}
  • ### Run scripts
If oneline commands are not enough, you can execute files. [docs][config-scripts]
commit-msg:
  jobs:
    - script: "template_checker"
      runner: bash
  • ### Tags
If you want to control a group of commands. [docs][config-tags]
pre-push:
  jobs:
    - name: audit packages
      tags:
        - frontend
        - linters
      run: yarn lint

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

  • ### Support Docker
If you are in the Docker environment. [docs][config-run]
pre-commit:
  jobs:
    - script: "good_job.js"
      runner: docker run -it --rm <containeridor_name> {cmd}
  • ### Local config
If you are a frontend/backend developer and want to skip unnecessary commands or override something in Docker. [docs][usage-local-config]
# lefthook-local.yml
pre-push:
  exclude_tags:
    - frontend
  jobs:
    - name: audit packages
      skip: true
  • ### Direct control
If you want to run hooks group directly.
$ lefthook run pre-commit
  • ### Your own tasks
If 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 fixer
  • ### Control output
You can control what lefthook prints with [output][config-output] option.
output:
  - execution
  - failure

Guides

  • [Install with Node.js][install-node]
  • [Install with Ruby][install-ruby]
  • [Install with Homebrew][install-brew]
  • [Install with Winget][install-winget]
  • [Install for Debian-based Linux][install-apt]
  • [Install for RPM-based Linux][install-rpm]
  • [Install for Arch Linux][install-arch]
  • [Install for Alpine Linux][install-alpine]
  • [Usage][usage]
  • [Configuration][configuration]

Examples

Check [examples][examples]

Articles

[documentation]: https://lefthook.dev/ [configuration]: https://lefthook.dev/configuration/index [examples]: https://lefthook.dev/examples/lefthook-local [installation]: https://lefthook.dev/install/ [usage]: https://lefthook.dev/usage/ [discussion]: https://github.com/evilmartians/lefthook/discussions [install-apt]: https://lefthook.dev/installation/deb [install-ruby]: https://lefthook.dev/installation/ruby [install-node]: https://lefthook.dev/installation/node [install-brew]: https://lefthook.dev/installation/homebrew [install-winget]: https://lefthook.dev/installation/winget [install-rpm]: https://lefthook.dev/installation/rpm [install-arch]: https://lefthook.dev/installation/arch [install-alpine]: https://lefthook.dev/installation/alpine [config-parallel]: https://lefthook.dev/configuration/parallel [config-files]: https://lefthook.dev/configuration/files [config-glob]: https://lefthook.dev/configuration/glob [config-run]: https://lefthook.dev/configuration/run [config-scripts]: https://lefthook.dev/configuration/Scripts [config-tags]: https://lefthook.dev/configuration/tags [config-output]: https://lefthook.dev/configuration/output [usage-local-config]: https://lefthook.dev/examples/lefthook-local

🔗 More in this category

© 2026 GitRepoTrend · evilmartians/lefthook · Updated daily from GitHub