Script to validate a commit message follows the conventional changelog standard
npx @tessl/cli install tessl/npm-validate-commit-msg@2.14.0validate-commit-msg is a Node.js tool that validates Git commit messages against the conventional changelog standard. It enforces commit message format requirements and can be integrated into Git hooks to automatically validate commits during development workflow.
npm install --save-dev validate-commit-msg (typically installed as dev dependency for git hooks)const validateMessage = require('validate-commit-msg');For accessing configuration utilities:
const { getConfig, getRcConfig, getPackageConfig, getConfigObject } = require('validate-commit-msg/lib/config');
const getGitFolder = require('validate-commit-msg/lib/getGitFolder');const validateMessage = require('validate-commit-msg');
// Validate a commit message programmatically
const isValid = validateMessage('feat(auth): add user login functionality');
console.log(isValid); // true
// Invalid commit message
const isInvalid = validateMessage('bad commit message');
console.log(isInvalid); // false
// Validate with auto-fix (requires source file path)
const result = validateMessage('FEAT: uppercase type', '.git/COMMIT_EDITMSG');
// Auto-fixes the type to lowercase if autoFix is enabled in configThe package provides a command-line tool for Git hooks:
# Install as git hook (using husky)
npm install --save-dev husky validate-commit-msg
# Add to package.json scripts
{
"scripts": {
"commitmsg": "validate-commit-msg"
}
}
# Direct CLI usage
validate-commit-msg "feat(scope): commit message"
validate-commit-msg # reads from COMMIT_EDITMSG file
validate-commit-msg GITGUI_EDITMSG # reads from specified git fileConfiguration can be provided through .vcmrc file (JSON format) or package.json:
{
"config": {
"validate-commit-msg": {
"types": ["feat", "fix", "docs", "style", "refactor", "test", "chore"],
"scope": {
"required": false,
"allowed": ["*"],
"validate": false,
"multiple": false
},
"warnOnFail": false,
"maxSubjectLength": 100,
"subjectPattern": ".+",
"subjectPatternErrorMsg": "subject does not match subject pattern!",
"helpMessage": "",
"autoFix": false
}
}
}Validates commit messages against conventional changelog format.
/**
* Validates a commit message against conventional changelog format
* @param {string} raw - Raw commit message text to validate
* @param {string} [sourceFile] - Optional path to commit message file for auto-fixing
* @returns {boolean} true if message is valid, false otherwise
*/
function validateMessage(raw, sourceFile);Validation Rules:
<type>(<scope>): <subject> or <type>: <subject>Special Cases:
Merge ...) are automatically validAccess and manage validation configuration. The configuration system supports two sources: .vcmrc files (JSON format) and package.json under the config.validate-commit-msg key. Configuration from .vcmrc takes precedence over package.json.
/**
* Get merged configuration from .vcmrc and package.json
* @returns {object} Configuration object with validation settings
*/
function getConfig();
/**
* Get configuration from .vcmrc file
* @returns {object|null} Configuration from .vcmrc or null if not found
*/
function getRcConfig();
/**
* Get configuration from package.json
* @returns {object|null} Configuration from package.json config.validate-commit-msg or null if not found
*/
function getPackageConfig();
/**
* Get configuration from specified file
* @param {string} filename - Configuration file name to read (e.g., '.vcmrc', 'package.json')
* @returns {object|null} Parsed configuration object or null if not found
*/
function getConfigObject(filename);Utilities for Git repository integration.
/**
* Locate .git folder in current directory tree
* @returns {string} Path to .git folder
* @throws {Error} If .git folder cannot be found
*/
function getGitFolder();Access the currently loaded configuration object from the main validation module.
const { config } = require('validate-commit-msg/lib/validateMessage');
/**
* Current configuration object used by the validator
* Contains merged settings from .vcmrc and package.json
* @type {object}
*/
const config;/**
* Configuration object structure for validate-commit-msg
*/
interface ValidateCommitMsgConfig {
/**
* Allowed commit types. Can be:
* - Array of strings: ["feat", "fix", "docs"]
* - "*" for any type
* - Module name: "conventional-commit-types" (default)
*/
types?: string[] | "*" | string;
/** Scope validation configuration */
scope?: {
/** Whether scope is required for all commits */
required?: boolean;
/** Array of allowed scopes or "*" for any scope */
allowed?: string[] | "*";
/** Whether to validate scope names against allowed list */
validate?: boolean;
/** Whether multiple scopes are allowed (comma-separated) */
multiple?: boolean;
};
/** If true, validation errors are warnings instead of failures */
warnOnFail?: boolean;
/** Maximum allowed subject length (default: 100) */
maxSubjectLength?: number;
/** Regular expression pattern for subject validation (default: ".+") */
subjectPattern?: string;
/** Error message when subject doesn't match pattern */
subjectPatternErrorMsg?: string;
/** Custom help message shown on validation failure */
helpMessage?: string;
/** Enable automatic fixing of common formatting issues (requires sourceFile parameter) */
autoFix?: boolean;
}The validator provides detailed error messages for validation failures:
When warnOnFail is enabled, validation errors are logged as warnings but don't cause the commit to fail.
const validateMessage = require('validate-commit-msg');
// Valid messages
console.log(validateMessage('feat: add new feature')); // true
console.log(validateMessage('fix(auth): resolve login issue')); // true
console.log(validateMessage('docs: update README')); // true
// Invalid messages
console.log(validateMessage('bad message')); // false
console.log(validateMessage('FEAT: uppercase type')); // false (unless autoFix enabled)
// Auto-merge commits are always valid
console.log(validateMessage('Merge branch "feature" into main')); // true
// WIP and semver commits are ignored
console.log(validateMessage('WIP: work in progress')); // true
console.log(validateMessage('v1.2.3')); // trueconst { getConfig, getRcConfig, getPackageConfig, getConfigObject } = require('validate-commit-msg/lib/config');
// Get current merged configuration
const config = getConfig();
console.log('Max subject length:', config.maxSubjectLength);
console.log('Allowed types:', config.types);
// Check specific config sources
const rcConfig = getRcConfig(); // From .vcmrc
const pkgConfig = getPackageConfig(); // From package.json
// Read any config file
const customConfig = getConfigObject('my-config.json');// In a git hook script
const validateMessage = require('validate-commit-msg');
const getGitFolder = require('validate-commit-msg/lib/getGitFolder');
const fs = require('fs');
const path = require('path');
try {
const gitDir = getGitFolder();
const commitMsgPath = path.join(gitDir, 'COMMIT_EDITMSG');
const commitMsg = fs.readFileSync(commitMsgPath, 'utf8');
// Validate with auto-fix capability
if (!validateMessage(commitMsg, commitMsgPath)) {
console.error('Invalid commit message format');
process.exit(1);
}
} catch (error) {
console.error('Error reading commit message:', error.message);
process.exit(1);
}// .vcmrc configuration file
{
"types": ["feat", "fix", "docs", "style", "refactor", "test", "chore"],
"scope": {
"required": true,
"allowed": ["auth", "api", "ui", "core"],
"validate": true,
"multiple": false
},
"warnOnFail": false,
"maxSubjectLength": 72,
"subjectPattern": "^[a-z].*[^.]$",
"subjectPatternErrorMsg": "Subject must start with lowercase and not end with period",
"helpMessage": "Please follow the conventional commit format: <type>(<scope>): <subject>",
"autoFix": true
}