When writing a git commit message. When task completes and changes need committing. When project uses semantic-release, commitizen, git-cliff. When choosing between feat/fix/chore/docs types. When indicating breaking changes. When generating changelogs from commit history.
Install with Tessl CLI
npx tessl i github:Jamie-BitFlight/claude_skills --skill conventional-commits72
Does it follow best practices?
If you maintain this skill, you can automatically optimize it using the tessl CLI to improve its score:
npx tessl skill review --optimize ./path/to/skillValidation for skill structure
Compose commit messages following the Conventional Commits v1.0.0 specification for structured commit history, automated changelog generation, and semantic versioning.
Use this skill when:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]| Component | Required | Description | Example |
|---|---|---|---|
| type | Yes | Commit category | feat, fix, docs |
| scope | No | Codebase section affected | (auth), (parser) |
| description | Yes | Short summary of changes | add user authentication |
| body | No | Detailed explanation | Multiple paragraphs with context |
| footer | No | Breaking changes, issue refs | BREAKING CHANGE:, Refs: #123 |
These types are mandated by the Conventional Commits specification and directly affect semantic versioning:
flowchart LR
Fix[fix: Bug fix<br/>for users] --> PatchVer[PATCH<br/>0.0.X]
Feat[feat: New feature<br/>for users] --> MinorVer[MINOR<br/>0.X.0]
Breaking[Any type with<br/>BREAKING CHANGE or !] --> MajorVer[MAJOR<br/>X.0.0]
style PatchVer fill:#e1f5ff
style MinorVer fill:#fff4e1
style MajorVer fill:#ffe1e1| Type | Description | SemVer | Example |
|---|---|---|---|
feat | New feature for users | MINOR (0.X.0) | feat: add user authentication |
fix | Bug fix for users | PATCH (0.0.X) | fix: prevent crash on empty input |
These types come from @commitlint/config-conventional based on Angular commit guidelines. They have no implicit SemVer effect unless they include BREAKING CHANGE.
| Type | Description | Example |
|---|---|---|
build | Build system or external dependency changes | build: update webpack to v5 |
ci | CI configuration changes | ci: add Node 18 to test matrix |
docs | Documentation only changes | docs: update API reference |
perf | Performance improvement | perf: reduce bundle size by 20% |
refactor | Code change with no bug fix or feature | refactor: extract validation logic |
style | Code style changes (whitespace, formatting) | style: fix indentation |
test | Adding or correcting tests | test: add unit tests for parser |
| Type | Description | Example |
|---|---|---|
chore | Changes not modifying src or test files | chore: update .gitignore |
revert | Reverts a previous commit | revert: feat: add user auth |
Note: Teams can define custom types beyond feat and fix, but Angular convention types are widely supported by tooling.
The following rules constitute the official Conventional Commits 1.0.0 specification per RFC 2119.
Commits MUST be prefixed with a type, consisting of a noun (feat, fix, etc.), followed by OPTIONAL scope, OPTIONAL !, and REQUIRED terminal colon and space.
Type feat MUST be used when a commit adds a new feature.
Type fix MUST be used when a commit represents a bug fix.
A scope MAY be provided after a type. A scope MUST consist of a noun describing a codebase section surrounded by parenthesis, e.g., fix(parser):
A description MUST immediately follow the colon and space after the type/scope prefix. The description is a short summary of code changes, e.g., fix: array parsing issue when multiple spaces were contained in string
A longer commit body MAY be provided after the short description, providing additional contextual information. The body MUST begin one blank line after the description.
A commit body is free-form and MAY consist of any number of newline separated paragraphs.
One or more footers MAY be provided one blank line after the body. Each footer MUST consist of a word token, followed by either a :<space> or <space># separator, followed by a string value (inspired by git trailer convention).
A footer's token MUST use - in place of whitespace characters, e.g., Acked-by (this helps differentiate footer section from multi-paragraph body). Exception: BREAKING CHANGE MAY also be used as a token.
A footer's value MAY contain spaces and newlines. Parsing MUST terminate when the next valid footer token/separator pair is observed.
Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the footer.
If included as a footer, a breaking change MUST consist of uppercase text BREAKING CHANGE, followed by colon, space, and description, e.g., BREAKING CHANGE: environment variables now take precedence over config files
If included in the type/scope prefix, breaking changes MUST be indicated by ! immediately before :. If ! is used, BREAKING CHANGE: MAY be omitted from footer, and commit description SHALL be used to describe the breaking change.
Types other than feat and fix MAY be used in commit messages, e.g., docs: update ref docs
The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, except BREAKING CHANGE which MUST be uppercase.
BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE when used as a token in a footer.
Based on Angular commit message guidelines:
feat: add validation for email input
fix: handle null pointer in user service
docs: update installation instructions
refactor: simplify authentication flowfeat: Added validation for email input # Past tense
fix: Handles null pointer in user service # Third person
docs: Update installation instructions. # Period at end, capitalized
FEAT: add validation # Uppercase type (inconsistent)Three equivalent approaches:
Footer notation:
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config filesType suffix with !:
feat!: remove support for Node 6Type+scope suffix with !:
feat(api)!: send an email to the customer when a product is shippedBREAKING CHANGE MUST be uppercaseBREAKING-CHANGE is synonymous when used as footer tokenflowchart TD
Start([Analyze Commits]) --> CheckBreaking{Any commit has<br/>BREAKING CHANGE<br/>or !?}
CheckBreaking -->|Yes| Major[MAJOR bump<br/>X.0.0]
CheckBreaking -->|No| CheckFeat{Any commit<br/>is feat?}
CheckFeat -->|Yes| Minor[MINOR bump<br/>0.X.0]
CheckFeat -->|No| CheckFix{Any commit<br/>is fix?}
CheckFix -->|Yes| Patch[PATCH bump<br/>0.0.X]
CheckFix -->|No| NoChange[No version change]
Major --> End([Release])
Minor --> End
Patch --> End
NoChange --> End| Commit Type | Version Bump |
|---|---|
fix | PATCH (0.0.X) |
feat | MINOR (0.X.0) |
BREAKING CHANGE or ! | MAJOR (X.0.0) |
Reason: Enables automated semantic versioning based on commit history.
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:\s.+$import re
CONVENTIONAL_COMMIT_PATTERN = re.compile(
r'^(?P<type>feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)'
r'(?:\((?P<scope>[^)]+)\))?'
r'(?P<breaking>!)?'
r':\s'
r'(?P<description>.+)$'
)
def validate_header(header: str) -> bool:
"""Validate commit header follows Conventional Commits."""
return bool(CONVENTIONAL_COMMIT_PATTERN.match(header))
def parse_header(header: str) -> dict | None:
"""Parse commit header into components."""
match = CONVENTIONAL_COMMIT_PATTERN.match(header)
if not match:
return None
return {
'type': match.group('type'),
'scope': match.group('scope'),
'breaking': bool(match.group('breaking')),
'description': match.group('description'),
}feat: add user authenticationfix: prevent crash on empty inputdocs: correct spelling of CHANGELOGfeat(lang): add Polish languagefeat(parser): add ability to parse arraysfix(auth): handle token expiration correctlyfeat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config filesfeat!: send an email to the customer when a product is shippedfeat(api)!: send an email to the customer when a product is shippedchore!: drop support for Node 6
BREAKING CHANGE: use JavaScript features not available in Node 6.fix: prevent racing of requests
Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.
Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
Reviewed-by: Z
Refs: #123revert: let us never again speak of the noodle incident
Refs: 676104e, a215868perf: reduce memory allocation in parser by 40%
Replace string concatenation with StringBuilder pattern.
Benchmark results show 40% reduction in heap allocations.
Refs: #456refactor: extract authentication logic into separate module
Move auth-related functions from utils.py to auth.py.
No functional changes.ci: add Node 18 to test matrixbuild: upgrade webpack from v4 to v5
- Update webpack.config.js for v5 compatibility
- Replace deprecated plugins
- Update all loader dependencies
Refs: #789test: add unit tests for user validation
Cover edge cases for email validation and password strength.style: format code according to prettier configchore: update .gitignore to exclude IDE filesValidate commits with commitlint using Angular configuration:
# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Create configuration
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# Test commit message
echo 'feat(api): add new endpoint' | npx commitlintFor comprehensive commitlint configuration guidance, activate the commitlint skill:
Skill(command: "commitlint:commitlint")Enforce commit message format with pre-commit hooks. For complete pre-commit setup guidance, activate the pre-commit skill:
Skill(command: "python3-development:pre-commit")Generate changelogs from Conventional Commits using semantic-release:
// release.config.js
module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
],
};Or using git-cliff:
# cliff.toml
[git]
conventional_commits = trueFrom the official specification:
Yes. Types beyond feat and fix are not mandated by the specification but have no implicit SemVer effect unless they include BREAKING CHANGE. Teams commonly add types like wip, deps, security.
Implementation-defined. Most tools normalize to lowercase. Exception: BREAKING CHANGE MUST be uppercase. Best practice: be consistent within your project.
Merge commits are typically ignored by changelog generators. They do not need to follow the format.
Before merging/releasing: Use git rebase -i to edit commit history After release: Depends on tools and processes Worst case: Non-conforming commit is missed by tools based on the specification
No. With squash-based workflows, lead maintainers can clean up commit messages when merging. Many teams configure git systems to automatically squash commits from pull requests and present a form for entering proper commit messages.
Use the revert type with a footer referencing reverted commit SHAs:
revert: let us never again speak of the noodle incident
Refs: 676104e, a215868Commit message validation and enforcement:
commitlint - Configure and use commitlint for commit message validation. Activate: Skill(command: "commitlint:commitlint")pre-commit - Set up pre-commit hooks for automated validation. Activate: Skill(command: "python3-development:pre-commit")Git workflow tools:
commit-staged - Generate conventional commit messages from diffs. Activate: Skill(command: "commit-staged")8ea4dbe
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.