Saltar al contenido principal

czg — Wizard interactivo de commits

🔄 Reemplazado por wietoo (2026-07). czg + commitlint ya no son el estándar Wiedii — el hook compartido lefthook/base.yaml de wiedii-configs usa el binario nativo wietoo para el asistente y la validación de commits, en todos los stacks (sin Node). Esta nota queda como referencia histórica de cómo funcionaba el flujo anterior; para el flujo vigente ver wietoo-cli.

⚠️ Verificar versiones antes de usar — las versiones de czg, cz-git, @commitlint/cli y @commitlint/config-conventional en esta nota pueden estar desactualizadas. Consultar bun info <paquete> version antes de instalar. Ver politicas-core.

Qué es

czg (cz-git) es un wizard de línea de comandos que guía al desarrollador a través de la creación de un mensaje de commit siguiendo el estándar Conventional Commits. En lugar de escribir el mensaje manualmente, el dev responde una serie de preguntas y czg construye el mensaje correctamente formateado.

En Wiedii, bun commit era el alias que invocaba czg — reemplazado por wietoo commit.

Por qué lo usábamos en Wiedii

  • Eliminaba el margen de error humano en el formato de commits — feat(auth): add OAuth2 login siempre quedaba bien escrito
  • Guiaba a devs nuevos que aún no tenían memorizado el formato Conventional Commits
  • Se integraba con commitlint — el hook commit-msg validaba que el mensaje generado cumpliera las reglas, cerrando el ciclo
  • Velocidad — czg era significativamente más rápido que alternativas como commitizen con cz-conventional-changelog

Instalación

Las secciones siguientes son referencia histórica del flujo anterior. Para el flujo vigente ver wietoo-cli.

czg iba como devDependency en el package.json de cada repo. No se instalaba globalmente.

bun add -d czg cz-git @commitlint/cli @commitlint/config-conventional
{
"type": "module",
"scripts": {
"commit": "bun --bun czg"
},
"devDependencies": {
"@commitlint/cli": "21.0.2",
"@commitlint/config-conventional": "21.0.2",
"cz-git": "1.13.1",
"czg": "1.13.1"
},
"engines": {
"bun": "1.3.14",
"node": "Please use Bun instead of Node to install dependencies",
"npm": "Please use Bun instead of NPM to install dependencies",
"pnpm": "Please use Bun instead of PNPM to install dependencies",
"yarn": "Please use Bun instead of Yarn to install dependencies"
}
}

czg vs cz-gitcz-git es dependencia transitiva de czg, pero se declara explícitamente porque commitlint.config.js la importa directamente (import { defineConfig } from 'cz-git'). commitizen no se usa — en Wiedii solo se invoca bun commitczg.

"type": "module" — todos los repos nuevos en Wiedii usan ESM. El archivo de configuración commitlint.config.js usa import/export default en lugar de require/module.exports.

bun --bun czgbun --bun fuerza el runtime de Bun (más rápido que Node). czg es el binario del wizard (lo instala el paquete czg). El binario para scripts es czg, no git-czg (este último solo habilita el atajo git czg).

engines — patrón Wiedii: mensajes de error en los campos de versión de otros package managers hace explícito que solo se usa Bun.


Uso

# Flujo anterior — referencia histórica
git add .
bun commit # ejecutaba: bun --bun czg → abría el wizard interactivo

El wizard hacía las siguientes preguntas en orden:

  1. Tipofeat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
  2. Scope (opcional) — el módulo o área afectada, ej. auth, api, ui
  3. Título — descripción corta en imperativo, sin mayúscula inicial, sin punto final
  4. Cuerpo (opcional) — descripción larga con contexto adicional
  5. Breaking change — si es un cambio que rompe compatibilidad
  6. Issues relacionados (opcional) — referencia a issues de GitLab ej. #42

El resultado es un mensaje como:

feat(auth): add OAuth2 login with GitLab provider

Implements OAuth2 flow using GitLab as identity provider.
Replaces the previous username/password form.

BREAKING CHANGE: removes /api/login endpoint

Closes #42

Configuración estándar en Wiedii

// commitlint.config.js — ESM (requiere "type": "module" en package.json)
import { defineConfig } from 'cz-git'

