| name | lefthook |
| description | Canonical lefthook git-hooks setup — pre-commit (format, check, secret scan) and pre-push (test), each delegating to `mise run` tasks. Use when configuring or debugging git hooks. |
| metadata | {"author":"Médéric HURIER (Fmind)","source":"github.com/fmind/dotfiles/tree/main/skills/lefthook","created":"2026-07-04T00:00:00.000Z","updated":"2026-07-06T00:00:00.000Z"} |
Lefthook Git Hooks Standard
Canonical git-hooks setup using lefthook. Keep hooks thin by delegating every command to a mise run task, so local hooks and CI run the exact same checks. Lefthook decides when to run; mise owns what each command does.
Principles
- pre-commit (fast): format staged files, then run the static checks and secret scan.
- pre-push (slower): the test suite.
- Delegate, don't duplicate: every command is a thin
mise run <task>; the command name mirrors the task (format:go → mise run format:go). Tasks are owned by the language stack (go-stack, python-stack) — see the mise skill.
- Staged formatters, whole-tree checks: formatters take
{staged_files} and restage their fixes (stage_fixed: true); check/test take no files so they always run on the whole tree — "run everything before commit/push".
- Clean output: suppress version headers and successful commands to keep commits quiet and distraction-free.
Setup
- Add lefthook using mise (Go: go-stack; Python: python-stack).
- Create
lefthook.yml at the repo root (template below).
- Install the hooks:
lefthook install (wired into mise run install).
Template
pre-commit:
parallel: false
commands:
format:dprint:
glob: "*.{json,md,toml,yaml,yml}"
run: mise run format:dprint {staged_files}
stage_fixed: true
format:<lang>:
glob: "*.<ext>"
run: mise run format:<lang> {staged_files}
stage_fixed: true
check:leaks:
run: mise run check:leaks --staged
check:
run: mise run check
pre-push:
commands:
test:
run: mise run test
See the reference lefthook.yml in go-stack and python-stack.
Gotchas
- Thin hooks: never inline tool commands; call
mise run <task> so CI stays identical.
- Ordering: lefthook runs a hook's commands alphabetically by name, not in file order — so
check sorts before format:* and, left unordered, runs first and fails on still-unformatted files. Set explicit priority (formatters low, check high) with parallel: false so formatters restage before check reads from disk.
- Bypass: avoid
--no-verify; fix the failure instead — the git-add-commit-push skill auto-heals hook failures.
- Unstaged changes: Lefthook stashes unstaged changes automatically under the hood to prevent accidental commits of unstaged changes when formatting.
Documentation