diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 0000000..d3205e1 --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Enforce Conventional Commits on the first line of the commit message. +# https://www.conventionalcommits.org/en/v1.0.0/ +# +# Activate per clone with: +# git config core.hooksPath .githooks + +set -euo pipefail + +msg_file="${1:?commit-msg: missing message file path}" +first_line="$(awk 'NR==1{print; exit}' "$msg_file")" + +case "$first_line" in + "Merge "*|"Revert "*|"fixup! "*|"squash! "*|"amend! "*) exit 0 ;; +esac + +pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9._-]+\))?!?: .+' + +if ! printf '%s' "$first_line" | grep -qE "$pattern"; then + printf 'commit-msg: aborting — message does not follow Conventional Commits.\n' >&2 + printf ' expected: [()][!]: \n' >&2 + printf ' types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert\n' >&2 + printf ' got: %s\n' "$first_line" >&2 + exit 1 +fi diff --git a/CLAUDE.md b/CLAUDE.md index 5c65203..8baa7ab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,6 +51,11 @@ Code skills used while working in this repo) — don't conflate them. - Research notes live in `docs/research/`. - Low dependencies by default. The project is bash-first; ask before adding new tools, runtimes, or package managers. +- Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/): + `[(scope)][!]: `, where `` is one of `feat`, `fix`, + `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`. + A `commit-msg` hook in `.githooks/` enforces this. Activate it once per clone + with `git config core.hooksPath .githooks`. ## Intended design