lefthook
Lefthook
Create or update Lefthook configuration with exact option names, practical defaults, and clear debugging steps. Explain the tool briefly, then produce a working config for the current repository.
Use this skill when the task mentions:
lefthook.yml,.lefthook.yml,.config/lefthook.yml,lefthook-local.yml, or anotherlefthook-local.*file- Git hooks such as
pre-commit,commit-msg,pre-push,post-merge, orpost-checkout lefthook install,lefthook run,lefthook dump, orlefthook validate- choosing between
commands,jobs, andscripts - placeholders such as
{staged_files},{push_files},{all_files},{files}, or{1} - hook bugs such as commands not running, wrong files matching, fixed files not restaged, or local-only wrappers leaking into shared config
Non-Negotiables
- Inspect the repository before writing config. Reuse the existing config filename and format if one already exists.
- Match hook commands to the repo's real toolchain. Reuse existing package manager commands, scripts, and linters instead of inventing wrappers.
- Choose the simplest structure that fits. Use
commandsby default,jobsfor ordering or grouping, andscriptsonly for executable hook files. - Use placeholders and filters that match the hook type.
pre-commitusually wants{staged_files},pre-pushusually wants{push_files}, andcommit-msgusually wants{1}. - Add
stage_fixed: trueonly for commands that rewrite tracked files and should re-stage them. - Put local-only skips, Docker wrappers, and private overrides in
lefthook-local.*, not in the shared team config. - When debugging or reviewing, use
lefthook validate,lefthook dump, andlefthook run <hook>before guessing.
Start Here
Inspect the repository before writing anything.
- Look for existing config files first:
lefthook.yml,.lefthook.yml,.config/lefthook.yml,lefthook.yaml,lefthook.toml,lefthook.json,lefthook.jsonc, and matchinglefthook-local.*overrides. - Preserve the existing format and naming if a config already exists.
- Prefer YAML
lefthook.ymlfor new setups unless the repo already standardizes on TOML, JSON, or JSONC. - Read package manager files, script directories, and CI or lint tooling before proposing hook commands.
- Keep one main format per project. Do not introduce a second main Lefthook config format.
Author Configs
Choose the simplest structure that fits the workflow.
- Use
commandsfor the default case: straightforward named tasks such as linting, formatting, tests, or commit message checks. - Use
jobswhen order, grouping,parallel,piped, mixedrunandscriptentries, or merge-friendly named jobs matter. - Use
scriptsonly when the repository already uses executable files undersource_dir/<hook>/or when the user explicitly wants file-based scripts. - Prefer hook names that match real Git hooks such as
pre-commit,commit-msg, andpre-push. It is also valid to define custom task groups and run them throughlefthook run <name>. - Keep commands local to the repo toolchain. Reuse existing
npm,pnpm,yarn,bun,go,bundle,uv, or shell commands instead of inventing new wrappers. - Use file templates deliberately:
{staged_files}forpre-commit,{push_files}forpre-push,{all_files}for whole-repo checks,{files}when a customfiles:command is defined,{cmd}for local wrapping, and{1}for hook arguments such ascommit-msg. - Add
stage_fixed: trueonly when the command actually rewrites tracked files and should re-stage them. - Use
glob,exclude,file_types, androotto keep commands narrow and fast. - Reach for
lefthook-local.*when the user wants local-only skips, Docker wrappers, or private overrides that should not change the shared team config.
Integrated example for a JS or TS repo that already uses ESLint, Prettier, and Commitlint:
pre-commit:
commands:
eslint:
glob: "*.{js,jsx,ts,tsx}"
run: pnpm eslint --fix {staged_files}
stage_fixed: true
prettier:
glob: "*.{js,jsx,ts,tsx,json,md,yml,yaml}"
run: pnpm prettier --write {staged_files}
stage_fixed: true
commit-msg:
commands:
commitlint:
run: pnpm commitlint --edit {1}
Why this shape:
commandsis enough because each task is independent.pre-commituses{staged_files}because the checks should scope to the staged set.commit-msguses{1}because Git passes the commit message file path as the first hook argument.- Both formatters set
stage_fixed: truebecause they rewrite tracked files.
Read overview.md for install and command flow, config-model.md for structure and merge behavior, patterns.md for common recipes, best-practices.md when the user asks for battle-tested guidance, and schema-cheatsheet.md for exact keys.
Explain And Debug
Explain Lefthook in terms of repository behavior, not marketing.
- Describe it as a Git hook manager that reads config on each run and executes repo-defined commands or scripts.
- Mention that
lefthook installinstalls Git hook entrypoints and creates an empty config if none exists. - Mention that config changes do not require reinstall in normal cases because hooks read config each time they run.
- Use
lefthook validateto check configuration validity. - Use
lefthook dumpto inspect the effective merged config afterextends,remotes, andlefthook-local.*. - Use
lefthook run <hook>with--all-files,--file,--job, or--tagto reproduce hook behavior outsidegit commitorgit push. - Explain merge precedence as: main config, then
extends, thenremotes, thenlefthook-local.*. - When using the phrase "best practice", ground exact behavior in the bundled docs and schema, and treat blog-derived patterns as workflow guidance rather than hard requirements.
When reviewing an existing config, call out:
- commands that will not match any files because placeholders and filters do not align;
- rewriters that forgot
stage_fixed: true; - file-wide commands incorrectly using
{staged_files}; - unnecessary complexity where
commandswould be enough; - local overrides that should live in
lefthook-local.*instead of shared config.
Use Bundled Resources
- For a quick starting point, copy
assets/minimal-pre-commit.yml. For JS or TS repos, copyassets/js-ts-pre-commit.yml. Then adapt the package manager and commands to the repo. - Load
references/patterns.mdfor concrete recipes before drafting a non-trivial config. - Load
references/best-practices.mdwhen the user explicitly asks for recommendations or wants rationale backed by real-world Lefthook usage. - Load
references/schema-cheatsheet.mdwhen exact option spelling or allowed nesting matters. - Keep explanations compact in the final answer. Include only the options that matter for the current repository.