| name | changelog |
| description | Maintain changelogs following Keep a Changelog format. Use when creating release notes, parsing conventional commits for changelog entries, auto-generating changelog sections from git history, or preparing CHANGELOG.md for releases. |
Commands for changelog maintenance:
- Parse conventional commits for changelog entries
- Auto-generate changelog sections from git history
- Version bump decisions using semantic versioning
- Create release notes and CHANGELOG.md updates
Changelog entries in Keep a Changelog format:
- Added (new features from `feat:` commits)
- Changed (changes from `perf:` commits, breaking changes)
- Deprecated (features marked for removal)
- Removed (removed features)
- Fixed (bug fixes from `fix:` commits)
- Security (vulnerability fixes)
Changelog Management Skill
When to Use This Skill
- Creating release notes
- Parsing conventional commits for changelog entries
- Auto-generating changelog sections from git history
- Managing semantic versioning changes
- Preparing CHANGELOG.md for releases
- Documenting breaking changes, features, and fixes
Overview
This skill guides changelog management using the Keep a Changelog format combined with Conventional Commits. This approach ensures consistency, enables automation, and provides clear communication about changes.
Project Reference: Pennyfarthing uses Keep a Changelog format in /CHANGELOG.md with semantic versioning.
Keep a Changelog Format Reference
The standard structure is:
# Changelog
All notable changes to [Project] are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
*No unreleased changes*
---
## [1.0.0] - 2024-01-15
### Added
- New user-facing features
### Changed
- Changes in existing functionality
### Deprecated
- Features marked for removal
### Removed
- Removed features
### Fixed
- Bug fixes
### Security
- Security vulnerability fixes
---
## [0.9.0] - 2024-01-10
...
Guidelines
- One version per section - Each release gets its own
## [version] - date heading
- Semantic versioning - Follow MAJOR.MINOR.PATCH (e.g., 1.5.3)
- ISO 8601 dates - Format as YYYY-MM-DD
- Categorized entries - Group changes by type (Added, Changed, Fixed, etc.)
- Unreleased section - Always maintain an
[Unreleased] section at the top for staging changes
- End-user focus - Write for developers using your project, not your own team
Section Hierarchy
- Added - New features
- Changed - Changes to existing functionality
- Deprecated - Features soon to be removed (provide migration path)
- Removed - Removed features (finalize deprecations)
- Fixed - Bug fixes
- Security - Vulnerability fixes with patches
Conventional Commits Parsing
Conventional Commits structure commits to enable automatic changelog generation:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types and Changelog Mapping
| Commit Type | Changelog Section | Example |
|---|
feat: | Added | feat: add user authentication |
fix: | Fixed | fix: handle null pointer in parser |
perf: | Changed | perf: optimize database queries |
docs: | (skip) | docs: update README |
style: | (skip) | style: format code |
refactor: | (skip) | refactor: simplify module |
test: | (skip) | test: add unit tests |
chore: | (skip) | chore: update dependencies |
ci: | (skip) | ci: update GitHub Actions |
Breaking Changes
Mark breaking changes with ! or BREAKING CHANGE: footer:
feat!: redesign authentication API
feat: change password hashing algorithm
BREAKING CHANGE: passwords now require bcrypt hashing
These go into the Changed or Removed section, not Added.
Auto-Generation from Git Commits
Step 1: Get Commits Since Last Tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
git log --format="%H %s" | head -50
else
git log "${LAST_TAG}..HEAD" --format="%H %s"
fi
Step 2: Parse Conventional Commits
git log "${LAST_TAG}..HEAD" --format="%s" | while read line; do
TYPE=$(echo "$line" | cut -d: -f1)
DESC=$(echo "$line" | cut -d: -f2- | sed 's/^ //')
echo "$TYPE: $DESC"
done
Step 3: Group by Category
git log "${LAST_TAG}..HEAD" --format="%s" | grep "^feat" | sed 's/^feat: /- /'
git log "${LAST_TAG}..HEAD" --format="%s" | grep "^fix" | sed 's/^fix: /- /'
git log "${LAST_TAG}..HEAD" --format="%B" | grep -A1 "BREAKING CHANGE:" | tail -n +2
Complete Auto-Generation Script
#!/bin/bash
set -euo pipefail
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
RANGE="${LAST_TAG:+${LAST_TAG}..HEAD}"
echo "## [Unreleased]"
echo ""
FEATURES=$(git log ${RANGE:---all} --format="%s" | grep "^feat:" || echo "")
if [ -n "$FEATURES" ]; then
echo "### Added"
echo "$FEATURES" | sed 's/^feat: /- /'
echo ""
fi
FIXES=$(git log ${RANGE:---all} --format="%s" | grep "^fix:" || echo "")
if [ -n "$FIXES" ]; then
echo "### Fixed"
echo "$FIXES" | sed 's/^fix: /- /'
echo ""
fi
BREAKING=$(git log ${RANGE:---all} --format="%B" | grep -A1 "BREAKING CHANGE:" | grep "^-" || echo "")
if [ -n "$BREAKING" ]; then
echo "### Changed"
echo "**Breaking Changes:**"
echo "$BREAKING"
echo ""
fi
Version Bump Patterns
Semantic Versioning
MAJOR.MINOR.PATCH
- MAJOR: Incompatible API changes (breaking changes)
- MINOR: Backward-compatible functionality additions
- PATCH: Backward-compatible bug fixes
Decision Tree
Breaking change detected?
├─ Yes → MAJOR.0.0 (or X+1.0.0 from X.0.0)
└─ No
└─ feat: commits present?
├─ Yes → X.Y+1.0 (minor version bump)
└─ No → X.Y.Z+1 (patch version bump)
Examples
1.5.1
1.6.0
2.0.0
Release Workflow Example
1. During Development
Maintain [Unreleased] section in CHANGELOG.md:
## [Unreleased]
### Added
- New dark mode theme
- User preference persistence
### Fixed
- Memory leak in event handler
- Incorrect timezone calculations
2. Prepare Release
LAST_VERSION="1.5.0"
COMMITS=$(git log v${LAST_VERSION}..HEAD --format="%s")
echo "$COMMITS" | grep -q "^feat:" && NEW_VERSION="1.6.0" || NEW_VERSION="1.5.1"
echo "Releasing version $NEW_VERSION"
3. Create Release Section
NEW_DATE=$(date +%Y-%m-%d)
sed -i '' "s/## \[Unreleased\]/## [Unreleased]\n\n*No unreleased changes*\n\n---\n\n## [$NEW_VERSION] - $NEW_DATE/" CHANGELOG.md
4. Commit and Tag
git add CHANGELOG.md VERSION
git commit -m "chore: bump to version $NEW_VERSION"
git tag -a "v$NEW_VERSION" -m "Release $NEW_VERSION"
git push origin main --tags
Integration with /pf-git release Command
The /pf-git release command in Pennyfarthing can use this skill for:
- Auto-detecting new commits - Run conventional commit analysis since last tag
- Generating changelog sections - Create properly formatted entries
- Version bumping - Semantic versioning based on commit types
- Tagging - Create annotated tags for releases
Reference in /pf-git release command:
See the [Changelog Skill](/changelog) for patterns on:
- Maintaining CHANGELOG.md
- Parsing conventional commits
- Auto-generating release notes
- Version bump decisions
Best Practices
- Commit message quality - Enforce conventional commits in CI/CD
- Review before release - Manual changelog review catches automation gaps
- One changelog file - Single CHANGELOG.md in project root
- Link to releases - Provide direct links to tags/release pages
- Backfill old changes - If starting Keep a Changelog mid-project, document recent versions
- Human-friendly descriptions - Conventional commits are machine-parseable; enhance for humans
- Changelog in PR reviews - Ensure PR descriptions clarify what should be in changelog
Tools and Automation
Conventional Commits Linting
npm install --save-dev @commitlint/config-conventional @commitlint/cli
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > .commitlintrc.js
echo "feat: add new feature" | commitlint
Automatic Changelog Generation
Tools that auto-generate from commits:
- conventional-changelog - Node.js package
- changie - Go-based with template support
- git-cliff - Rust-based with flexible templates
Example with conventional-changelog:
npm install --save-dev conventional-changelog-cli
npx conventional-changelog -p angular -i CHANGELOG.md -s
CI/CD Integration
- name: Generate Changelog
run: |
npx conventional-changelog -p angular -i CHANGELOG.md -s
git add CHANGELOG.md
git commit -m "docs: update CHANGELOG" || echo "No changes"
Reference Documentation