brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
commitlintcommitlint checks that Git commit messages follow the Conventional Commits format (type(scope): subject) and fails when they do not. Use when a user asks to standardize commit messages, enforce commit conventions with a husky commit-msg hook, lint commits or PR commits in CI, customize rules, or prepare commits for automated changelogs and semantic versioni…
Independent GitHub snapshot · Automated classification · Original documentation governs
commitlint (@commitlint/cli, v21 at the time of writing) lints a commit message against a rule set; the usual rule set is @commitlint/config-conventional, which enforces type(scope?): subject. It requires Node.js 22.12 or newer. It runs in a Git commit-msg hook (typically via husky) and in CI. Valid messages let tools such as semantic-release, release-please, changesets or conventional-changelog derive version bumps and changelogs.
npm install -D @commitlint/cli @commitlint/config-conventional husky
npx husky init
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
npx husky init also creates .husky/pre-commit containing npm test, which makes every commit fail in a project without tests. Edit or empty that file if you do not want it.
Create commitlint.config.mjs (or commitlint.config.js with "type": "module", .cjs, .ts, .commitlintrc.*, or a commitlint key in package.json).
// commitlint.config.mjs
export default {
extends: ['@commitlint/config-conventional'],
rules: {
// [severity, applicable, value]; severity 0 off, 1 warning, 2 error
'scope-enum': [2, 'always', ['auth', 'api', 'billing', 'ui', 'deps']],
'scope-case': [2, 'always', 'kebab-case'],
'header-max-length': [2, 'always', 72],
},
}
The default type-enum is build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test. If you override type-enum, repeat the types you still want, including revert. Default config-conventional limits headers and body/footer lines to 100 characters and forbids sentence-case subjects and trailing periods.
echo "updated stuff" | npx commitlint # exit 1: subject and type may not be empty
echo "feat(auth): add Google OAuth login" | npx commitlint # exit 0
git commit -m "fix(api): handle null response from /users" # hook runs commitlint
# .github/workflows/commitlint.yml
name: commitlint
on: [pull_request]
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
Other useful forms: npx commitlint --last (latest commit), --from origin/main (everything since main), --config path for a non-default config. If you squash-merge, lint the PR title instead of the individual commits.
User request: "Make everyone on the team use conventional commits."
Run Step 1 and Step 2, empty .husky/pre-commit if the repo has no npm test, and commit commitlint.config.mjs and .husky/. Then git commit -m "updated stuff" is rejected with type may not be empty [type-empty], and git commit -m "feat(billing): add annual plan" succeeds. Add a prepare script ("prepare": "husky", which husky init sets) so teammates get hooks after npm install.
User request: "Only allow scopes that match our package names."
Set 'scope-enum': [2, 'always', ['web', 'api', 'worker']]. Then echo "feat(mobile): add push" | npx commitlint exits 1 with scope must be one of [web, api, worker] [scope-enum], while fix(api): retry on 503 passes.
git commit --no-verify; keep the CI check as the enforcement point.subject-max-length does not exist in config-conventional by default; the header limit is header-max-length (100).feat!: or a BREAKING CHANGE: footer and map to a major version; feat maps to minor, fix to patch.