export default defineConfig({
extends: ['@commitlint/config-conventional'],
rules: {
'subject-case': [2, 'always', 'lower-case'],
'subject-full-stop': [2, 'never', '.'],
'header-max-length': [2, 'always', 100],
},
prompt: {
messages: {
type: "Select the type of change that you're committing:",
scope: 'Denote the SCOPE of this change (optional):',
customScope: 'Denote the SCOPE of this change:',
subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
footerPrefixesSelect: 'Select the ISSUES type of change (optional):',
customFooterPrefix: 'Input ISSUES prefix:',
footer: 'List any ISSUES by this change. E.g.: #31, #34:\n',
confirmCommit: 'Are you sure you want to proceed with the commit above?',
},
types: [
{ value: 'feat', name: 'feat: ✨ A new feature', emoji: '✨' },
{ value: 'fix', name: 'fix: 🐛 A bug fix', emoji: '🐛' },
{ value: 'docs', name: 'docs: 📝 Documentation only changes', emoji: '📝' },
{ value: 'style', name: 'style: 💄 Changes that do not affect the meaning of the code', emoji: '💄' },
{ value: 'refactor', name: 'refactor: ♻️ A code change that neither fixes a bug nor adds a feature', emoji: '♻️' },
{ value: 'perf', name: 'perf: ⚡️ A code change that improves performance', emoji: '⚡️' },
{ value: 'test', name: 'test: ✅ Adding missing tests or correcting existing tests', emoji: '✅' },
{ value: 'build', name: 'build: 📦️ Changes that affect the build system or external dependencies', emoji: '📦️' },
{ value: 'ci', name: 'ci: 🎡 Changes to CI configuration files and scripts', emoji: '🎡' },
{ value: 'chore', name: "chore: 🔨 Other changes that don't modify src or test files", emoji: '🔨' },
{ value: 'revert', name: 'revert: ⏪️ Reverts a previous commit', emoji: '⏪️' },
],
useEmoji: true,
emojiAlign: 'center',
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
enableMultipleScopes: true,
scopeEnumSeparator: ',',
upperCaseSubject: false,
markBreakingChangeMode: false,
allowBreakingChanges: ['feat', 'fix'],
maxHeaderLength: 100,
maxSubjectLength: 100,
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixes: [
{ value: 'closed', name: 'closed: ISSUES has been processed' },
{ value: 'Fixes', name: 'Fixes: 🐛 Fixes an open ISSUE' },
{ value: 'Ref', name: 'Ref: 🔗 Related ISSUES' },
],
emptyIssuePrefixAlias: 'skip',
customIssuePrefixAlias: 'custom',
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: '',
},
})

changelog.config.js

Archivo separado de commitlint.config.js. Lo consume conventional-changelog / Nx Release para generar CHANGELOG.md. Define los scopes del proyecto y el límite de longitud del mensaje.

// changelog.config.js — ESM
// Sobreescribe 'scopes' con los paquetes reales del repo
export default {
scopes: [], // ← completar con los módulos del proyecto
maxMessageLength: 100,
}

scopes debe reflejar exactamente los mismos valores definidos en commitlint.config.jsrules['scope-enum'] cuando el proyecto tiene scopes fijos.


Integración con lefthook

El hook commit-msg valida el mensaje generado por czg antes de completar el commit:

# lefthook.yaml
commit-msg:
parallel: false
jobs:
- run: mise trust
- run: mise install --yes
commands:
commitlint:
priority: 1
run: mise exec -- bun commitlint --config commitlint.config.js --edit "$1"

Si el mensaje no cumple las reglas de commitlint.config.js, el commit se rechaza con un mensaje de error claro.


Troubleshooting rápido

bun commit abre el wizard pero el commit falla con error de commitlint:

# Verificar que commitlint.config.js existe en la raíz del repo
ls commitlint.config.js

# Probar commitlint manualmente
bun commitlint --from HEAD~1

El wizard no muestra los tipos personalizados:

# Verificar que commitlint.config.js exporta el bloque `prompt`
# y que czg y cz-git están en devDependencies, no en dependencies
cat package.json | grep -E "czg|cz-git"

bun commit no encuentra czg:

# Verificar que está instalado
bun install
ls node_modules/.bin/czg

Referencias