core.hooksPath makes this hook global to every repo, which is why it is tracked and travels — and why it must hold no repo knowledge. A repo opts in by declaring `.precommit-triggers` at its root: staged pathspecs on the left, a command on the right. If the staged diff touches a declared pathspec the command runs, and a non-zero exit refuses the commit. Three decisions worth stating rather than leaving to be rediscovered: Path matching is delegated to `git diff --cached --name-only -- <pathspec>` rather than reimplemented, so declarations use the pathspec syntax the repo's users already know and globs behave as they do everywhere else in git. The declaration file is read on fd 3, so a declared check that reads stdin cannot swallow the remainder of the rules. It is dependency-free by design — no yq, no python. A global convention that needs a toolchain silently fails to travel to the next machine, and a check that silently does not run is worse than no check, because its absence reads as a pass. This is a deliberate departure from the YAML used by data that python tools consume. Scope: this is a tripwire, not an enforcement boundary. --no-verify steps over it, and the message says so. It is worth having because the failure mode it addresses is forgetting, not evading. First consumer: studium-engine, where a corpus edit invalidates engine fixtures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A35wiD55yRHj5U1ECZAX4t
Git Hooks
This directory contains global git hooks that can be used across all repositories.
Setup
- Configure git to use this directory for hooks:
git config --global core.hooksPath ~/dotfiles/git/hooks
- Make hooks executable:
chmod +x ~/dotfiles/git/hooks/*
Available Hooks
pre-commit: Run before each commitcommit-msg: Validate commit messagespre-push: Run before pushing
Per-Repository Hooks
To use repository-specific hooks instead of global ones:
git config --local core.hooksPath .git/hooks