Complete guide for integrating commitment with git hooks.
Git hooks allow commitment to generate commit messages automatically when you run git commit. The prepare-commit-msg hook is called before the commit message editor opens, making it perfect for AI-generated messages.
Benefits:
- ✅ Automatic message generation on every commit
- ✅ Preserves your custom messages when using
-m - ✅ No workflow changes - just
git commit - ✅ Works with all git commands (commit, merge, etc.)
The Hook Lifecycle:
git commit
↓
prepare-commit-msg hook runs
↓
commitment generates message
↓
Message written to .git/COMMIT_EDITMSG
↓
Editor opens with generated message
↓
You can edit/accept
↓
Commit created
Automatic setup (recommended):
npx commitment initThis detects your existing hook setup and configures everything automatically.
That's it! Now every git commit will generate an AI message.
The init command automatically detects your hook manager:
npx commitment initDetection Order:
- Checks for
.husky/directory → Uses husky - Checks for
simple-git-hooksin package.json → Uses simple-git-hooks - Falls back to plain git hooks
Output:
$ npx commitment init
🔍 Detecting hook manager...
✅ Found husky installation
📝 Updating .husky/prepare-commit-msg
✅ Hooks installed successfully!
Test with: git commitHusky is the most popular git hook manager for Node.js projects.
npx commitment init --hook-manager huskyWhat this does:
- Installs husky if not present (
npm install -D husky) - Runs
husky install - Creates
.husky/prepare-commit-msg - Makes it executable
1. Install husky:
npm install -D husky
npx husky install2. Add prepare script to package.json:
{
"scripts": {
"prepare": "husky install"
}
}3. Create hook file:
npx husky add .husky/prepare-commit-msg4. Edit .husky/prepare-commit-msg:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# commitment: AI-powered commit messages
# Only run for regular commits (not merge, squash, or when message specified)
if [ -z "$2" ]; then
echo "🤖 Generating commit message..." > /dev/tty 2>/dev/null || true
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fi5. Make executable (Unix-like systems):
chmod +x .husky/prepare-commit-msgHusky runs hooks without a TTY by default. The exec < /dev/tty ensures commitment can:
- Show progress/errors to user
- Handle interactive prompts if needed
- Access terminal for AI agent execution
package.json:
{
"scripts": {
"prepare": "husky install"
},
"devDependencies": {
"husky": "^8.0.0",
"@arittr/commitment": "^1.0.0"
}
}simple-git-hooks is a lightweight alternative to husky.
npx commitment init --hook-manager simple-git-hooksWhat this does:
- Installs simple-git-hooks if not present
- Adds hook configuration to package.json
- Runs
npx simple-git-hooksto install hooks
1. Install simple-git-hooks:
npm install -D simple-git-hooks2. Add to package.json:
{
"scripts": {
"prepare": "simple-git-hooks"
},
"simple-git-hooks": {
"prepare-commit-msg": "[ -z \"$2\" ] && npx @arittr/commitment --message-only > $1"
}
}3. Install hooks:
npm run prepare
# or
npx simple-git-hooksThe hook is a one-liner shell command:
[ -z "$2" ] && npx @arittr/commitment --message-only > $1Breakdown:
[ -z "$2" ]- Check if$2(commit source) is empty&&- If true (regular commit), run commitmentnpx @arittr/commitment --message-only- Generate message> $1- Write to commit message file
Note: Simple-git-hooks doesn't show progress indicators to keep the one-liner simple. For progress feedback, use husky or plain hooks.
No dependencies - uses git's native hook system.
npx commitment init --hook-manager plainWhat this does:
- Creates
.git/hooks/prepare-commit-msg - Makes it executable
- Adds commitment command
1. Create hook file:
touch .git/hooks/prepare-commit-msg
chmod +x .git/hooks/prepare-commit-msg2. Edit .git/hooks/prepare-commit-msg:
#!/bin/sh
# commitment: AI-powered commit messages
# Only run for regular commits (not merge, squash, or when message specified)
if [ -z "$2" ]; then
echo "🤖 Generating commit message..." > /dev/tty 2>/dev/null || true
npx @arittr/commitment --message-only > "$1" || exit 1
fi3. Make executable:
chmod +x .git/hooks/prepare-commit-msg.git/hooks/ is not tracked by git. Team members must run commitment init individually.
✅ Best for: Personal projects, quick prototypes, single-developer repos.
For teams using plain hooks, add to README:
## Setup
1. Clone repository
2. Install dependencies: `npm install`
3. Install hooks: `npx commitment init`Or create a setup script:
#!/bin/bash
# setup.sh
npm install
npx commitment init --hook-manager plain
echo "✅ Setup complete!"| Git Command | Hook Runs? | commitment Runs? | Why |
|---|---|---|---|
git commit |
✅ Yes | ✅ Yes | Regular commit - generate message |
git commit -m "msg" |
✅ Yes | ⏭️ No | Message specified - use user's message |
git commit -F file |
✅ Yes | ⏭️ No | Message from file - use file content |
git commit --amend |
✅ Yes | ⏭️ No | Amending - keep existing message |
git merge |
✅ Yes | ⏭️ No | Merge commit - use merge message |
git revert |
✅ Yes | ⏭️ No | Revert commit - use revert message |
git cherry-pick |
✅ Yes | ⏭️ No | Cherry-pick - use original message |
The hook uses git's $2 parameter (commit source) to decide whether to generate:
if [ -z "$2" ]; then
# $2 is empty → regular commit → generate
echo "🤖 Generating commit message..." > /dev/tty 2>/dev/null || true
npx @arittr/commitment --message-only > "$1"
fiPossible $2 values:
| Value | Meaning | Hook Action |
|---|---|---|
| (empty) | Regular git commit |
Generate message ✅ |
message |
git commit -m "..." |
Skip (use user message) |
template |
git commit -t file |
Skip (use template) |
merge |
Merge commit | Skip (use merge message) |
squash |
Squash commit | Skip (use squash message) |
commit |
git commit --amend |
Skip (keep existing) |
After the hook runs, git opens your editor:
git commit
# Hook generates:
# feat: add user authentication
#
# - Implement JWT token generation
# - Add login endpoint
# - Create middleware
# Editor opens - you can:
# 1. Accept as-is (save and close)
# 2. Edit the message
# 3. Abort (close without saving)Editor Behavior:
- Accept: Save and close → commit created with AI message
- Edit: Modify message, save → commit created with your edits
- Abort: Close without saving → commit cancelled
You can extend the hook with custom logic:
Example: Skip for WIP commits:
#!/bin/sh
# .husky/prepare-commit-msg
# Check if staged changes include WIP
if git diff --cached | grep -q "WIP"; then
# Skip AI generation for work-in-progress
echo "WIP: work in progress" > "$1"
exit 0
fi
# Otherwise generate AI message
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fiExample: Require AI success:
#!/bin/sh
# .husky/prepare-commit-msg
if [ -z "$2" ]; then
# Generate message, fail commit if AI fails
npx @arittr/commitment --message-only > "$1"
if [ $? -ne 0 ]; then
echo "❌ Failed to generate commit message"
exit 1 # Abort commit
fi
fiExample: Fallback to template:
#!/bin/sh
# .husky/prepare-commit-msg
if [ -z "$2" ]; then
# Try AI generation
if ! npx @arittr/commitment --message-only > "$1" 2>/dev/null; then
# If AI fails, use template
cat > "$1" << EOF
feat:
-
EOF
fi
fiForce a specific agent in hooks:
#!/bin/sh
# .husky/prepare-commit-msg
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --agent codex --message-only > "$1" || exit 1
fiAdd timeout to prevent hanging:
#!/bin/sh
# .husky/prepare-commit-msg
if [ -z "$2" ]; then
# 30 second timeout
timeout 30 npx @arittr/commitment --message-only > "$1" || exit 1
fiSkip for certain branches:
#!/bin/sh
# .husky/prepare-commit-msg
BRANCH=$(git symbolic-ref --short HEAD)
# Skip AI for main/master
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
exit 0
fi
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fiSkip for certain file patterns:
#!/bin/sh
# .husky/prepare-commit-msg
# Skip for docs-only changes
if git diff --cached --name-only | grep -v "\.md$" > /dev/null; then
# Has non-markdown changes, use AI
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fi
else
# Only markdown changes, use simple message
echo "docs: update documentation" > "$1"
fi1. Check hook exists:
# For husky
ls -la .husky/prepare-commit-msg
# For plain hooks
ls -la .git/hooks/prepare-commit-msg
# For simple-git-hooks
cat package.json | grep -A 3 "simple-git-hooks"2. Check permissions (Unix-like):
# Should show: -rwxr-xr-x
ls -l .husky/prepare-commit-msg
# Fix permissions
chmod +x .husky/prepare-commit-msg3. Reinstall:
npx commitment init1. Check for errors:
# Run hook manually
.husky/prepare-commit-msg .git/COMMIT_EDITMSG
# or
.git/hooks/prepare-commit-msg .git/COMMIT_EDITMSG
# Check output for errors2. Test commitment directly:
git add .
npx commitment --dry-run3. Check git commit source:
# If using -m, hook skips generation
git commit -m "test" # Hook won't run commitment
# Use without -m
git commit # Hook will run commitmentIssue: Hook script not executable on Windows.
Solution:
Use Git Bash or WSL:
# In Git Bash
chmod +x .husky/prepare-commit-msg
git commitOr ensure git config allows hooks:
git config core.hooksPath .huskyThis should not happen if hooks are configured correctly.
Check hook code:
cat .husky/prepare-commit-msgShould have if [ -z "$2" ] check:
if [ -z "$2" ]; then
npx @arittr/commitment --message-only > "$1"
fiTest:
# Should use your message
git commit -m "my message"
# Should generate AI message
git commitIssue: Hooks run in CI but fail (no TTY, no AI CLI).
Solution 1 - Skip hooks in CI:
# In CI pipeline
git commit --no-verify -m "ci: automated commit"Solution 2 - Detect CI environment:
#!/bin/sh
# .husky/prepare-commit-msg
# Skip in CI
if [ -n "$CI" ]; then
exit 0
fi
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fiSolution 3 - Disable hooks in CI:
# In CI config
git config core.hooksPath /dev/nullAlready using commitment manually? Add hooks:
# Before: Manual every time
git add .
npx commitment
# After: Automatic with hooks
npx commitment init
git add .
git commit # Auto-generated!# Remove old husky
npm uninstall husky@4
# Install new husky
npm install -D husky@8
npx husky install
# Install commitment hooks
npx commitment init --hook-manager husky# Remove pre-commit
pip uninstall pre-commit
rm .pre-commit-config.yaml
# Install husky and commitment
npm install -D husky
npx commitment init --hook-manager husky# Backup existing hooks
cp .git/hooks/prepare-commit-msg .git/hooks/prepare-commit-msg.bak
# Install simple-git-hooks
npm install -D simple-git-hooks
# Setup commitment
npx commitment init --hook-manager simple-git-hooksIf you have custom logic in prepare-commit-msg:
1. Backup existing hook:
cp .husky/prepare-commit-msg .husky/prepare-commit-msg.bak2. Run commitment init:
npx commitment init3. Merge custom logic:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Your custom logic here
npm run lint-staged
# commitment integration
if [ -z "$2" ]; then
exec < /dev/tty && npx @arittr/commitment --message-only > "$1" || exit 1
fiAdd to README:
## Git Hooks
This project uses commitment for automatic commit messages.
Setup: `npx commitment init`Add to onboarding:
#!/bin/bash
# scripts/setup-dev.sh
npm install
npx commitment init
git config commit.template .gitmessage # Optional: custom templateProvide template for when AI fails:
#!/bin/sh
# .husky/prepare-commit-msg
if [ -z "$2" ]; then
if ! exec < /dev/tty npx @arittr/commitment --message-only > "$1" 2>/dev/null; then
# AI failed, use template
cat > "$1" << 'EOF'
# Enter commit message following Conventional Commits:
# feat: add new feature
# fix: fix bug
# docs: update documentation
# style: format code
# refactor: refactor code
# test: add tests
# chore: update tooling
EOF
fi
fi# Skip hook for this commit only
git commit --no-verify
# Or set environment variable
SKIP_COMMITMENT=1 git commitHook can check for this:
#!/bin/sh
if [ -n "$SKIP_COMMITMENT" ]; then
exit 0
fi#!/bin/sh
# .husky/prepare-commit-msg
LOG_FILE=".git/hooks.log"
echo "[$(date)] prepare-commit-msg started" >> "$LOG_FILE"
echo " Args: $*" >> "$LOG_FILE"
if [ -z "$2" ]; then
if exec < /dev/tty npx @arittr/commitment --message-only > "$1" 2>> "$LOG_FILE"; then
echo " Result: Success" >> "$LOG_FILE"
else
echo " Result: Failed ($?)" >> "$LOG_FILE"
exit 1
fi
fiView logs:
cat .git/hooks.log- CLI Reference - Detailed CLI documentation
- README - Main documentation
- Git Hooks Documentation - Official git hooks guide