Conventional commits
29 free, verified agents, skills & packs for Claude Code - install with 'npx vanara install <name>'. Apache-2.0. From the Vanara catalog (206 items).
npx -y skills add vanara-agents/skills --skill conventional-commitsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 22 days oldThe repository was created 22 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Write Conventional Commits — the type(scope)!: subject + body + footer spec — so history is readable and changelogs and SemVer bumps can be derived automatically. Use when committing, configuring commitlint, designing release tooling, or deciding feat vs fix vs breaking change.
SKILL.md
7.2 KB, as published. Nobody here has run it
Conventional Commits
A commit message is the only documentation guaranteed to travel with a change forever. Conventional
Commits turn that prose into a structured, machine-parseable record: a tool can read your history and
derive the next version number and a categorized changelog without a human touching either. This skill is
the deep reference for the spec, the trade-offs, and the failure modes. Heavy detail lives in
references/; copy-paste config in examples/; a runnable linter in scripts/.
Mental model
Every commit answers three questions, and the format maps one-to-one onto them:
| Question | Where it lives |
|---|---|
| What kind of change? | the type (feat, fix, …) |
| Where, narrowly? | the optional scope (feat(auth):) |
| Does it break callers? | the ! marker and/or BREAKING CHANGE: footer |
| Why, in prose? | the body |
| What does it reference/close? | the footer (Refs:, Closes:) |
The header is for machines and scanners; the body is for the next human. Get the header structurally correct and your release tooling does the rest for free.
The spec
<type>(<optional scope>)<optional !>: <subject>
<blank line>
<optional body — wrapped prose explaining the why, may span paragraphs>
<blank line>
<optional footer(s) — BREAKING CHANGE: …, Refs: #123, Closes: #456, Co-Authored-By: …>
Rules that the linter enforces (see scripts/lint-commit.mjs):
- Type is required, lowercase, from the allowed set below.
- Scope is optional, in parentheses, a lowercase noun for the affected area (
api,auth,deps). !before the colon flags a breaking change.- Subject follows
:(colon-space), is imperative mood, lowercase, no trailing period, and the whole header is ≤ 72 characters (50 is the ideal — it keepsgit log --onelineand GitHub from truncating).
The full grammar, footer tokens, and revert/merge conventions are in references/spec.md.
Allowed types
| Type | Use for | SemVer impact |
|---|---|---|
feat | a new user-facing feature | MINOR |
fix | a bug fix | PATCH |
docs | documentation only | none |
style | formatting, whitespace, no code change | none |
refactor | code change that neither fixes a bug nor adds a feature | none |
perf | a performance improvement | PATCH |
test | adding or correcting tests | none |
build | build system or dependencies | none |
ci | CI configuration and scripts | none |
chore | maintenance, no production code change | none |
revert | reverts a previous commit | varies |
Any commit with a ! or BREAKING CHANGE: footer is a MAJOR bump, regardless of type. Keep the set
small and team-agreed — inventing per-developer types defeats the automation. See
references/breaking-changes-semver.md for the precise type → version mapping.
Why bother (the automation payoff)
The structure is not bureaucracy — it unlocks tooling you'd otherwise hand-maintain:
- Automated versioning:
semantic-release/ Changesets read the commits since the last tag and pick MAJOR / MINOR / PATCH from the types. No more "what should this version be?" debates. - Generated changelogs: commits group by type into a categorized
CHANGELOG.mdwith links to PRs and issues, written from the footers. - Scannable history: filtering by type answers "what features shipped this quarter?" in one command:
git log --oneline --grep '^feat' v1.4.0..HEAD # every feature since the last release
git log --oneline --grep 'BREAKING CHANGE' # every breaking change, ever
- Reviewable diffs: one logical change per commit means reviewers and
git bisectoperate on coherent units instead of tangled mega-commits.
Scoping commits (one logical change)
A perfect message on a tangled commit is still a bad commit. Each commit should be one coherent change
that builds and passes tests on its own — don't mix a refactor with a feature, or a fix with a formatting
sweep. This makes git revert, git bisect, and cherry-picks surgical instead of all-or-nothing. The
discipline of staging hunks (git add -p) to separate concerns is covered in references/scoping-commits.md.
Common pitfalls and failure modes
- Past tense / capitalized subject (
Added login) — the convention is imperative, lowercase:add login. A useful test: the subject should complete the sentence "If applied, this commit will ___". - A scope that's really a type (
feat(fix):) — scope is a place (auth), not a kind of change. - Forgotten breaking-change marker — renaming a public field as a plain
refactor:ships a MAJOR break as a no-bump release and silently breaks downstream consumers. Always add!+ aBREAKING CHANGE:footer explaining the migration. - Junk-drawer
chore:— usingchorefor everything erases the signal. A dependency bump that fixes a CVE is afix; a new capability is afeat. - Header over 72 chars — it truncates in
git log --oneline, GitHub, and changelog output. Move detail into the body. - Mega-commits ("WIP", "fixes") — unparseable by tooling and impossible to revert cleanly.
- Enforcing only on the final squash — if you squash-merge, the PR title becomes the commit; lint that, not just local commits, or the rule has no teeth.
When NOT to use / trade-offs
- Solo throwaway prototypes — the changelog/versioning payoff is zero; the ceremony is pure overhead.
- Squash-merge-only teams — per-commit discipline matters less; instead enforce the convention on PR titles via a CI check and let local commits be messy.
- Non-software repos (docs sites, infra-as-data) — the type vocabulary often doesn't fit; a lighter convention may serve better.
- The cost: it adds friction and requires a
commitlintgate plus team buy-in to stay consistent. Half-adopted, it's worse than nothing because the automation can't trust the data. Adopt it fully (with thecommit-msghook inexamples/commitlint.config.js) or not at all.
Files in this package
references/spec.md— full grammar: header, body, footers, revert/merge, FAQreferences/breaking-changes-semver.md—!vsBREAKING CHANGE:and exact type → SemVer mappingreferences/scoping-commits.md— splitting work into atomic commits withgit add -pexamples/commit-examples.md— annotated good and bad messages across every typeexamples/commitlint.config.js— zero-config-friendly commitlint setup + huskycommit-msghookscripts/lint-commit.mjs— runnable Node linter for a commit header, with--selftest
Pairs with the ci-pipeline-design skill (gate commits in CI), the changelog-writing skill (turn the
history into release notes), and the code-reviewer agent. See the
Conventional Commits spec for the canonical wording.