# cz-conventional-changelog, the Commitizen adapter for Angular style commits

> cz-conventional-changelog is a Commitizen adapter that prompts for commit messages in the conventional changelog format used by the Angular preset. It is a small prompt layer, configured from package.json or environment variables, meant for teams that want the commit message format asked for rather than enforced by a linter.

**commitizen/cz-conventional-changelog** — A commitizen adapter for the angular preset of https://github.com/conventional-changelog/conventional-changelog

- Repository: https://github.com/commitizen/cz-conventional-changelog
- Stars: 795 · Forks: 443
- Language: JavaScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/commitizen-cz-conventional-changelog

## The gap between a commit linter and a commit prompt

Commitizen is a tool that asks questions in the terminal and assembles the answers into a commit message. An adapter is the part that supplies the questions. cz-conventional-changelog is one such adapter, and the README describes it as prompting for the conventional changelog standard, specifically the angular preset of the conventional-changelog project.

That distinction matters for how teams adopt it. A linter reacts after the fact: the commit is written, a rule rejects it, and the developer rewrites. A prompt adapter acts before the commit exists, so the format is chosen from a menu rather than typed from memory. Neither approach replaces the other, and the documentation here is explicit that this adapter exists to help the case where the developer has not yet learned the format.

The scope is narrow by design. The repository is four meaningful JavaScript files, index.js and engine.js with their tests, plus package.json. The dependencies are the Commitizen library itself, conventional-commit-types for the type list, chalk for terminal colour, lodash.map, longest and word-wrap for text handling. That is the whole cost of the tool: a prompt, a set of types and some formatting rules.

## Configuration lives in package.json under config.commitizen

Configuration follows the Commitizen convention, so the adapter is pointed at through the config.commitizen key in package.json. The README shows the shape of that block, and the path property is what connects Commitizen to this adapter:

```json
{
// ...  default values
    "config": {
        "commitizen": {
            "path": "./node_modules/cz-conventional-changelog",
            "disableScopeLowerCase": false,
            "disableSubjectLowerCase": false,
            "maxHeaderWidth": 100,
            "maxLineWidth": 100,
            "defaultType": "",
            "defaultScope": "",
            "defaultSubject": "",
            "defaultBody": "",
            "defaultIssues": "",
            "types": {
```

The types object continues with one entry per commit type, each carrying a description for the prompt and a title for grouping:

```json
              ...
              "feat": {
                "description": "A new feature",
                "title": "Features"
              },
              ...
            }
        }
    }
// ...
}
```

Several things are adjustable here. The two disable flags control whether scope and subject are forced to lower case, so a team that prefers capitalised subjects can turn that behaviour off rather than fighting the prompt. The maxHeaderWidth and maxLineWidth values are character limits applied to the header and the body. The default properties prefill answers, which is how a repository can make the type field default to something specific instead of leaving it empty.

The types object is the most interesting part. Each entry carries a description shown in the prompt and a title used for grouping, so a team can rename or extend the conventional changelog type list. The shipped example defines feat as a new feature under a Features heading.

One nuance worth knowing: the path in the README example points into node_modules, while the adapter's own package.json sets the path to ./index.js. Both work, but they are different resolutions. A path that points at node_modules assumes the package is installed, whereas a relative path to the checked in file assumes you vendor or link it.

## Environment variables override a narrow slice of the settings

Any default or package.json based setting can be overridden by an environment variable, and the README lists six of them:

```bash
CZ_TYPE = defaultType
CZ_SCOPE = defaultScope
CZ_SUBJECT = defaultSubject
CZ_BODY = defaultBody
CZ_MAX_HEADER_WIDTH = maxHeaderWidth
CZ_MAX_LINE_WIDTH = maxLineWidth
```

The mapping is one to one and easy to reason about, which makes these variables useful in CI or in a hook that pre-fills a type for a release commit. What they do not cover is the rest of the configuration. The types list, the two lower case flags and the defaultIssues value are not exposed this way, so a pipeline that needs a different type list has to change package.json rather than set an environment variable.

That asymmetry matters more than it looks. The env vars are a convenience for the values a human changes occasionally, not a complete alternative to file based configuration. If your CI expects a fixed commit prefix for a release, CZ_TYPE and CZ_SUBJECT will do it, but a release commit that also needs a special scope list will not be covered here.

## Commitlint compatibility is about one number

The adapter can cooperate with commitlint, the linting library for commit messages, and the cooperation is narrow and precise. When commitlint is present, the maxHeaderWidth property defaults to the value of commitlint's header-max-length rule rather than to the hard coded value of 100.

The mechanics are visible in the package manifest. The commitlint loader appears as an optional dependency, @commitlint/load, so the adapter does not force commitlint on a project that does not use it. When the package is absent, the fallback is the hard coded 100.

The reason this is worth caring about is that two tools can disagree about the same limit. If the adapter wrapped the header at 100 characters while commitlint rejected anything above 80, the developer would fight the tool every time. The tie to the lint rule removes that conflict, and the README notes that the value can still be overridden by setting maxHeaderWidth in package.json or by exporting CZ_MAX_HEADER_WIDTH.

Note what is not covered. The integration concerns header length only. Types, scopes and body rules from a commitlint configuration are not read by the adapter, so a commitlint setup that allows custom scopes or enforces a body footer will not make the prompt stricter.

## How the adapter is installed and driven from a project

The package is published on npm under the name cz-conventional-changelog, and it is a Commitizen adapter, so it is used through Commitizen rather than as a standalone command. The adapter's own manifest lists Commitizen as a runtime dependency, and the conventional way to reach it is the git-cz command that Commitizen provides.

