Issue 06 | /caveman-commit β Bringing Git Commit Messages Back to Basics
π― Learning Objectives
After this issue, you will master:
- The output rules and format specifications of
/caveman-commit - The "Why over What" principle β why is more important than what
- How to use caveman-commit on five major platforms
- Automatic integration with Git Hook (prepare-commit-msg)
π Core Content
6.1 Why Do Commit Messages Need Caveman?
Have you seen commit messages like this?
β Bad commit (real case):
"Updated the authentication middleware to properly validate token
expiry by checking if the token's expiration timestamp is less than
or equal to the current time instead of using a strict less-than
comparison, which was causing tokens that expire at exactly the
current second to not be properly caught and rejected"
This isn't a commit message; it's a thesis abstract.
Caveman Style:
β
fix(auth): token expiry use <= not <
13 characters. The same information. Perfectly displayed in git log --oneline.
6.2 Three Rules of caveman-commit
graph TD
A["caveman-commit Rules"]
A --> B["π Length Constraint
Subject Line β€ 50 characters"]
A --> C["π Format Specification
Conventional Commits"]
A --> D["π§ Content Principle
Why over What"]
B --> B1["git log --oneline perfectly aligned
Not truncated"]
C --> C1["type(scope): message
feat/fix/docs/chore/refactor"]
D --> D1["Explain 'Why'
not 'What'"]Rule 1: Conventional Commits Format
<type>(<scope>): <description>
type enumeration:
feat β New feature
fix β Bug fix
docs β Documentation changes
chore β Chores (dependency updates, config, etc.)
refactor β Refactoring (no behavior change)
perf β Performance improvement
test β Tests
ci β CI/CD changes
style β Code style (no logic impact)
Rule 2: Subject Line β€ 50 characters
β
fix(auth): token expiry use <= not < (38 chars)
β
feat(api): add rate limiting per user (39 chars)
β
refactor(db): extract query builder (40 chars)
β feat(api): add comprehensive rate limiting mechanism with sliding window (73 chars β Truncated!)
Rule 3: Why over What
β What (describes what was done β already visible in code):
"change < to <= in token check"
β
Why (explains why it was done β not visible in code):
"fix(auth): token expiry use <= not <"
β Implies "because of boundary conditions, tokens were allowed to pass at the exact moment of expiry"
β What:
"add try-catch around database call"
β
Why:
"fix(db): handle connection timeout gracefully"
6.3 Usage
In Claude Code
# After completing code modifications
> /caveman-commit
# Claude will analyze your staged changes and generate:
# fix(auth): token expiry use <= not <
#
# Then you can:
> Commit with this message
# Or
> git commit -m "fix(auth): token expiry use <= not <"
In Antigravity
# Natural language trigger
> Help me write a commit message in caveman-commit style
# Or after configuring caveman rules in GEMINI.md:
> Analyze my changes and write a concise commit message
In Gemini CLI
> /caveman-commit
# Gemini will analyze the current diff and output a concise commit message
In Codex
> $caveman-commit
# Codex uses the $ prefix to trigger skills
In OpenCode
# Natural language trigger (no slash command)
> Write a commit message in caveman style, analyze current staged changes
6.4 Practical Before / After Comparison
| Scenario | β Normal Claude | β Caveman Commit |
|---|---|---|
| Fix login Bug | "Fixed a bug where users couldn't log in when their password contained special characters by properly escaping the input" | fix(auth): escape special chars in password |
| Add dark mode | "Added dark mode support to the application with a toggle button in the settings page and automatic detection of system preferences" | feat(ui): dark mode + system pref detect |
| Refactor database layer | "Refactored the database access layer to use the repository pattern instead of direct queries for better testability and maintainability" | refactor(db): repository pattern for testability |
| Update dependencies | "Updated React from version 18.2 to 19.0 and fixed breaking changes in the useEffect cleanup timing" | chore(deps): react 19 + fix effect cleanup |
| Fix CSS layout | "Fixed the mobile responsive layout issue where the sidebar was overlapping the main content area on screens smaller than 768px" | fix(layout): sidebar overlap on mobile <768px |
6.5 Automatic Integration with Git Hook
You can combine caveman-commit with Git's prepare-commit-msg Hook for automation:
#!/bin/bash
# .git/hooks/prepare-commit-msg
# Skip if it's a merge commit or amend
case "$2" in
merge|squash) exit 0 ;;
esac
# Skip if commit message already has content (not a template)
if [ -s "$1" ] && [ "$(head -1 "$1")" != "" ]; then
exit 0
fi
# Get diff of staged changes
DIFF=$(git diff --cached --stat)
# Use Claude Code to generate caveman-style commit message
# (requires claude CLI in PATH)
MSG=$(echo "Generate a caveman-commit message for this diff. Rules: Conventional Commits, β€50 chars, why over what. Diff: $DIFF" | claude --print 2>/dev/null)
if [ -n "$MSG" ]; then
echo "$MSG" > "$1"
fi
graph LR
A["git commit"] --> B["prepare-commit-msg Hook"]
B --> C["Read staged diff"]
C --> D["Call Agent
Generate caveman-commit"]
D --> E["Write commit message"]
E --> F["Open editor
(editable)"]
F --> G["β
Commit complete"]π Five Platforms Commit Workflow Comparison
| Dimension | Claude Code | Antigravity | Gemini CLI | Codex | OpenCode |
|---|---|---|---|---|---|
| Trigger Command | /caveman-commit |
Natural language | /caveman-commit |
$caveman-commit |
Natural language |
| Automatically read diff | β
git diff --cached |
β | β | β | β |
| Directly execute commit | β Can be requested | β οΈ Requires confirmation | β Can be requested | β Can be requested | β οΈ Requires confirmation |
| Git Hook Integration | β Native support | β Manual setup required | β οΈ Limited | β hooks.json | β Manual setup required |
| Batch multiple commits | β | β | β | β | β |
π Key Takeaways
/caveman-commitgenerates concise commit messages in Conventional Commits format- Three rules: β€50 character subject line + Conventional Commits + Why over What
- All platforms support it, but trigger methods differ (Claude Code uses
/, Codex uses$, others use natural language) - Can be integrated with Git's
prepare-commit-msgHook for automation - Key principle: commit messages should tell the reader "why" rather than "what"