commitlint
About
This skill validates commit messages against Conventional Commits format using existing commitlint configuration files. It helps developers set up, configure, and troubleshoot commitlint rules, including integration with CI/CD pipelines and pre-commit hooks. It can also extract rules to generate LLM prompts for proper commit message creation.
Quick Install
Claude Code
Recommended/plugin add https://github.com/majiayu000/claude-skill-registrygit clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/commitlintCopy and paste this command in Claude Code to install this skill
Documentation
Commitlint
Validate commit messages against Conventional Commits format using commitlint configuration and rules.
When to Use This Skill
Use this skill when:
- Setting up commitlint for a repository
- Configuring commitlint rules and shareable configurations
- Integrating commitlint with pre-commit hooks or CI/CD pipelines
- Extracting rules from commitlint config to generate LLM prompts for commit message generation
- Validating commit messages programmatically
- Troubleshooting commitlint configuration or validation errors
- Understanding commitlint rule syntax and severity levels
- Detecting commitlint configuration files in a repository
Core Capabilities
Configuration Detection
Commitlint uses cosmiconfig to find configuration files in this priority order:
Dedicated config files:
.commitlintrc
.commitlintrc.json
.commitlintrc.yaml
.commitlintrc.yml
.commitlintrc.js
.commitlintrc.cjs
.commitlintrc.mjs
.commitlintrc.ts
.commitlintrc.cts
commitlint.config.js
commitlint.config.cjs
commitlint.config.mjs
commitlint.config.ts
commitlint.config.cts
Package files:
package.jsonwithcommitlintfieldpackage.yaml(PNPM) withcommitlintfield
Configuration Formats
JavaScript ES Modules (Recommended):
// commitlint.config.js or commitlint.config.mjs
export default {
extends: ['@commitlint/config-conventional'],
};
TypeScript:
// commitlint.config.ts
import type { UserConfig } from '@commitlint/types';
import { RuleConfigSeverity } from '@commitlint/types';
const config: UserConfig = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [RuleConfigSeverity.Error, 'always', ['feat', 'fix', 'docs']],
},
};
export default config;
JSON:
{
"extends": ["@commitlint/config-conventional"]
}
YAML:
extends:
- "@commitlint/config-conventional"
Rule Configuration
Rules are configured as arrays: [level, applicability, value]
Severity Levels:
| Level | Meaning | TypeScript Enum |
|---|---|---|
| 0 | Disabled | RuleConfigSeverity.Disabled |
| 1 | Warning | RuleConfigSeverity.Warning |
| 2 | Error | RuleConfigSeverity.Error |
Applicability:
'always'- Rule must match'never'- Rule must not match
Example rules:
rules: {
// Error if type is not in enum
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']],
// Error if type is empty
'type-empty': [2, 'never'],
// Error if subject is empty
'subject-empty': [2, 'never'],
// Error if header exceeds 100 chars
'header-max-length': [2, 'always', 100],
// Error if subject ends with period
'subject-full-stop': [2, 'never', '.'],
// Warning if body doesn't have leading blank line
'body-leading-blank': [1, 'always'],
}
Common Configurations
@commitlint/config-conventional
The most widely used shareable configuration. Default error-level rules:
| Rule | Configuration | Pass Example | Fail Example |
|---|---|---|---|
type-enum | ['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'] | fix: message | foo: message |
type-case | 'lowerCase' | fix: message | FIX: message |
type-empty | never | fix: message | : message |
subject-case | never + ['sentence-case', 'start-case', 'pascal-case', 'upper-case'] | fix: some message | fix: Some Message |
subject-empty | never | fix: message | fix: |
subject-full-stop | never, '.' | fix: message | fix: message. |
header-max-length | 100 | Short header | Header > 100 chars |
body-leading-blank | always (warning) | Blank line before body | No blank line |
body-max-line-length | 100 | Lines <= 100 chars | Line > 100 chars |
footer-leading-blank | always (warning) | Blank line before footer | No blank line |
footer-max-line-length | 100 | Lines <= 100 chars | Line > 100 chars |
Complete Configuration Schema
// commitlint.config.js
export default {
// Extend shareable configs (resolved via node resolution)
extends: ['@commitlint/config-conventional'],
// Parser preset for parsing commit messages
parserPreset: 'conventional-changelog-atom',
// Output formatter
formatter: '@commitlint/format',
// Custom rules (override inherited rules)
rules: {
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']],
},
// Functions that return true to ignore specific commits
// Merged with default ignores (merge commits, reverts, semver tags)
ignores: [(commit) => commit.includes('WIP')],
// Whether to use default ignore patterns
// Default patterns: 'Merge pull request', 'Revert X', 'v1.2.3', etc.
defaultIgnores: true,
// Custom help URL shown on failure
helpUrl: 'https://example.com/commit-guidelines',
// Prompt configuration (for @commitlint/cz-commitlint)
prompt: {
messages: {},
questions: {
type: {
description: 'Select the type of change:',
},
},
},
};
CLI Usage
Installation
# npm
npm install -D @commitlint/cli @commitlint/config-conventional
# yarn
yarn add -D @commitlint/cli @commitlint/config-conventional
# pnpm
pnpm add -D @commitlint/cli @commitlint/config-conventional
Common Commands
# Lint the last commit
npx commitlint --last
# Lint a range of commits
npx commitlint --from HEAD~5
# Lint from a specific commit
npx commitlint --from abc1234
# Lint message from stdin
echo "feat: add feature" | npx commitlint
# Lint message from file
npx commitlint < .git/COMMIT_EDITMSG
# Lint with edit flag (reads .git/COMMIT_EDITMSG)
npx commitlint --edit
# Lint with custom config path
npx commitlint --config ./custom-commitlint.config.js
# Print resolved config
npx commitlint --print-config
# Strict mode (warnings become exit code 2)
npx commitlint --last --strict
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success (no errors) |
| 1 | Lint errors found |
| 2 | Warnings found (strict mode only) |
| 3 | Errors found (strict mode) |
| 9 | Config file missing (with -g flag) |
Rule Reference
Type Rules
| Rule | Condition | Default Applicability |
|---|---|---|
type-enum | type is found in value | always |
type-case | type is in case value | always, 'lower-case' |
type-empty | type is empty | never |
type-max-length | type has value or less characters | always, Infinity |
type-min-length | type has value or more characters | always, 0 |
Subject Rules
| Rule | Condition | Default Applicability |
|---|---|---|
subject-case | subject is in case value | always |
subject-empty | subject is empty | never |
subject-full-stop | subject ends with value | never, '.' |
subject-max-length | subject has value or less characters | always, Infinity |
subject-min-length | subject has value or more characters | always, 0 |
subject-exclamation-mark | subject has exclamation before : | never |
Scope Rules
| Rule | Condition | Default Applicability |
|---|---|---|
scope-enum | scope is found in value | always, [] |
scope-case | scope is in case value | always, 'lower-case' |
scope-empty | scope is empty | never |
scope-max-length | scope has value or less characters | always, Infinity |
scope-min-length | scope has value or more characters | always, 0 |
Header Rules
| Rule | Condition | Default Applicability |
|---|---|---|
header-case | header is in case value | always, 'lower-case' |
header-full-stop | header ends with value | never, '.' |
header-max-length | header has value or less characters | always, 72 |
header-min-length | header has value or more characters | always, 0 |
header-trim | header has no leading/trailing whitespace | always |
Body Rules
| Rule | Condition | Default Applicability |
|---|---|---|
body-leading-blank | body begins with blank line | always |
body-empty | body is empty | never |
body-max-length | body has value or less characters | always, Infinity |
body-max-line-length | body lines have value or less characters (URLs excluded) | always, Infinity |
body-min-length | body has value or more characters | always, 0 |
body-case | body is in case value | always, 'lower-case' |
body-full-stop | body ends with value | never, '.' |
Footer Rules
| Rule | Condition | Default Applicability |
|---|---|---|
footer-leading-blank | footer begins with blank line | always |
footer-empty | footer is empty | never |
footer-max-length | footer has value or less characters | always, Infinity |
footer-max-line-length | footer lines have value or less characters | always, Infinity |
footer-min-length | footer has value or more characters | always, 0 |
Case Values
For rules that check case (*-case):
[
'lower-case', // lowercase
'upper-case', // UPPERCASE
'camel-case', // camelCase
'kebab-case', // kebab-case
'pascal-case', // PascalCase
'sentence-case', // Sentence case
'snake-case', // snake_case
'start-case', // Start Case
]
Programmatic Usage
Load Configuration
import load from '@commitlint/load';
async function getCommitlintConfig() {
const config = await load();
console.log(config.rules);
return config;
}
Validate Message
import load from '@commitlint/load';
import lint from '@commitlint/lint';
async function validateMessage(message) {
const config = await load();
const result = await lint(message, config.rules);
return {
valid: result.valid,
errors: result.errors,
warnings: result.warnings,
};
}
LLM Integration Patterns
Extract Rules for Prompt Generation
Generate LLM-friendly constraints from commitlint config:
def extract_rules_for_prompt(config: dict) -> str:
"""Extract commitlint rules into LLM-friendly format."""
rules = config.get('rules', {})
prompt_parts = []
# Extract type-enum if present
if 'type-enum' in rules:
level, applicability, types = rules['type-enum']
if level > 0 and applicability == 'always':
prompt_parts.append(f"Allowed commit types: {', '.join(types)}")
# Extract scope-enum if present
if 'scope-enum' in rules:
level, applicability, scopes = rules['scope-enum']
if level > 0 and applicability == 'always' and scopes:
prompt_parts.append(f"Allowed scopes: {', '.join(scopes)}")
# Extract header-max-length
if 'header-max-length' in rules:
level, applicability, length = rules['header-max-length']
if level > 0:
prompt_parts.append(f"Header must be {length} characters or less")
# Extract subject-case
if 'subject-case' in rules:
level, applicability, cases = rules['subject-case']
if level > 0 and applicability == 'never':
prompt_parts.append(f"Subject must NOT use: {', '.join(cases)}")
return '\n'.join(prompt_parts)
Validation Loop
import subprocess
async def validate_with_commitlint(message: str, cwd: Path | None = None) -> tuple[bool, list[str]]:
"""
Validate commit message with commitlint.
Args:
message: The commit message to validate
cwd: Working directory (defaults to current directory)
Returns:
Tuple of (is_valid, error_messages)
"""
result = subprocess.run(
['npx', 'commitlint'],
input=message,
capture_output=True,
text=True,
cwd=cwd,
)
if result.returncode == 0:
return True, []
# Parse errors from stderr
errors = [line.strip() for line in result.stderr.split('\n') if line.strip()]
return False, errors
Validation loop pattern:
- LLM generates commit message based on diff and rules
- Run commitlint on generated message
- If validation fails, feed errors back to LLM with context
- Retry (max 3 times by default)
- Return final message (valid or best effort after retries)
Common Issues
Node v24 ESM issues:
Use .mjs extension for ES modules config, or add "type": "module" to package.json
Missing extends:
Config without extends or rules fails with "Please add rules" error. Include at least one:
export default {
extends: ['@commitlint/config-conventional'],
};
Empty config error:
Config file must have at least extends or rules defined.
Scope enum empty array:
scope-enum with [] passes all scopes. Use specific array to restrict:
rules: {
'scope-enum': [2, 'always', ['api', 'ui', 'docs']],
}
Subject case trap:
@commitlint/config-conventional uses never with specific cases, meaning those cases are forbidden (not required):
// This forbids sentence-case, start-case, pascal-case, upper-case
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']]
Pre-commit Integration
For pre-commit hook integration with commitlint, activate the pre-commit skill:
Skill(command: "pre-commit")
Conventional Commits Reference
For Conventional Commits format specification and examples, activate the conventional-commits skill:
Skill(command: "conventional-commits")
References
Official Documentation
- Commitlint Official Site (accessed 2025-01-15)
- Configuration Reference (accessed 2025-01-15)
- Rules Reference (accessed 2025-01-15)
- CLI Reference (accessed 2025-01-15)
- Getting Started Guide (accessed 2025-01-15)
- GitHub Repository (accessed 2025-01-15)
Related Specifications
- Conventional Commits - Commit message format specification
- Cosmiconfig - Configuration file discovery mechanism
Source Attribution
This skill was created from reference documentation at the commit-polish repository (2025-12-01)
GitHub Repository
Related Skills
sglang
MetaSGLang is a high-performance LLM serving framework that specializes in fast, structured generation for JSON, regex, and agentic workflows using its RadixAttention prefix caching. It delivers significantly faster inference, especially for tasks with repeated prefixes, making it ideal for complex, structured outputs and multi-turn conversations. Choose SGLang over alternatives like vLLM when you need constrained decoding or are building applications with extensive prefix sharing.
evaluating-llms-harness
TestingThis Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
llamaguard
OtherLlamaGuard is Meta's 7-8B parameter model for moderating LLM inputs and outputs across six safety categories like violence and hate speech. It offers 94-95% accuracy and can be deployed using vLLM, Hugging Face, or Amazon SageMaker. Use this skill to easily integrate content filtering and safety guardrails into your AI applications.
