Contributing¶
The canonical entry point for adding a hook, changing an existing one, or
updating the rendered docs.
CLAUDE.md
records the same conventions for AI-assisted edits. Keep both documents in
sync when the contract changes.
Hook conventions¶
Every hook follows the same contract. Keep it intact when editing or adding hooks.
- One script per hook. Each hook is a self-contained script under
hooks/, named after its hook ID (hooks/<id>.sh). No runtime dependencies beyondgitand a POSIX-ish shell;set -euo pipefailat the top. - Registered in the manifest. Every hook has a stable
id, a humanname, adescription, andlanguage: scriptin.pre-commit-hooks.yaml. - Fail open in automation. Hooks short-circuit to exit 0 when
CIis set, so the same hook installed locally never blocks a CI lint job. - Tunable via
args:. Expose tunable inputs through pre-commitargs:(for example--branch <name>), parsed defensively with a sensible default. Don't hard-code a portfolio-specific value that amain-integrating repository can't override.
Self-test contract¶
Every hook has a matching self-test under tests/test_<id>.sh. The test
builds throwaway git repositories under tests/.sandbox/, drives HEAD
into a known state, runs the hook, and asserts on its exit code — no
network, no global git side effects.
task test # run the hook self-tests
tests/test_guard-primary-checkout.sh # run one suite directly
Run the whole suite before changing a hook, and add cases for any new behaviour or argument.
Local checks¶
task # list available tasks
task lint # run every pre-commit hook (shellcheck, hygiene, the guard)
task test # run the hook self-tests
task docs # serve the mkdocs site locally
task lint and task docs delegate to the remote
nolte/taskfiles modules and depend
on the pre-provisioned virtual environments at ~/.venvs/development and
~/.venvs/docs. When a venv is missing, the task fails on the first run;
the fix is to provision the venv, not to inline pip install.
Documentation conventions¶
mkdocs-include-markdown-pluginpulls the intro block from the README into the rendered home page through the<!--intro-start-->and<!--intro-end-->markers. Keep those markers in place.- Every hook gets a page under
docs/en/references/hooks/(and the matching translation underdocs/de/references/hooks/) with the same schema: short intro, Prerequisites, Arguments, Behaviour, Example, Troubleshooting. - New hook names and technical terms go into the local Vale vocabulary at
.github/styles/config/vocabularies/pre-commit-hooks/accept.txt; otherwise the spelling-vale workflow fails on the first prose mention.
Pull request flow¶
- Branch off
developin a dedicated worktree — the same parallel working-copies model theguard-primary-checkouthook enforces. The primary checkout stays ondevelop. - Pull requests run the reusable workflows from
nolte/gh-plumbingat a pinned tag (currentlyv1.1.18). Bump every workflow reference together when updating the pin. - Merges are squash-only and automerge once checks pass. Renovate-driven dependency bumps follow the same path.
- Prose changes have to pass Vale (Microsoft + RedHat plus the
nolte/vale-stylepack and the localpre-commit-hooksvocabulary).