The adapter's package.json defines the script that a project would call:

```json
  "scripts": {
    "commit": "git-cz",
    "test": "mocha *.test.js",
    "format": "prettier --write *.js",
    "semantic-release": "semantic-release"
  },
```

The commit script is the entry point in practice. Running it starts the prompt, and the answers become the commit message that Commitizen passes to git. A project that adds this adapter also needs a config.commitizen block pointing at it, since Commitizen reads that key to find the adapter to load.

The runtime floor is stated in the manifest, with engineStrict set and node required at version 16 or newer. The engineStrict flag is intended to make the version requirement binding, though modern npm tooling largely treats engines as advisory.

The remaining scripts reveal how the project itself is worked on. Mocha runs the tests, Prettier formats the JavaScript, and semantic-release handles publishing. A renovate.json at the repository root points at automated dependency updates, which is the likely reason the manifest carries newer dependency versions than the last published release does.

## Where this adapter stops being the right answer

The first limitation is the fixed prompt set. The conventional format has a type, an optional scope, a subject and an optional body, and that is what you get. If your project needs a different structure, a template with placeholders, or a required trailer line in every message, this adapter does not offer a mechanism for it. The types object lets you rename and add types, but it does not let you add a new field to the message.

The second is the division of responsibility. The adapter prompts, it does not check. Nothing here rejects a malformed commit, and the commitlint integration only borrows a single number. A team that wants guarantees in CI needs a linter in the pipeline regardless of whether the prompt exists.

The third is the release history. The published versions stop at v3.3.0 on 2020-08-26, and the manifest itself carries the placeholder version 0.0.2, which is the sort of value that semantic-release overwrites at publish time. So the source in the repository has moved on since 2020, with dependency updates and formatting changes, while the last artifact on npm is from that year. That is not automatically a problem for a package with no runtime surprises, but it does mean the version you install is older than the code you read, and new Node versions are supported in the repository without necessarily being supported by the published tarball.

The fourth is Node itself. The manifest requires Node 16 or newer and enforces it, so this adapter is out of reach for a runtime policy pinned below that.

## Maintenance, licensing and the upgrade path

The last push to the repository was on 2026-10-13, so the source is receiving updates, and the presence of renovate.json suggests those updates are largely dependency bumps rather than new features. The npm release trail, by contrast, ends at v3.3.0 on 2020-08-26, with v3.2.1 and v3.2.0 shortly before it.

The gap between an actively pushed repository and a dormant release feed is the single most important fact for an adopter here. If you install from npm you get code from 2020 with the dependency ranges that shipped then, on a runtime that has moved on. If you install from the repository you get the current source, which requires building or linking it. Neither path is documented as an install option in the README, so decide which one you want before standardising on it.

The licence is MIT, which places no obligations on your own code beyond attribution and makes the adapter safe to embed in a proprietary toolchain. That is a licensing note, not legal advice. The upgrade cost in practice is small because the configuration surface is small, but it is not zero: a change to the types list or to the width behaviour can alter the commit messages your CI tooling parses, so re-read the CHANGELOG before bumping the version in a shared repository.

## Conclusion

cz-conventional-changelog fits teams already using Commitizen that want the conventional format prompted at commit time and are willing to accept the adapter's fixed prompt set, its Node 16 floor and the fact that npm releases stopped at v3.3.0 in 2020 while the repository itself was pushed to on 2026-10-13. It does not fit teams that need custom commit types, teams on an older Node runtime, or teams that would rather reject bad messages than prompt for them, since commitlint is a separate tool with a separate workflow. Verify first that the types list in your package.json matches the types your CI expects, that the path under config.commitizen resolves to the adapter you installed, and that your commitlint header-max-length rule and this adapter agree on the line width.

## FAQ

### How do I install and configure cz-conventional-changelog in a project?

The package is published on npm as cz-conventional-changelog and is loaded through Commitizen. Point the config.commitizen path in package.json at it, for example at ./node_modules/cz-conventional-changelog, and call the git-cz command that the adapter's own package.json uses in its commit script.

### Which environment variables can override cz-conventional-changelog settings?

Six are documented: CZ_TYPE, CZ_SCOPE, CZ_SUBJECT, CZ_BODY, CZ_MAX_HEADER_WIDTH and CZ_MAX_LINE_WIDTH. They map onto defaultType, defaultScope, defaultSubject, defaultBody, maxHeaderWidth and maxLineWidth respectively, and the types list is not among them.

### How does cz-conventional-changelog work with commitlint?

The commitlint loader is an optional dependency, so the library is used only if the project already has it. When it is present, maxHeaderWidth defaults to the commitlint header-max-length rule value instead of the hard coded 100, and it can still be overridden in package.json or through CZ_MAX_HEADER_WIDTH.

### Can I add my own commit types to cz-conventional-changelog?

Yes. The types object in the config.commitizen block holds an entry per type, each with a description shown in the prompt and a title for grouping, and the README shows feat defined with the description A new feature and the title Features.

### What Node version does cz-conventional-changelog require?

The package manifest sets engineStrict and requires node at version 16 or newer, so the requirement is declared to be binding, though npm tooling may treat it as advisory.

## Sources

- [commitizen/cz-conventional-changelog on GitHub](https://github.com/commitizen/cz-conventional-changelog)
- [Issues](https://github.com/commitizen/cz-conventional-changelog/issues)
- [License: MIT](https://github.com/commitizen/cz-conventional-changelog/blob/master/LICENSE)
- [README](https://github.com/commitizen/cz-conventional-changelog/blob/master/README.md)
- [Releases](https://github.com/commitizen/cz-conventional-changelog/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/commitizen-cz-conventional-changelog
