cz-git

Installation
SKILL.md

cz-git - Interactive Commitizen Adapter

Lightweight, highly customizable, and standard-compliant commitizen adapter for enforcing conventional commits.

Installation

npm install -D cz-git commitizen

Configuration

Method 1: package.json

{
  "scripts": {
    "commit": "cz"
  },
  "config": {
    "commitizen": {
      "path": "node_modules/cz-git"
    }
  }
}

Method 2: .czrc file

{
  "path": "node_modules/cz-git"
}

Basic Configuration

.cz-config.js

module.exports = {
  // Type options
  types: [
    { value: 'feat', name: 'feat:     ✨ A new feature' },
    { value: 'fix', name: 'fix:      🐛 A bug fix' },
    { value: 'docs', name: 'docs:     📝 Documentation only changes' },
    { value: 'style', name: 'style:    💄 Code style changes (formatting, etc)' },
    { value: 'refactor', name: 'refactor: ♻️  Code refactoring' },
    { value: 'perf', name: 'perf:     ⚡️ Performance improvements' },
    { value: 'test', name: 'test:     ✅ Adding or updating tests' },
    { value: 'build', name: 'build:    📦️ Build system or dependencies' },
    { value: 'ci', name: 'ci:       🎡 CI configuration changes' },
    { value: 'chore', name: 'chore:    🔧 Other changes (no src/test)' },
    { value: 'revert', name: 'revert:   ⏪️ Revert previous commit' }
  ],

  // Scopes
  scopes: [
    'core',
    'ui',
    'api',
    'auth',
    'database',
    'config',
    'deps'
  ],

  // Allow custom scopes
  allowCustomScopes: true,

  // Allow empty scopes
  allowEmptyScopes: false,

  // Skip questions
  skipQuestions: ['body', 'footer'],

  // Subject length
  subjectLimit: 100,

  // Breaking change prefix
  breakingChangePrefix: '🚨 BREAKING CHANGE:',

  // Footer prefix
  footerPrefix: 'ISSUES CLOSED:',

  // Use emojis
  useEmoji: true,

  // Empty commit message prefix
  emptyIssuePrefixAlias: 'skip-ci',

  // Custom scopes prompt
  scopeOverrides: {
    feat: ['ui', 'api', 'auth'],
    fix: ['ui', 'api', 'database']
  }
};

Advanced Configuration

With TypeScript

// .cz-config.ts
import { UserConfig } from 'cz-git';

const config: UserConfig = {
  alias: { fd: 'docs: fix typos' },
  
  messages: {
    type: 'Select the type of change:',
    scope: 'Select the scope (optional):',
    customScope: 'Enter custom scope:',
    subject: 'Write a SHORT description:',
    body: 'Provide a LONGER description (optional):',
    breaking: 'List BREAKING CHANGES (optional):',
    footerPrefixesSelect: 'Select issue prefix (optional):',
    customFooterPrefix: 'Enter custom issue prefix:',
    footer: 'List issues (optional):',
    confirmCommit: 'Confirm commit?'
  },

  types: [
    { value: 'feat', name: 'feat:     ✨ New feature', emoji: '✨' },
    { value: 'fix', name: 'fix:      🐛 Bug fix', emoji: '🐛' },
    { value: 'docs', name: 'docs:     📝 Documentation', emoji: '📝' },
    { value: 'style', name: 'style:    💄 Formatting', emoji: '💄' },
    { value: 'refactor', name: 'refactor: ♻️  Refactoring', emoji: '♻️' },
    { value: 'perf', name: 'perf:     ⚡️ Performance', emoji: '⚡️' },
    { value: 'test', name: 'test:     ✅ Testing', emoji: '✅' },
    { value: 'build', name: 'build:    📦️ Build', emoji: '📦️' },
    { value: 'ci', name: 'ci:       🎡 CI/CD', emoji: '🎡' },
    { value: 'chore', name: 'chore:    🔧 Chores', emoji: '🔧' }
  ],

  scopes: [
    { name: 'core', value: 'core' },
    { name: 'ui', value: 'ui' },
    { name: 'api', value: 'api' }
  ],

  enableMultipleScopes: true,
  scopeEnumSeparator: ',',
  
  allowCustomScopes: true,
  allowEmptyScopes: true,
  
  customScopesAlign: 'bottom',
  defaultScope: '',
  
  allowBreakingChanges: ['feat', 'fix'],
  breaklineNumber: 100,
  breaklineChar: '|',
  
  skipQuestions: [],
  
  issuePrefixes: [
    { value: 'closed', name: 'closed:   ISSUES CLOSED' },
    { value: 'link', name: 'link:     RELATED ISSUES' }
  ],
  
  customIssuePrefixAlign: 'top',
  emptyIssuePrefixAlias: 'skip',
  
  upperCaseSubject: false,
  markBreakingChangeMode: false,
  
  allowCustomIssuePrefix: true,
  allowEmptyIssuePrefix: true,
  
  confirmColorize: true,
  maxHeaderLength: Infinity,
  maxSubjectLength: Infinity,
  minSubjectLength: 0,
  
  scopeOverrides: undefined,
  defaultBody: '',
  defaultIssues: '',
  defaultSubject: ''
};

