# What changed in lefthook

> 76 changes in lefthook 2 from its official release notes, upgrade guides and advisories: 7 breaking, 12 new APIs and options. Each one cited. Sources checked 2026-10-18. HTML: https://unstale.sh/npm/lefthook/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## lefthook 2

### Breaking changes

- Color blending is removed. (2.1.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.15)
- The hook now fails when staging fixed files errors. (2.1.12) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.12)
- The minimum required Go version was updated. (2.1.3) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.3)
- Custom hooks are no longer installed to the hooks directory. (2.0.14) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.14)
- Custom templates are no longer escaped in command replacement. (2.0.8) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.8)
- Support for exclude regexp has been dropped. (2.0.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.0)
- The deprecated skip_output option is no longer supported. (2.0.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.0)

### New APIs and options

- Packaging now supports Android. (2.2.2) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.2)
- Adds support for PHP Composer. (2.2.1) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.1)
- Adds integration with AI coding agents. (2.1.10) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.10)
- Introduces a setup hook option. (2.1.2) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.2)
- Allows installing hooks in non-Git repositories. (2.1.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.0)
- A timeout argument was added. (2.0.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.16)
- JSONC support was added, allowing configuration in JSONC format. (2.0.14) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.14)
- Adds the ability to show a diff when failing on changes. (2.0.12) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.12)
- Adds no_auto_install to lefthook.yml to control automatic installation. (2.0.10) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.10)
- Scripts can now accept optional arguments, allowing developers to pass arguments when using them. (2.0.5) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.5)
- Adds an optional standard glob matcher, doublestar, for configuring glob matching. (2.0.4) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.4)
- Adds the fail_on_changes option for non-CI environments. (2.0.3) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.3)

### Performance

- A ghost hook is skipped when hooks are already configured. (2.0.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.16)

### Behavior and default changes

- Install no longer writes an install-time lefthook path into AI hook configs. (2.2.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.0)
- Push files are diffed against the merge base with the default branch. (2.1.17) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.17)
- Forced colors are propagated to hook commands via CLICOLOR_FORCE. (2.1.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.15)
- Hints from lefthook install are less verbose. (2.1.1) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.1)
- Checks core.hooksPath when installing hooks. (2.1.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.0)
- Python wheels now contain one binary per platform. (2.0.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.16)
- Scripts are skipped when arguments are given with an empty file template. (2.0.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.15)
- Refetches and cleans up when the ref changes. (2.0.11) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.11)
- Lefthook now prefers using the executable found in $PATH. (2.0.7) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.7)
- Hooks now save the original executable location. (2.0.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.6)
- Windows uses sh as the command executor. (2.0.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.0)

### Tooling

- Adds rudimentary shell completions for Lefthook commands. (2.0.11) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.11)

### Fixes and other changes

- Cleanup now removes only the current stash hash, avoiding cleanup of other stashes. (2.2.2) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.2)
- Generates different patch names when running in a worktree. (2.2.1) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.1)
- The flag now ignores a trailing NUL. (2.2.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.0)
- The --output path is now passed to git diff as a single argument. (2.2.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.2.0)
- Submodules are no longer hashed when checking fail_on_changes. (2.1.17) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.17)
- Preserves unrelated unstaged changes when a conflict occurs. (2.1.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.16)
- Fixes staging fixed files when files are partially staged. (2.1.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.16)
- Paths in the generated hook shim are quoted. (2.1.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.15)
- Stdin is no longer piped into the post-checkout git-lfs hook. (2.1.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.15)
- The push-files fallback now resolves against the remote-tracking ref. (2.1.15) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.15)
- Fixed precedence for LEFTHOOK_OUTPUT. (2.1.12) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.12)
- PTY commands inherit the terminal size. (2.1.11) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.11)
- Updates the hooks path after resetting. (2.1.9) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.9)
- Lefthook no longer warns when the local hooks path equals the default hooks path. (2.1.8) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.8)
- Colors are changed to provide contrast. (2.1.7) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.7)
- The fallback push branch is separated from pathspecs. (2.1.7) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.7)
- The stage_fixed behavior is applied only when it is safe. (2.1.7) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.7)
- Unstaged changes are now always restored, preventing them from being lost during hook execution. (2.1.7) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.7)
- Skips PTY allocation when stdout is not a terminal. (2.1.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.6)
- Ensures root includes a trailing slash before path replacement. (2.1.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.6)
- Logs the full scoped name for skipped jobs. (2.1.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.6)
- Packaging no longer pipes stdout and stderr. (2.1.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.6)
- Normalizes the lefthook path used for the sh script on Windows. (2.1.6) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.6)
- Fixes an issue involving Git repository merges. (2.1.5) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.5)
- Prevents lefthook run from overwriting global hooks. (2.1.5) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.5)
- Uses pre-push stdin for push file detection. (2.1.5) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.5)
- Separates non-option arguments with -- in more commands. (2.1.4) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.4)
- Restores the {lefthook_job_name} template. (2.1.4) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.4)
- Support for Git debug versions was fixed. (2.1.3) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.3)
- Auto-staged changes are rolled back if unwanted changes are detected. (2.1.2) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.2)
- Colors are reset when reading configuration. (2.1.1) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.1.1)
- The JSON schema now accepts a string for file_types. (2.0.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.16)
- A direct file is read instead of reading all remotes. (2.0.16) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.16)
- Execution is skipped if an any-files template is empty. (2.0.14) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.14)
- The JSON schema now allows custom hooks, so configurations using them can be validated against the schema. (2.0.13) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.13)
- The extends value is set to an empty slice after loading remotes. (2.0.13) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.13)
- Makes the Git short status parser more robust. (2.0.12) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.12)
- Skips the template when the files are empty. (2.0.10) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.10)
- Improves separation of options and filenames for more git commands. (2.0.9) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.9)
- The pre-commit hook is skipped when there are no staged files. (2.0.9) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.9)
- Scanner errors are now checked and reported. (2.0.9) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.9)
- Fixes the JSON Schema values for glob_matcher. (2.0.4) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.4)
- Adds a mutex lock before all git commands. (2.0.2) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.2)
- The CLI accepts --fail-on-changes=false as an override value. (2.0.0) — [release notes](https://github.com/evilmartians/lefthook/releases/tag/v2.0.0)
