Skip to content
Back to skills

Conventional Commits

ASecurity

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.

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
ai-agentsrustgobashnodecode-reviewgitapiperformancedocumentation

Works with

  • api

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned September 6, 2026

npx -y skills add vanara-agents/skills --skill conventional-commits --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Conventional Commits?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Conventional Commits
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vanara-agents-conventional-commits/badge)](https://www.skillsdirectory.com/skills/vanara-agents-conventional-commits)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: conventional-commits
description: 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.
type: skill
version: 2.0.0
updated: 2026-06-29
---
# 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`):

1. **Type** is required, lowercase, from the allowed set below.
2. **Scope** is optional, in parentheses, a lowercase noun for the affected area (`api`, `auth`, `deps`).
3. **`!`** before the colon flags a breaking change.
4. **Subject** follows `: ` (colon-space), is imperative mood, lowercase, no trailing period, and the
   whole header is **≤ 72 characters** (50 is the ideal — it keeps `git log --oneline` and 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.md` with links to PRs and
  issues, written from the footers.
- **Scannable history:** filtering by type answers "what features shipped this quarter?" in one command:

```bash
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 bisect` operate 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 `!` + a `BREAKING
  CHANGE:` footer explaining the migration.
- **Junk-drawer `chore:`** — using `chore` for everything erases the signal. A dependency bump that fixes
  a CVE is a `fix`; a new capability is a `feat`.
- **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 `commitlint` gate 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
  the `commit-msg` hook in `examples/commitlint.config.js`) or not at all.

## Files in this package

- `references/spec.md` — full grammar: header, body, footers, revert/merge, FAQ
- `references/breaking-changes-semver.md` — `!` vs `BREAKING CHANGE:` and exact type → SemVer mapping
- `references/scoping-commits.md` — splitting work into atomic commits with `git add -p`
- `examples/commit-examples.md` — annotated good and bad messages across every type
- `examples/commitlint.config.js` — zero-config-friendly commitlint setup + husky `commit-msg` hook
- `scripts/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](https://www.conventionalcommits.org/) for the canonical wording.

Files in this skill

  • SKILL.md7.2 KB
  • examples/commit-examples.md1.8 KB
  • examples/commitlint.config.js1.4 KB
  • references/breaking-changes-semver.md2.1 KB
  • references/scoping-commits.md1.9 KB
  • references/spec.md2.6 KB
  • scripts/lint-commit.mjs3.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…