Automated changelog generation from git commits.

Install

mkdir -p .claude/skills/changelog-psenger && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12350" && unzip -o skill.zip -d .claude/skills/changelog-psenger && rm skill.zip

Installs to .claude/skills/changelog-psenger

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Updates CHANGELOG.md by collecting git commits since the last tag, categorising them into Keep a Changelog v1.1.0 sections (Added, Changed, Fixed, etc.), and cutting a new versioned release entry. Called autonomously by the `release` skill. Accepts VERSION and optional DATE arguments. Do not trigger on general conversation — only activate when explicitly called by another skill or invoked directly as /changelog <version> [date].
432 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Update `CHANGELOG.md` with new release entries
  • Categorize git commits into Keep a Changelog sections
  • Handle conventional commit prefixes for section mapping
  • Bootstrap `CHANGELOG.md` if it does not exist
  • Collapse old entries to links-only based on a threshold

How it works

The skill collects git commits since the last tag, categorizes them based on conventional commit prefixes, and updates `CHANGELOG.md` with a new versioned release entry and comparison links.

Inputs & outputs

You give it
A semantic version string and optional date, git commit history
You get back
An updated `CHANGELOG.md` file with a new versioned release entry and comparison links

When to use changelog

  • Generate release changelog
  • Update project history
  • Automate release notes

About this skill

Changelog Skill

Usage

Called by the release skill, or directly:

/changelog <version>
/changelog <version> <date>

Examples:

/changelog 1.2.0
/changelog 1.2.0 2026-05-19

Arguments:

  • VERSION — required. Semantic version string, e.g. 1.2.0 or 2.0.0-beta.1.
  • DATE — optional. ISO date YYYY-MM-DD. Defaults to today.
  • MAX_FULL_ENTRIES — optional. Integer. When the file already contains more than this many versioned entries, entries beyond the threshold are collapsed to links-only (heading and comparison link remain; entry body is removed). Default: no limit (all entries kept in full).

Commit-to-Section Mapping

Conventional Commits prefixes map to Keep a Changelog sections:

Commit prefixChangelog section
feat: / feat!:Added
fix: / fix!:Fixed
security:Security
deprecate:Deprecated
remove: / revert:Removed
refactor: / perf: / style:Changed
docs:Changed
chore: / ci: / build: / test:(skip — not user-facing)
(no recognised prefix)Changed
Any commit with BREAKING CHANGE in body or ! after typePrefix entry with BREAKING:

Chores that are always skipped, even when they look meaningful:

  • Version bump commits ("Bump version to X.Y.Z", "chore: release X.Y.Z") — the versioned heading itself is the release record; a separate entry would duplicate it.
  • Tagging commits — implied by the heading date and comparison link.
  • Dependency version bumps (build(deps):, chore(deps):) without an explicit security advisory callout in the commit body — purely internal. If a commit message explicitly names a CVE or advisory (e.g. "fix CVE-2025-1234"), treat it as security: and include it under Security.
  • Changelog update commits ("docs: update CHANGELOG") — the file is self-describing.

Step 1 — Resolve Arguments

Parse VERSION from the argument. If missing, stop:

"Usage: /changelog <version> [date] Example: /changelog 1.2.0"

Resolve DATE: use the supplied date if provided, otherwise use today's date in YYYY-MM-DD format.


Step 2 — Detect Repository Context

# Get the GitHub repo URL for comparison links
git remote get-url origin

Derive REPO_URL in https://github.com/{owner}/{repo} form by converting SSH remote syntax ([email protected]:{owner}/{repo}.git) if needed.


Step 3 — Find the Last Tag

git tag --sort=-version:refname | head -1

Store as LAST_TAG. If no tags exist, store as empty string and collect the full commit history in Step 4.


Step 4 — Collect Commits

# With a previous tag
git log {LAST_TAG}..HEAD --oneline --no-merges --format="%s"

# No previous tag — full history
git log --oneline --no-merges --format="%s"

Collect all commit subjects. Ignore merge commits (--no-merges). Store as COMMITS.


Step 5 — Categorise Commits

For each commit subject in COMMITS:

  1. Strip the scope, e.g. feat(books): add Sirach alias → type feat, message add Sirach alias.
  2. Check for ! after the type or BREAKING CHANGE in the full commit body — if present, mark as breaking.
  3. Map the type to a section using the table above.
  4. Skip commits that map to (skip).
  5. Format each entry as - {message} (sentence-case, no trailing period).
  6. Prefix breaking entries: - **BREAKING:** {message}.

Build a map of section → list of entries. Only include sections that have at least one entry.

Section order in output: Added, Changed, Deprecated, Removed, Fixed, Security.


Step 6 — Bootstrap CHANGELOG.md if Missing

If CHANGELOG.md does not exist at the project root, create it:

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

<!-- comparison links — maintained automatically by the changelog skill -->

Step 7 — Build the New Release Section

Construct the versioned entry block:

## [{VERSION}] - {DATE}

### Added
- entry one
- entry two

### Fixed
- entry three

