imba-commitlint
v1.0.3
Published
A lightweight commitlint tool powered by Bun — validates Conventional Commits format
Downloads
203
Maintainers
Readme
imba-commitlint
A lightweight commitizen adapter built with Bun + TypeScript. It provides an interactive prompt to generate Conventional Commits format messages, compatible with cz-customizable configuration files.
Features
- Interactive commit message prompt (type, scope, ticket number, subject, body, breaking changes, footer)
- Compatible with existing
.cz-config.js/.cz-config.jsonfiles — drop-in replacement forcz-customizable - Config auto-discovery (walks up from cwd)
- Scope overrides per commit type
- Ticket number support with custom prefix/suffix and validation
- Breaking change detection and formatted output
- Text wrapping (no
word-wrapdependency) - Special character escaping for shell safety
- Edit mode — open commit message in
$EDITORbefore finalizing
Installation
bun add -d imba-commitlintUsage
With commitizen
Configure commitizen to use imba-commitlint as the adapter in package.json:
{
"config": {
"commitizen": {
"path": "imba-commitlint"
}
}
}Then commit as usual:
git cz
# or
npx czConfiguration
Create a .cz-config.js or .cz-config.json in your project root. The config format matches cz-customizable:
// .cz-config.js
module.exports = {
types: [
{ name: 'feat', value: 'feat' },
{ name: 'fix', value: 'fix' },
{ name: 'docs', value: 'docs' },
{ name: 'refactor', value: 'refactor' },
{ name: 'perf', value: 'perf' },
{ name: 'test', value: 'test' },
{ name: 'chore', value: 'chore' },
{ name: 'style', value: 'style' },
],
scopes: [
{ name: 'core' },
{ name: 'api' },
{ name: 'ui' },
],
scopeOverrides: {
fix: [
{ name: 'hotfix' },
],
},
allowCustomScopes: true,
skipEmptyScopes: true,
allowBreakingChanges: ['feat', 'fix'],
subjectLimit: 100,
upperCaseSubject: false,
ticketNumberPrefix: 'JIRA-',
ticketNumberSuffix: ' -',
allowTicketNumber: true,
isTicketNumberRequired: false,
ticketNumberRegExp: '\\d{2,5}',
fallbackTicketNumber: '000',
prependTicketToHead: false,
footerPrefix: 'ISSUES CLOSED:',
breakingPrefix: 'BREAKING CHANGE:',
subjectSeparator: ': ',
typePrefix: '',
typeSuffix: '',
breaklineChar: '|',
usePreparedCommit: false,
askForBreakingChangeFirst: false,
skipQuestions: ['body', 'footer'],
messages: {
type: "Select the type of change that you're committing:",
scope: '\nDenote the SCOPE of this change (optional):',
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):\n',
footer: 'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
confirmCommit: 'Are you sure you want to proceed with the commit above?',
},
}Config resolution order
The adapter searches for configuration in this order:
.cz-config.js— walks up from cwd through parent directories.cz-config.json— same walk, looking for JSON variantpackage.json→config.cz-customizable.configfield
As a library
import { buildCommit, readConfigFile } from 'imba-commitlint'
const config = await readConfigFile()
const message = buildCommit({
type: 'feat',
scope: 'core',
subject: 'add rate limiting',
body: 'Implements token bucket algorithm',
}, config)
// → "feat(core): add rate limiting\n\nImplements token bucket algorithm"Configuration options
| Option | Type | Default | Description |
|---|---|---|---|
| types | Array<{name, value?}> | — | Commit types shown in prompt |
| scopes | Array<{name, value?}> | — | Available scopes |
| scopeOverrides | Record<string, Array<{name, value?}>> | — | Per-type scope overrides |
| allowCustomScopes | boolean | — | Allow typing custom scopes |
| skipEmptyScopes | boolean | false | Skip scope step when no scopes defined |
| subjectLimit | number | 100 | Max subject length |
| upperCaseSubject | boolean | false | Auto-capitalize first letter of subject |
| allowTicketNumber | boolean | — | Show ticket number prompt |
| isTicketNumberRequired | boolean | — | Require ticket number |
| ticketNumberPrefix | string | — | Prefix for ticket number (e.g. JIRA-) |
| ticketNumberSuffix | string | — | Suffix for ticket number (e.g. -) |
| ticketNumberRegExp | string | — | Validation regex for ticket number |
| fallbackTicketNumber | string | — | Default ticket number |
| prependTicketToHead | boolean | false | Place ticket number at start (before type) |
| footerPrefix | string | 'ISSUES CLOSED:' | Footer label |
| breakingPrefix | string | 'BREAKING CHANGE:' | Breaking change label |
| subjectSeparator | string | ': ' | Separator between type/scope and subject |
| typePrefix / typeSuffix | string | '' | Wrap type with prefix/suffix |
| breaklineChar | string | '\|' | Character used for line breaks in body |
| usePreparedCommit | boolean | false | Pre-fill from last commit message |
| askForBreakingChangeFirst | boolean | false | Ask breaking before body |
| skipQuestions | string[] | — | Skip specific prompt steps |
| messages | object | — | Custom prompt messages for each step |
| additionalQuestions | Array<{name, type, message, ...}> | — | Custom additional prompt questions |
Development
bun run build # Build to dist/
bun test # Run tests
bun run lint # Lint with oxlintBuilt with Bun + TypeScript.