export default config;

Usage

Basic Commit

# Interactive commit
npm run commit
# or
npx cz

# Direct git commit (if configured globally)
git cz

Workflow Example

# 1. Stage changes
git add .

# 2. Interactive commit
npm run commit

# Select type: feat
# Enter scope: auth
# Enter subject: add OAuth2 authentication
# Confirm: yes

# Result: feat(auth): add OAuth2 authentication

Integration with Commitlint

commitlint.config.js

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat',
        'fix',
        'docs',
        'style',
        'refactor',
        'perf',
        'test',
        'build',
        'ci',
        'chore',
        'revert'
      ]
    ],
    'scope-enum': [
      2,
      'always',
      ['core', 'ui', 'api', 'auth', 'database', 'config']
    ],
    'subject-case': [2, 'never', ['upper-case']],
    'subject-empty': [2, 'never'],
    'subject-full-stop': [2, 'never', '.'],
    'type-empty': [2, 'never']
  }
};

Husky Integration

# Install husky
npm install -D husky

# Initialize husky
npx husky init

# Create commit-msg hook
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

# Create prepare-commit-msg hook for cz-git
echo "exec < /dev/tty && npx cz --hook || true" > .husky/prepare-commit-msg

Common Configurations

Monorepo Configuration

// .cz-config.js
const fs = require('fs');
const path = require('path');

// Auto-detect packages
const packages = fs
  .readdirSync(path.resolve(__dirname, 'packages'))
  .filter(f => fs.statSync(path.join('packages', f)).isDirectory());

module.exports = {
  scopes: [
    ...packages,
    'workspace',
    'deps',
    'release'
  ],
  scopeOverrides: {
    feat: packages,
    fix: packages
  }
};

Team-specific Configuration

module.exports = {
  types: [
    { value: 'feat', name: 'feat:     New feature for user' },
    { value: 'fix', name: 'fix:      Bug fix for user' },
    { value: 'docs', name: 'docs:     Documentation changes' },
    { value: 'refactor', name: 'refactor: Code refactoring' },
    { value: 'test', name: 'test:     Adding tests' },
    { value: 'chore', name: 'chore:    Maintenance tasks' }
  ],

  scopes: [
    'frontend',
    'backend',
    'mobile',
    'infra',
    'docs'
  ],

  messages: {
    type: '🎯 Select the type of change:',
    scope: '📦 Select affected component:',
    subject: '✍️  Write a SHORT description:\n',
    body: '📝 Provide detailed description (optional):\n',
    breaking: '🚨 List BREAKING CHANGES (optional):\n',
    footer: '🔗 Reference issues (e.g., "fixes #123"):\n',
    confirmCommit: '✅ Confirm commit?'
  },

  skipQuestions: ['body'],
  subjectLimit: 72,
  breaklineChar: '|',
  footerPrefix: 'Refs:'
};

Custom Prompts

Conditional Scopes

module.exports = {
  scopeOverrides: {
    feat: [
      { name: 'frontend', value: 'frontend' },
      { name: 'backend', value: 'backend' }
    ],
    fix: [
      { name: 'critical', value: 'critical' },
      { name: 'major', value: 'major' },
      { name: 'minor', value: 'minor' }
    ]
  }
};

Custom Validators

module.exports = {
  messages: {
    type: 'Select type:',
    subject: 'Short description:',
    customScope: 'Custom scope (must match /^[a-z]+$/):'
  },
  
  // Custom scope validation
  allowCustomScopes: true,
  customScopesAlign: 'bottom',
  
  // Subject validation
  subjectLimit: 50,
  upperCaseSubject: false
};

VS Code Integration

settings.json

{
  "git.enableCommitSigning": true,
  "git.inputValidationLength": 72,
  "conventionalCommits.autoCommit": false,
  "conventionalCommits.showEditor": true
}

tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Commit with cz-git",
      "type": "shell",
      "command": "npm run commit",
      "problemMatcher": [],
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

Best Practices

  1. Keep subjects concise - Under 50 characters
  2. Use imperative mood - "add" not "added"
  3. Reference issues - Link to issue tracker
  4. Consistent scopes - Define clear scope list
  5. Breaking changes - Always document
  6. Emojis optional - Use consistently if enabled
  7. Skip unnecessary questions - Configure skipQuestions
  8. Team alignment - Share configuration

Common Issues

cz-git not found

# Ensure cz-git is installed
npm install -D cz-git

# Verify package.json config
"config": {
  "commitizen": {
    "path": "node_modules/cz-git"
  }
}

Commitlint conflicts

# Ensure rules match cz-git config
# .cz-config.js types should match commitlint.config.js type-enum

Interactive mode not working

# Run with TTY
exec < /dev/tty && npx cz --hook

Resources

Weekly Installs
2
First Seen
Jan 26, 2026
Installed on
claude-code2
codex1
github-copilot1
gemini-cli1