Only include section headings that have entries. If COMMITS is empty (no user-facing changes), add a single entry under Changed:

### Changed
- Internal maintenance and dependency updates

Step 8 — Update CHANGELOG.md

Read the current CHANGELOG.md. Apply these edits in order:

  1. Replace the ## [Unreleased] block — remove all content between ## [Unreleased] and the next ## [ heading (or end of file before the links section). Insert the new versioned release section in its place.

  2. Re-insert a blank ## [Unreleased] section above the new versioned section:

    ## [Unreleased]
    
    ## [{VERSION}] - {DATE}
    ...
    
  3. Update or create comparison links at the bottom of the file. The links section sits below all versioned entries. Maintain this structure:

    [Unreleased]: {REPO_URL}/compare/v{VERSION}...HEAD
    [{VERSION}]: {REPO_URL}/compare/v{PREV_TAG}...v{VERSION}
    [{PREV_TAG}]: ...
    

    Where PREV_TAG is LAST_TAG (without a leading v added twice — match the existing tag format in the repo). If there is no previous tag, the first versioned link uses the first commit SHA:

    [{VERSION}]: {REPO_URL}/commits/v{VERSION}
    

Write the updated content back to CHANGELOG.md.


Step 8b — Apply History Threshold (optional)

Only runs when MAX_FULL_ENTRIES was supplied.

Count the versioned entries in the file (every ## [X.Y.Z] heading that is not ## [Unreleased]). If the count exceeds MAX_FULL_ENTRIES, collapse the oldest entries down to links-only:

Before (full entry):

## [0.1.0] - 2026-01-15

### Added
- Initial release with bible_enrich_markdown tool

After (links-only):

## [0.1.0] - 2026-01-15

*See the [0.1.0 comparison](comparison-link) for details.*

Rules:

  • Collapse from the oldest entry upward until the count of full entries equals MAX_FULL_ENTRIES.
  • The newest MAX_FULL_ENTRIES entries always remain in full.
  • Never collapse [Unreleased].
  • The comparison link at the bottom is always preserved regardless of threshold.
  • If the file already has links-only entries and the count of full entries is within the threshold, do nothing — do not re-expand collapsed entries.

Step 9 — Report

Print:

CHANGELOG.md updated
  Version:       {VERSION}
  Date:          {DATE}
  Sections:      {comma-separated list of sections written, e.g. "Added, Fixed"}
  Commits:       {N} user-facing commits included ({M} skipped as internal)
  Links:         comparison links updated
  Collapsed:     {K} old entries reduced to links-only  (omit line if K = 0)

Return control to the calling skill (e.g. release) without creating a git commit — committing is the responsibility of the caller.


Behavioral Rules

  • Never commit or stage files — the caller is responsible for that.
  • Never invent entries not present in the git log.
  • Never remove existing versioned entries from the changelog.
  • If CHANGELOG.md already contains an entry for VERSION, stop:

    "CHANGELOG.md already has an entry for {VERSION}. Bump the version or edit the file manually."

  • Preserve any manually written content in the ## [Unreleased] section by including it in the new versioned entry before the auto-generated entries (manual entries first, then git-derived).
  • Never re-expand a previously collapsed (links-only) entry, even if MAX_FULL_ENTRIES is raised.
  • When MAX_FULL_ENTRIES is not supplied, never collapse any entries — the default is no limit.

When not to use it

  • When the user wants to commit or stage files directly
  • When inventing entries not present in the git log
  • When removing existing versioned entries from the changelog

Limitations

  • It never commits or stages files
  • It never invents entries not present in the git log
  • It never removes existing versioned entries from the changelog

How it compares

This skill automates the process of generating and updating a `CHANGELOG.md` based on conventional commits, including versioning and link management, which is more structured than manual changelog maintenance.

Compared to similar skills

changelog side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
changelog (this skill)02moReviewIntermediate
prepare-changelog67moReviewBeginner
workthrough108moReviewBeginner
generate-release-notes78moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

prepare-changelog

nextest-rs

Guidelines for preparing changelog entries for nextest releases following Keep a Changelog format

689

workthrough

bear2u

Automatically document all development work and code modifications in a structured workthrough format. Use this skill after completing any development task, bug fix, feature implementation, or code refactoring to create comprehensive documentation.

1085

generate-release-notes

teambit

Generate comprehensive release notes for Bit from git commits and pull requests. Use when creating release notes, building changelogs, documenting version releases, or preparing a new Bit release.

752

changelog-generator

ComposioHQ

Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.

346

release-note-generation

microsoft

Toolkit for generating PowerToys release notes from GitHub milestone PRs or commit ranges. Use when asked to create release notes, summarize milestone PRs, generate changelog, prepare release documentation, request Copilot reviews for PRs, update README for a new release, manage PR milestones, or collect PRs between commits/tags. Supports PR collection by milestone or commit range, milestone assignment, grouping by label, summarization with external contributor attribution, and README version bumping.

537

doc-check

coder

Checks if code changes require documentation updates

427

Search skills

Search the agent skills registry