Thank you for your interest in contributing! This document covers everything you need to know to get changes merged.
All changes — including from maintainers — must go through a pull request. Direct pushes to main are not allowed. Every PR runs automated checks via GitHub Actions to validate shell syntax and script integrity before merging.
git clone git@github.com:rootstrap/ai-git-hooks.git
cd ai-git-hooksNo dependencies to install — the project is pure shell scripts and YAML.
This project uses Conventional Commits.
release-please reads your commit messages to determine version bumps and
generate the changelog automatically, so following the convention is important.
| Prefix | When to use | Version bump |
|---|---|---|
fix: |
Bug fix in the hook or installer | Patch |
feat: |
New feature or template | Minor |
feat!: or fix!: |
Breaking change | Major |
docs: |
Documentation only | None |
chore: |
Maintenance, config, CI | None |
refactor: |
Code restructure, no behaviour change | None |
Examples:
feat: add python template
fix: handle filenames with spaces in tool runner
docs: add troubleshooting section to README
feat!: require Claude Code CLI — remove fallback to allow push
Templates live in templates/ and are downloaded by install.sh when a user
passes --template <name>. To add one:
- Create
templates/<name>.ymlbased on an existing template - Populate the
tools:section with the stack's standard linters and test runners - Add appropriate
ignore_paths:for generated or vendored files - Add a row to the templates table in
README.md - Add the new template name to the
--templateusage comment ininstall.sh
Keep templates self-contained — no inheritance, no references to other files. Each template should be a ready-to-use starting point that a developer can commit as-is and customise from there.
hook/pre-push has been hardened over many iterations. Before making changes:
- Run
bash -n hook/pre-pushto validate syntax before committing - Avoid
eval, heredoc variable expansion, and unquoted variable interpolation - File lists must always be passed as arrays, never as interpolated strings
- Test on both macOS (BSD tools) and Linux (GNU tools) if possible —
sed,grep, andprintfbehave differently between them
install.sh follows the same shell safety rules as the hook. Additionally:
- It must work when piped through
bash(curl ... | bash) - It must not assume any tools beyond
bash,curl, andgitare available
There is no automated test suite yet. To test manually:
# Validate shell syntax
bash -n hook/pre-push
bash -n install.sh
# Test the installer locally (from inside a git repo)
bash install.sh --template node
# Test the hook by installing it and making a push
bash install.sh --template node
git pushFor template changes, install the template into a representative project and verify the configured tools run correctly against changed files.
-
bash -n hook/pre-pushpasses with no output -
bash -n install.shpasses with no output - Commit messages follow Conventional Commits
- New templates include all keys from an existing template
-
README.mdupdated if a new template was added -
install.shusage comment updated if a new template was added
Releases are fully automated via release-please. When your PR is merged to
main, release-please analyses the commit messages and opens a Release PR if
there is anything releasable. Merging the Release PR creates the GitHub Release
and git tag automatically — you don't need to do anything manually.