The tenzir-changelog harness curates
changelog entries, ships release notes, and assembles the public changelog
across Tenzir repositories. Use this page as a reference for concepts,
configuration, and CLI details. For step-by-step walkthroughs, see the guide for
maintaining a changelog.
Install
Section titled “Install”tenzir-changelog ships as a Python package that requires Python 3.12 or later.
Install it with uv (or pip) and verify the
console script:
uv add tenzir-changeloguvx tenzir-changelog --helpCore concepts
Section titled “Core concepts”- Project – Identifies which documentation stream the changelog belongs to. Every entry and release references the same project string.
- Entry – A changelog consists of entries. Each entry uses one of four
hard-coded types:
breaking,feature,bugfix, orchange. - Unreleased bucket – Pending entries live in
unreleased/until you move them to a release. - Release – Versioned milestone under
releases/<version>/containingmanifest.yaml,notes.md, and archived entry files inentries/. - Configuration file – Settings live in
config.yamlby default, or you can store them inpackage.yamlalongside thechangelog/directory.config.yamltakes precedence when both exist. - Export style – Controls whether release notes use a detailed card layout
or a compact bullet-list layout. Set
export_style: compactin configuration to prefer the bullet-list format without passing--compacteach time. - Components – You may constrain the optional
componentfield on entries by listing allowed labels in configuration. Component filters apply to the CLI table, exports, and validation.
A typical project layout looks like this:
Directoryproject-root/
Directorychangelog/
- config.yaml
Directoryunreleased/
- 01-add-feature.md
- 02-fix-bug.md
Directoryreleases/
Directoryv1.0.0/
- manifest.yaml
- notes.md
Directoryentries/
- 01-add-feature.md
- 02-fix-bug.md
For a package layout (with package.yaml), the
structure may look like:
Directorymy-package/
- package.yaml
Directorychangelog/
Directoryunreleased/
- …
Directoryreleases/
- …
Commands
Section titled “Commands”Run changelog commands from the project root or the changelog/ directory:
uvx tenzir-changelog [command] [options]All commands accept --config to point at an explicit configuration file (YAML
format, defaulting to config.yaml) and --root to operate on another
repository. When you omit both options, the CLI looks for config.yaml inside
the changelog root or, failing that, for a package.yaml one directory above
the changelog folder. This package mode lets you run commands from either the
package root or the changelog/ directory without repeating --root.
Display changelog entries in multiple views.
tenzir-changelog show [identifiers...] [options]| Option | Description |
|---|---|
identifiers | Row numbers, entry IDs, release versions, or - (optional) |
-c/--card | Show detailed cards for matching entries |
-m/--markdown | Export as Markdown |
-j/--json | Export as JSON |
--compact | Use compact bullet-list layout |
--no-compact | Use detailed card layout |
--no-emoji | Remove type emoji from output |
--project <id> | Filter to specific project |
--component <label> | Filter to specific component |
--banner <text> | Add banner text to table output |
The table view (default) lists entries with ID, title, type, project, PRs, and
authors. Row numbers count backward from the newest entry, so #1 always
targets the latest change.
Create a new changelog entry in unreleased/.
tenzir-changelog add [options]| Option | Description |
|---|---|
--title <text> | Entry title |
--type <type> | breaking, feature, bugfix, or change |
--description <text> | Entry body |
--author <name> | Contributor name (repeatable) |
--pr <number> | Pull request number (repeatable) |
--component <label> | Component label (must match configuration) |
--web | Open prefilled GitHub file creation URL |
The command prompts for any information you do not pass explicitly. The first
invocation scaffolds config.yaml, unreleased/, and releases/
automatically. The CLI assigns globally sequential filenames with numeric
prefixes (e.g., 01-feature-name.md).
release create
Section titled “release create”Stage a release under releases/<version>/.
tenzir-changelog release create [version] [options]| Option | Description |
|---|---|
version | Release version (e.g., v1.0.0) |
--patch | Bump patch version from latest release |
--minor | Bump minor version from latest release |
--major | Bump major version from latest release |
--yes | Commit changes (default is dry run) |
--intro <text> | Inline intro text (mutually exclusive with --intro-file) |
--intro-file <path> | Path to intro file (mutually exclusive with --intro) |
--compact | Use bullet-list layout for notes.md |
--date <YYYY-MM-DD> | Override release date |
The command renders notes.md, updates manifest.yaml, and moves entry files
into entries/. It performs a dry run by default. When the release already
exists, the CLI appends additional unreleased entries.
release notes
Section titled “release notes”Re-export release notes without modifying files.
tenzir-changelog release notes <identifier> [options]| Option | Description |
|---|---|
identifier | Release version or - for unreleased |
-m | Export as Markdown (default) |
-j | Export as JSON |
--compact | Use bullet-list layout |
--no-emoji | Drop type icons |
release publish
Section titled “release publish”Publish a release to GitHub via gh.
tenzir-changelog release publish <version> [options]| Option | Description |
|---|---|
version | Release version |
--yes | Skip confirmation prompts |
--draft | Mark as draft |
--prerelease | Mark as prerelease |
--tag | Create and push annotated Git tag |
The command reads project metadata from config.yaml or package.yaml for the
repository slug and uses notes.md as the release body.
validate
Section titled “validate”Run structural checks across entry files, release manifests, and exported documentation.
tenzir-changelog validateThe validator reports missing metadata, unused entries, duplicate entry IDs, and configuration drift across repositories.
Configuration
Section titled “Configuration”Configuration settings live in config.yaml by default, or you can store them
in package.yaml alongside the changelog/ directory. config.yaml takes
precedence when both exist.
Configuration fields:
| Field | Description |
|---|---|
id | Canonical project slug written into entry frontmatter (required) |
name | Human-friendly label surfaced in release titles and CLI output |
description | Optional project description included in release manifests |
repository | Optional GitHub slug (e.g., owner/repo) used by release publish |
export_style | Default layout: compact (bullet-list) or omit for detailed cards |
components | Optional list of component labels that entries must satisfy |
Example:
id: tenzir-corename: Tenzir Coredescription: Core pipeline enginerepository: tenzir/tenzirexport_style: compactcomponents: - cli - engine - operatorsThe first invocation of tenzir-changelog add scaffolds config.yaml
automatically, inferring defaults from the directory name. Projects with
package.yaml next to changelog/ reuse the package id and name
automatically.
Entry file format
Section titled “Entry file format”Entry files live in unreleased/ or releases/<version>/entries/ as Markdown
files with YAML frontmatter. The CLI assigns sequential numeric prefixes (e.g.,
01-feature-name.md, 02-bugfix.md).
Example entry:
---title: Add pipeline buildertype: featureauthors: - alicecreated: 2025-10-16prs: - 101component: cli---
Introduces the new pipeline builder UI with drag-and-drop support.Frontmatter fields:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | yes | Entry title |
type | string | yes | breaking, feature, bugfix, or change |
authors | list[string] | no | Contributor names |
created | string | yes | Creation date in YYYY-MM-DD format |
prs | list[int] | no | Pull request numbers |
component | string | no | Label matching configured components |
Release manifest format
Section titled “Release manifest format”Release manifests live at releases/<version>/manifest.yaml and record metadata
about a release.
Example manifest:
created: 2025-10-18intro: | Welcome to version 1.0.0!
This release includes significant performance improvements.Manifest fields:
| Field | Type | Required | Description |
|---|---|---|---|
created | string | yes | Release date in YYYY-MM-DD format |
intro | string | no | Introductory content (supports Markdown) |
The CLI generates notes.md by stitching together the intro and grouped entry
sections. Intro content comes from either --intro (inline text) or
--intro-file (file path) when creating a release.
Environment variables
Section titled “Environment variables”The CLI recognizes these environment variables:
| Variable | Description |
|---|---|
GITHUB_TOKEN | GitHub token with repo scope for private repos |
Multi-project mode
Section titled “Multi-project mode”For managing multiple related projects, tenzir-changelog supports coordinated
changelog operations across multiple project roots using the --root flag
repeatedly.
When you specify multiple --root flags, the CLI enters multi-project mode:
- The
showcommand displays entries from all projects in a unified table with a Project column, sorting entries by project order (as specified by--rootflags) and then by date within each project. - Markdown and JSON exports group entries by project using a hierarchical format: version → project → entry type → entries.
- The
release createcommand performs atomic coordinated releases across all projects. If any project fails validation (e.g., the version already exists), the CLI makes no changes to any project.
Use --project <id> to filter output to specific projects. Entry identifiers
may repeat across projects, and the CLI keeps them correctly scoped to their
origin project when rendering tables or exports.
Multi-project markdown exports follow this hierarchical structure:
# v5.0.0
## Tenzir Core
### Features
- **Add pipeline builder**: Introduces the new pipeline builder UI.
## Tenzir Cloud
### Features
- **Add SSO support**: Integrates enterprise SSO for authentication.Troubleshooting
Section titled “Troubleshooting”- Validation errors – Run
tenzir-changelog validateto identify missing metadata, unused entries, or duplicate IDs. - Component mismatch – When
componentsis configured, ensure every entry either omitscomponentor uses an allowed label. - Configuration not found – Ensure
config.yamlexists in the changelog root orpackage.yamlsits next to thechangelog/directory. Runtenzir-changelog addonce to scaffold the configuration. - Version bump fails – Bump flags read the latest release manifest on disk.
Create an initial release with an explicit version before using
--patch/--minor/--major.