Keep a Changelog (Multi-Format Support)
Authored and maintained by Ivan De Marino.
This skill manages the project's CHANGELOG.md (or CHANGELOG) — bootstrapping it from scratch, creating new version entries, or updating unreleased/in-progress entries in-place. It supports multiple changelog formats, dynamically detects existing formats, and prompts the user to select or confirm the desired standard.
Supported Formats
1. Keep a Changelog v1.1.0
This format adheres to Keep a Changelog v1.1.0 and Semantic Versioning.
- Header Structure: Standard markdown headings detailing compliance with the format.
- Release Entry Heading:
## [<version>] - <YYYY-MM-DD> (e.g., ## [1.6.0] - 2026-03-27).
- Standard Categories:
### Added — For new features.
### Changed — For changes in existing functionality.
### Fixed — For bug fixes.
### Removed — For now-removed features.
- Conventions: Empty categories are omitted. Each bullet point is a concise, user-facing summary.
2. HashiCorp / Terraform Provider Format
This format adheres to HashiCorp's changelog standard (commonly used for Terraform providers and other plugins).
- Header Structure: Mentions compliance with HashiCorp's versioning and changelog best practices.
- Release Entry Heading:
- Unreleased / Upcoming:
## X.Y.Z (Unreleased)
- Released:
## A.B.C (Month Day, Year) (e.g., ## 1.0.0 (March 27, 2026)).
- Standard Categories:
BREAKING CHANGES: or BACKWARDS INCOMPATIBILITIES: — Brief documentation of incompatible changes and upgrade paths.
NOTES: — Deprecations, critical crash fixes, or unexpected upgrade behavior.
FEATURES: — Major improvements, such as new resources or data sources.
IMPROVEMENTS: or ENHANCEMENTS: — Smaller additions (e.g., attributes).
BUG FIXES: — Any fixed bugs.
- Conventions:
- Every entry must match the syntax:
* subsystem: Descriptive message [GH-####]
- Subsystem is typically the resource name (e.g.,
resource/instance) or provider if global.
- PR Reference
[GH-####] must correspond to the GitHub pull request number.
- Entries under each category are ordered lexicographically based on the subsystem (e.g.,
resource/load_balancer comes before resource/subnet). Cross-cutting changes (provider) are listed first.
3. Other / Custom Format
If the repository follows a custom standard, the agent prompts the user to specify or describe it, then proceeds to follow that custom layout and syntax.
Workflow: Detect, Ask, and Decide Mode
Before writing or editing anything, execute this workflow to establish the format and update mode:
Step 1: Detect or Prompt for Changelog Format
- Check for Existing Files: Look for
CHANGELOG.md or CHANGELOG in the root of the repository.
- Auto-Detect Format:
- If the file exists, inspect the top-level headings and entries:
- Contains
## [<version>] - <YYYY-MM-DD> or mentions keepachangelog.com → Keep a Changelog format.
- Contains
(Unreleased) or categories like BREAKING CHANGES:, FEATURES:, IMPROVEMENTS: or bullet points with [GH-####] → HashiCorp format.
- Ask/Confirm with the User:
- Always verify the detected format, or ask the user to choose when bootstrapping or if detection is ambiguous.
- Action: Use the agent's interactive questioning tool (e.g.,
question in Crush, or the appropriate interactive tool in your platform) to present a clear option:
"Keep a Changelog" format
"HashiCorp" format (Terraform providers, etc.)
"Other / Custom" format (please specify)
- Under the hood, document which format the changelog adheres to (both in the bootstrap header and in your internal execution context), and comply with it from that point forward.
Step 2: Determine Update Mode
Check if any git tags exist:
git tag --sort=-v:refname | head -1
If no tags exist, proceed to Mode C: Bootstrap (even if a file exists, treat it as a fresh project).
Extract the latest version from the changelog:
- Parse the first version heading using the pattern of the detected format (e.g.,
## [1.6.0] or ## 1.6.0 (Unreleased)).
Check if a git tag exists for that version:
- Check if the tag matches (e.g.,
v1.6.0 or 1.6.0).
git tag --list "v<version>"
git tag --list "<version>"
Decide the mode:
- No file, no tags, or empty file → Mode C: Bootstrap.
- Tag exists for latest entry (it represents a finalized release) → Mode A: Create a New Entry at the top.
- Tag does NOT exist for latest entry (it represents a work-in-progress release or an "Unreleased" section) → Mode B: Update Existing Entry in-place.
Workflow Modes
Mode A: Create a New Entry (tag exists for latest entry)
- Determine Version: Ask the user what the next version should be. Do not guess or infer the version number — always confirm with the user.
- Gather Changes: Follow Determining What Changed using the latest tag as the baseline.
- Insert Heading:
- For Keep a Changelog: Insert
## [<version>] - <YYYY-MM-DD> at the top (under the file header).
- For HashiCorp: If this is an upcoming unreleased version, insert
## <version> (Unreleased). If finalizing a release, insert ## <version> (Month Day, Year).
Mode B: Update an Existing Unreleased Entry (no tag for latest entry)
- Find Baseline Tag: Find the most recent tag that actually exists (which served as the baseline for this in-progress version):
git tag --sort=-v:refname | head -1
- Gather Changes: Retrieve all commits since that baseline tag.
- Rewrite Entry:
- Replace the entire top entry from the unreleased header down to the next version header.
- Ensure you perform a full rewrite to avoid duplicates and accurately reflect any changes or squashed commits.
- Preserve the unreleased designation or version number unless a bump is requested.
Mode C: Bootstrap a New CHANGELOG
- Create the file: Write
CHANGELOG.md or CHANGELOG.
- Include Header:
- For Keep a Changelog:
# 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).
- For HashiCorp:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [HashiCorp's Changelog Best Practices](https://developer.hashicorp.com/terraform/plugin/best-practices/versioning).
- Generate First Entry: Use the repository's root commit (or latest tag if tags exist but file is missing) as the baseline. Write the first entry at version
0.1.0 (or 1.0.0 or user's requested version) adhering to the chosen format structure.
Determining What Changed
- Find the last tag:
git tag --sort=-v:refname | head -1
- List commits since tag with message/body:
git log <last-tag>..HEAD --no-merges --format="%h %s%n%b---"
- Extract PR numbers:
- Parse merge commits or commit subjects for pull request IDs (e.g.,
(#123) or Merge pull request #123). These are used to generate references like [GH-123] in HashiCorp format.
Category and Subsystem Mapping
Map the conventional commit prefixes and file changes to the appropriate categories for each format:
| Commit Prefix |
Keep a Changelog Section |
HashiCorp Section |
feat (new resource/feature) |
Added |
FEATURES: |
feat (enhancements) |
Added / Changed |
IMPROVEMENTS: |
fix |
Fixed |
BUG FIXES: |
refactor / chore |
Changed |
IMPROVEMENTS: |
breaking / ! |
Added/Changed (highlighted) |
BREAKING CHANGES: |
Subsystem Determination (HashiCorp Format Only)
For HashiCorp format, parse the modified files in the commit diff to find the affected subsystem (e.g., internal/provider/resource_aws_instance.go -> resource/aws_instance or provider).
- Sort entries lexicographically by subsystem within each category.
- List global
provider entries first.
Examples
Example: HashiCorp Format Entry
Given the following commits since v1.1.0:
feat: add resource_network_interface (#42)
fix(resource/subnet): resolve IP allocation issue (#45)
refactor(provider): configure custom user agent (#46)
The resulting entry for version 1.2.0 (Unreleased) or 1.2.0 (July 2, 2026) will look like:
## 1.2.0 (Unreleased)
FEATURES:
* **New Resource:** `network_interface` [GH-42]
IMPROVEMENTS:
* provider: Configure custom user agent [GH-46]
BUG FIXES:
* resource/subnet: Resolve IP allocation issue [GH-45]
Checklist Before Finishing
1---2name: keep-a-changelog3description: Manages the project's CHANGELOG.md following the detected or requested format (e.g., Keep a Changelog or HashiCorp/Terraform format). Bootstraps a new changelog, creates entries for new releases, or updates in-progress entries in-place based on git history.4license: Apache-2.05---67# Keep a Changelog (Multi-Format Support)89> Authored and maintained by **Ivan De Marino**.1011This skill manages the project's `CHANGELOG.md` (or `CHANGELOG`) — bootstrapping it from scratch, creating new version entries, or updating unreleased/in-progress entries in-place. It supports multiple changelog formats, dynamically detects existing formats, and prompts the user to select or confirm the desired standard.1213## Supported Formats1415### 1. Keep a Changelog v1.1.016This format adheres to [Keep a Changelog v1.1.0](https://keepachangelog.com/en/1.1.0/) and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).1718- **Header Structure**: Standard markdown headings detailing compliance with the format.19- **Release Entry Heading**: `## [<version>] - <YYYY-MM-DD>` (e.g., `## [1.6.0] - 2026-03-27`).20- **Standard Categories**:21 - `### Added` — For new features.22 - `### Changed` — For changes in existing functionality.23 - `### Fixed` — For bug fixes.24 - `### Removed` — For now-removed features.25- **Conventions**: Empty categories are omitted. Each bullet point is a concise, user-facing summary.2627### 2. HashiCorp / Terraform Provider Format28This format adheres to HashiCorp's changelog standard (commonly used for Terraform providers and other plugins).2930- **Header Structure**: Mentions compliance with HashiCorp's versioning and changelog best practices.31- **Release Entry Heading**:32 - Unreleased / Upcoming: `## X.Y.Z (Unreleased)`33 - Released: `## A.B.C (Month Day, Year)` (e.g., `## 1.0.0 (March 27, 2026)`).34- **Standard Categories**:35 - `BREAKING CHANGES:` or `BACKWARDS INCOMPATIBILITIES:` — Brief documentation of incompatible changes and upgrade paths.36 - `NOTES:` — Deprecations, critical crash fixes, or unexpected upgrade behavior.37 - `FEATURES:` — Major improvements, such as new resources or data sources.38 - `IMPROVEMENTS:` or `ENHANCEMENTS:` — Smaller additions (e.g., attributes).39 - `BUG FIXES:` — Any fixed bugs.40- **Conventions**:41 - Every entry must match the syntax: `* subsystem: Descriptive message [GH-####]`42 - *Subsystem* is typically the resource name (e.g., `resource/instance`) or `provider` if global.43 - *PR Reference* `[GH-####]` must correspond to the GitHub pull request number.44 - Entries under each category are ordered **lexicographically** based on the subsystem (e.g., `resource/load_balancer` comes before `resource/subnet`). Cross-cutting changes (`provider`) are listed first.4546### 3. Other / Custom Format47If the repository follows a custom standard, the agent prompts the user to specify or describe it, then proceeds to follow that custom layout and syntax.4849---5051## Workflow: Detect, Ask, and Decide Mode5253Before writing or editing anything, execute this workflow to establish the format and update mode:5455### Step 1: Detect or Prompt for Changelog Format56571. **Check for Existing Files**: Look for `CHANGELOG.md` or `CHANGELOG` in the root of the repository.582. **Auto-Detect Format**:59 - If the file exists, inspect the top-level headings and entries:60 - Contains `## [<version>] - <YYYY-MM-DD>` or mentions `keepachangelog.com` → **Keep a Changelog** format.61 - Contains `(Unreleased)` or categories like `BREAKING CHANGES:`, `FEATURES:`, `IMPROVEMENTS:` or bullet points with `[GH-####]` → **HashiCorp** format.623. **Ask/Confirm with the User**:63 - Always verify the detected format, or ask the user to choose when bootstrapping or if detection is ambiguous.64 - **Action**: Use the agent's interactive questioning tool (e.g., `question` in Crush, or the appropriate interactive tool in your platform) to present a clear option:65 - `"Keep a Changelog" format`66 - `"HashiCorp" format (Terraform providers, etc.)`67 - `"Other / Custom" format (please specify)`68 - Under the hood, document which format the changelog adheres to (both in the bootstrap header and in your internal execution context), and comply with it from that point forward.6970### Step 2: Determine Update Mode71721. **Check if any git tags exist**:73 ```bash74 git tag --sort=-v:refname | head -175 ```76 If no tags exist, proceed to **Mode C: Bootstrap** (even if a file exists, treat it as a fresh project).77782. **Extract the latest version from the changelog**:79 - Parse the first version heading using the pattern of the detected format (e.g., `## [1.6.0]` or `## 1.6.0 (Unreleased)`).80813. **Check if a git tag exists for that version**:82 - Check if the tag matches (e.g., `v1.6.0` or `1.6.0`).83 ```bash84 git tag --list "v<version>"85 git tag --list "<version>"86 ```87884. **Decide the mode**:89 - **No file, no tags, or empty file** → **Mode C: Bootstrap**.90 - **Tag exists for latest entry** (it represents a finalized release) → **Mode A: Create a New Entry** at the top.91 - **Tag does NOT exist for latest entry** (it represents a work-in-progress release or an "Unreleased" section) → **Mode B: Update Existing Entry** in-place.9293---9495## Workflow Modes9697### Mode A: Create a New Entry (tag exists for latest entry)981. **Determine Version**: Ask the user what the next version should be. Do not guess or infer the version number — always confirm with the user.992. **Gather Changes**: Follow [Determining What Changed](#determining-what-changed) using the latest tag as the baseline.1003. **Insert Heading**:101 - For *Keep a Changelog*: Insert `## [<version>] - <YYYY-MM-DD>` at the top (under the file header).102 - For *HashiCorp*: If this is an upcoming unreleased version, insert `## <version> (Unreleased)`. If finalizing a release, insert `## <version> (Month Day, Year)`.103104### Mode B: Update an Existing Unreleased Entry (no tag for latest entry)1051. **Find Baseline Tag**: Find the most recent tag that actually exists (which served as the baseline for this in-progress version):106 ```bash107 git tag --sort=-v:refname | head -1108 ```1092. **Gather Changes**: Retrieve all commits since that baseline tag.1103. **Rewrite Entry**:111 - Replace the entire top entry from the unreleased header down to the next version header.112 - Ensure you perform a full rewrite to avoid duplicates and accurately reflect any changes or squashed commits.113 - Preserve the unreleased designation or version number unless a bump is requested.114115### Mode C: Bootstrap a New CHANGELOG1161. **Create the file**: Write `CHANGELOG.md` or `CHANGELOG`.1172. **Include Header**:118 - For *Keep a Changelog*:119 ```markdown120 # Changelog121122 All notable changes to this project will be documented in this file.123124 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),125 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).126 ```127 - For *HashiCorp*:128 ```markdown129 # Changelog130131 All notable changes to this project will be documented in this file.132133 The format is based on [HashiCorp's Changelog Best Practices](https://developer.hashicorp.com/terraform/plugin/best-practices/versioning).134 ```1353. **Generate First Entry**: Use the repository's root commit (or latest tag if tags exist but file is missing) as the baseline. Write the first entry at version `0.1.0` (or `1.0.0` or user's requested version) adhering to the chosen format structure.136137---138139## Determining What Changed1401411. **Find the last tag**:142 ```bash143 git tag --sort=-v:refname | head -1144 ```1452. **List commits since tag with message/body**:146 ```bash147 git log <last-tag>..HEAD --no-merges --format="%h %s%n%b---"148 ```1493. **Extract PR numbers**:150 - Parse merge commits or commit subjects for pull request IDs (e.g., `(#123)` or `Merge pull request #123`). These are used to generate references like `[GH-123]` in HashiCorp format.151152### Category and Subsystem Mapping153154Map the conventional commit prefixes and file changes to the appropriate categories for each format:155156| Commit Prefix | Keep a Changelog Section | HashiCorp Section |157|-------------------------------|-----------------------------|-------------------|158| `feat` (new resource/feature) | Added | FEATURES: |159| `feat` (enhancements) | Added / Changed | IMPROVEMENTS: |160| `fix` | Fixed | BUG FIXES: |161| `refactor` / `chore` | Changed | IMPROVEMENTS: |162| `breaking` / `!` | Added/Changed (highlighted) | BREAKING CHANGES: |163164#### Subsystem Determination (HashiCorp Format Only)165For HashiCorp format, parse the modified files in the commit diff to find the affected subsystem (e.g., `internal/provider/resource_aws_instance.go` -> `resource/aws_instance` or `provider`).166- Sort entries lexicographically by subsystem within each category.167- List global `provider` entries first.168169---170171## Examples172173### Example: HashiCorp Format Entry174Given the following commits since `v1.1.0`:175- `feat: add resource_network_interface (#42)`176- `fix(resource/subnet): resolve IP allocation issue (#45)`177- `refactor(provider): configure custom user agent (#46)`178179The resulting entry for version `1.2.0 (Unreleased)` or `1.2.0 (July 2, 2026)` will look like:180181```markdown182## 1.2.0 (Unreleased)183184FEATURES:185186* **New Resource:** `network_interface` [GH-42]187188IMPROVEMENTS:189190* provider: Configure custom user agent [GH-46]191192BUG FIXES:193194* resource/subnet: Resolve IP allocation issue [GH-45]195```196197---198199## Checklist Before Finishing200201- [ ] Used an interactive questioning tool (`question`) to confirm or select the format if bootstrapping or if detection was ambiguous.202- [ ] Complied with the exact conventions of the selected format (Keep a Changelog or HashiCorp).203- [ ] Grouped and classified commits accurately into standard category headers.204- [ ] If HashiCorp format: applied subsystem prefixes, sorted entries lexicographically by subsystem within categories, and appended `[GH-####]` PR references.205- [ ] Verified that any generated file clearly documents which format it follows.206- [ ] Preserved all existing untouched history below the edited section.207- [ ] Set correct dates and version tags in accordance with the format rules.