| name | commit |
| description | Conventional commit message generator for jj and git repos. Analyzes diffs and produces scoped, well-formed commit messages. Use whenever the user says "commit", "make a commit", "write commit message", or similar. |
Commit Skill
Detection
which jj 2>/dev/null && jj root 2>/dev/null && echo "jj" || (git rev-parse --show-toplevel 2>/dev/null && echo "git")
Prefer jj if both work — it's the user's primary VCS.
jj
Check state
jj status
jj diff
jj diff <file>
Commit (set message on working copy)
jj describe -m "<type>(<scope>): <subject>"
With body:
jj describe -m "$(cat <<'EOF'
<type>(<scope>): <subject>
<body>
EOF
)"
Drop unrelated files before committing
jj restore --from @- <file1> <file2>
Git
git status
git diff HEAD
git add <file>
git commit -m "<type>(<scope>): <subject>"
git commit -m "$(cat <<'EOF'
<type>(<scope>): <subject>
<body>
EOF
)"
Conventional Commit Format
<type>(<scope>): <subject>
<body>
Types: feat fix refactor perf style test docs chore revert
Scope: module changed, 1-2 words
Subject: imperative, no period, ≤72 chars
Body (optional): what and why, not how (diff shows how)
Breaking: add ! after type — feat!(api): change pagination response
Writing the Message
- Read
jj diff / git diff — understand every change
- Identify primary intent — feat? fix? refactor?
- Pick type + scope from that
- Skim each hunk — if any doesn't serve the primary intent, flag it
- Write imperative subject — "add X", "remove Y", "fix Z in W"
- Body only when why isn't obvious — platform quirk, perf trade-off, migration step
Examples
✅ Right
| Change | Message |
|---|
| New API route | feat(flights): add GET /api/flights/:id |
| Modal bug | fix(responsive-modal): stop blurring select on mobile after scroll |
| Rename function | refactor(utils): rename fetchWrapper to useFetchWrapper |
| Bump dep | chore(deps): bump radix-ui/react-select to 2.2.6 |
| Remove dead code | chore(auth): remove legacy session shim |
| Perf | perf(table): memoize row renderer |
| Breaking change | refactor!(db): drop legacy fuel_storage table |
❌ Wrong
| Message | Why |
|---|
fix: fix bug | Zero info |
fixed the modal | Past tense, no scope |
fix(modal):fixed | Missing space after colon |
feat(auth): add login page with form validation, error handling, remember-me, password reset, OAuth buttons | Subject >72 chars |
fix(cache): change gcTime from 5min to 30min in queryClient config | Describes how (diff shows it), not why |
✨ feat(ui): add spinner | Emojis are noise in terminal |
fix #1234 | No description |
Bump lodash to 4.17.21 (#4567) | GitHub auto-suffix noise |
Rules
- One logical change per commit — drop unrelated files before committing
- Don't commit stray
pnpm-lock.yaml — restore them out unless the change intentionally modifies deps
- Don't use
git add . / jj restore blindly — check what's in working copy first
- Don't write subjects longer than 72 chars — body exists for details
- Don't omit scope —
fix: ... is ambiguous, fix(tooltip): ... is not
- Don't use
chore: wip — either write a meaningful subject or leave undescribed