JS API
StandardChangelog is ConventionalChangelog with the Angular preset preloaded. It exposes the exact same chainable builder — you configure where commits, tags, the version and repository come from, then generate the changelog with write() or writeStream() — but you don’t need to load a preset first.
import { StandardChangelog } from 'standard-changelog'Quick example
Section titled “Quick example”Read the version from package.json and print the changelog — no loadPreset() call needed:
import { StandardChangelog } from 'standard-changelog'
const generator = new StandardChangelog(process.cwd()) .readPackage()
for await (const chunk of generator.write()) { process.stdout.write(chunk)}This prints the same Markdown as the CLI — see the CLI examples for what the output looks like.
Constructor
Section titled “Constructor”new StandardChangelog(cwdOrGitClient: string | ConventionalGitClient)Pass a working directory or a ConventionalGitClient instance. Unlike ConventionalChangelog, the argument is required:
import { StandardChangelog } from 'standard-changelog'import { ConventionalGitClient } from '@conventional-changelog/git-client'
new StandardChangelog(process.cwd())new StandardChangelog(new ConventionalGitClient('/path/to/repo'))Builder methods
Section titled “Builder methods”All methods return this for chaining, except write() and writeStream(), which generate the output. They are inherited unchanged from ConventionalChangelog:
| Method | Purpose |
|---|---|
loadPreset(preset, loader?) | Override the built-in Angular preset with another one. |
config(config) | Set the preset config object ({ tags, commits, parser, writer }) directly. |
readPackage(path?, transform?) | Find and read package.json for the version and repository (falls back to git remote origin for the repository). |
package(pkg) | Set package data directly. |
readRepository() | Read the repository URL from git remote origin. |
repository(infoOrGitUrl) | Set repository info or a git URL directly. |
tags(params) | Configure how semver tags are read. |
commits(params, parserOptions?) | Configure the commit range and parser options. |
options(options) | Generator options — release count, append, loggers, etc. |
context(context) | Extra changelog writer context template variables. |
writer(params) | Changelog Writer options — templates, grouping, sorting. |
write(includeDetails?) | Generate the changelog (async generator). |
writeStream(includeDetails?) | Generate the changelog as a Node.js stream. |
Package and repository
Section titled “Package and repository”readPackage() provides both the version and the repository. It reads the nearest package.json (walking up from the working directory, or from an explicit path), taking the version from its version field and the commit/version links from its repository field. When package.json has no repository, it falls back to the git remote origin URL:
generator.readPackage() // nearest package.jsongenerator.readPackage('./package.json') // or an explicit pathUse readRepository() or repository() only when you set the package data yourself (which skips that fallback), or want to force reading the URL from git:
generator .package({ version: '1.2.0' }) // no repository field .readRepository() // read it from `git remote origin`
generator.repository('https://github.com/acme/app.git') // or set it directlyTags and commit range
Section titled “Tags and commit range”tags() controls which git tags count as releases; commits() controls the commit range and parsing:
generator .tags({ prefix: 'v', // only tags like v1.2.0 skipUnstable: true // ignore x.x.x-rc.1, etc. }) .commits({ path: 'packages/api', // only commits touching this directory from: 'v1.0.0', // range start (tag or SHA) to: 'HEAD' // range end })See GetSemverTagsParams and GetCommitsParams for all fields.
Options
Section titled “Options”Passed to options():
| Option | Type | Default | Description |
|---|---|---|---|
reset | boolean | false | Reset the changelog instead of extending it. |
append | boolean | false | Append newer releases below older ones. |
releaseCount | number | 1 | How many releases to generate, counting from the latest. 0 generates all. |
outputUnreleased | boolean | auto | Emit unreleased commits; the version becomes Unreleased. |
transformCommit | (commit, params) => Partial<Commit> | null | Promise<…> | Transform each parsed commit before it is written. | |
warn | (source, messages) => void | Logger for warnings. | |
debug | (source, messages) => void | Logger for debug messages. | |
formatDate | (date) => string | Custom date formatter for release headings. |
generator.options({ releaseCount: 0, formatDate: date => new Date(date).toISOString().slice(0, 10)})Consuming the output
Section titled “Consuming the output”write() returns an async generator that yields one chunk per release; writeStream() wraps the same output in a Node.js Readable:
import { createWriteStream } from 'node:fs'
// (1) Async iterationfor await (const section of generator.write()) { console.log(section)}
// (2) Node.js streamgenerator .writeStream() .pipe(createWriteStream('CHANGELOG.md'))Real-world example
Section titled “Real-world example”Generating per-package release notes in a monorepo — the pattern used by release tooling such as simple-release:
import { StandardChangelog } from 'standard-changelog'import { ConventionalGitClient } from '@conventional-changelog/git-client'
const gitClient = new ConventionalGitClient(projectPath)
const changelog = new StandardChangelog(gitClient) .commits({ path: projectPath }) // only commits under this package .tags({ prefix: tagPrefix }) // e.g. "my-pkg-v" .readRepository() // link commits and versions to the host .context({ version: nextVersion }) // the version about to be released .writer({ preamblePartial }) // optional preamble for the release section
for await (const section of changelog.write()) { // append `section` to the package's CHANGELOG.md}Package-prefixed (Lerna-style) tags
Section titled “Package-prefixed (Lerna-style) tags”For monorepos that tag releases as name@1.2.0, build the prefix with the exported packagePrefix helper:
import { StandardChangelog, packagePrefix } from 'standard-changelog'
const generator = new StandardChangelog(process.cwd()) .readPackage() .tags({ prefix: packagePrefix('my-package') // matches my-package@1.2.0 tags })Details objects
Section titled “Details objects”Passing true to write() (or writeStream()) yields structured objects instead of Markdown strings — useful for building custom output:
| Field | Type | Description |
|---|---|---|
log | string | Rendered Markdown for one release. |
keyCommit | Commit | null | The commit identifying the release, or null. |
for await (const { log, keyCommit } of generator.write(true)) { console.log(keyCommit?.version, log.length)}Exported helpers
Section titled “Exported helpers”standard-changelog re-exports the conventional-changelog helpers — packagePrefix, guessNextTag, isUnreleasedVersion, and defaultCommitTransform — alongside the ConventionalChangelog class itself.