Agent skill

commitlint

When setting up commit message validation for a project. When project has commitlint.config.js or .commitlintrc files. When configuring CI/CD to enforce commit format. When extracting commit rules for LLM prompt generation. When debugging commit message rejection errors.

Stars 33
Forks 4

Install this agent skill to your Project

npx add-skill https://github.com/Jamie-BitFlight/claude_skills/tree/main/plugins/commitlint/skills/commitlint

SKILL.md

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:

text
.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.json with commitlint field
  • package.yaml (PNPM) with commitlint field

Configuration Formats

JavaScript ES Modules (Recommended):

javascript
// commitlint.config.js or commitlint.config.mjs
export default {
  extends: ['@commitlint/config-conventional'],
};

TypeScript:

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:

json
{
  "extends": ["@commitlint/config-conventional"]
}

YAML:

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:

javascript
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

javascript
// 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

bash
# 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

bash
# 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):

javascript
[
  '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

javascript
import load from '@commitlint/load';

async function getCommitlintConfig() {
  const config = await load();
  console.log(config.rules);
  return config;
}

Validate Message

javascript
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:

python
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

python
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:

  1. LLM generates commit message based on diff and rules
  2. Run commitlint on generated message
  3. If validation fails, feed errors back to LLM with context
  4. Retry (max 3 times by default)
  5. 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:

javascript
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:

javascript
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):

javascript
// 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:

text
Skill(skill: "python3-development:pre-commit")

Conventional Commits Reference

For Conventional Commits format specification and examples, activate the conventional-commits skill:

text
Skill(skill: "conventional-commits:conventional-commits")

References

Official Documentation

Related Specifications

Source Attribution

This skill was created from reference documentation at the commit-polish repository (2025-12-01)

Expand your agent's capabilities with these related and highly-rated skills.

Jamie-BitFlight/claude_skills

ccc

This skill should be used when code search is needed (whether explicitly requested or as part of completing a task), when indexing the codebase after changes, or when the user asks about ccc, cocoindex-code, or the codebase index. Trigger phrases include 'search the codebase', 'find code related to', 'update the index', 'ccc', 'cocoindex-code'.

33 4
Explore
Jamie-BitFlight/claude_skills

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.

33 4
Explore
Jamie-BitFlight/claude_skills

delegate

Quick delegation template for sub-agent prompts. Use when assigning work to a sub-agent, before invoking the Agent tool, or when preparing prompts for specialized agents. Provides the WHERE-WHAT-WHY framework. For comprehensive delegation guidance, activate the agent-orchestration how-to-delegate skill.

33 4
Explore
Jamie-BitFlight/claude_skills

swarm-spawning

Spawn agents and teammates in Claude Code swarms. Use when choosing between subagents vs teammates, selecting agent types (Explore, Plan, general-purpose, plugin agents), configuring spawn backends (in-process, tmux, iterm2), or setting environment variables for spawned agents.

33 4
Explore
Jamie-BitFlight/claude_skills

knowledge-explorer

Manage the research/ knowledge base (KB) of tool and library research entries. Use when browsing KB topics, adding new research entries, updating existing entries with dated revisions, fetching GitHub repo metadata into a draft KB entry, or migrating old-format entries to skill-spec frontmatter. Triggers on tasks like "what do we have on X", "add this to the KB", "update the KB entry for Y", "fetch github info for owner/repo", or "migrate old entries".

33 4
Explore
Jamie-BitFlight/claude_skills

design-anti-patterns

Enforce anti-AI UI design rules based on the Uncodixfy methodology. Use when generating HTML, CSS, React, Vue, Svelte, or any frontend UI code. Prevents "Codex UI" — the generic AI aesthetic of soft gradients, floating panels, oversized rounded corners, glassmorphism, hero sections in dashboards, and decorative copy. Applies constraints from Linear/Raycast/Stripe/GitHub design philosophy: functional, honest, human-designed interfaces. Triggers on: UI generation, dashboard building, frontend component creation, CSS styling, landing page design, or any task producing visual interface code.

33 4
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results