$npx -y skills add girijashankarj/cursor-handbook --skill changelog-generatorGenerate a CHANGELOG.md from Conventional Commit history with grouped sections and version headers. Use when the user asks to create or update a changelog.
| 1 | # Skill: Changelog Generator |
| 2 | |
| 3 | Parse git commit history and produce a structured CHANGELOG following Keep a Changelog format and Conventional Commits. |
| 4 | |
| 5 | ## Trigger |
| 6 | When the user asks to generate, update, or create a changelog — or before a release. |
| 7 | |
| 8 | ## Prerequisites |
| 9 | - [ ] Git repository with Conventional Commit messages |
| 10 | - [ ] Previous version tag known (or first release) |
| 11 | |
| 12 | ## Quick Usage |
| 13 | |
| 14 | For a quick changelog from recent commits, run the bundled script: |
| 15 | |
| 16 | ```bash |
| 17 | scripts/generate-changelog.sh [output-file] [since-tag] |
| 18 | ``` |
| 19 | |
| 20 | Examples: |
| 21 | ```bash |
| 22 | scripts/generate-changelog.sh # Last 20 commits → CHANGELOG.md |
| 23 | scripts/generate-changelog.sh CHANGELOG.md v1.0 # Commits since v1.0 |
| 24 | ``` |
| 25 | |
| 26 | For a fully structured Keep a Changelog output, follow the detailed steps below. |
| 27 | |
| 28 | ## Steps |
| 29 | |
| 30 | ### Step 1: Determine Version Range |
| 31 | - [ ] Get the latest tag: `git describe --tags --abbrev=0 2>/dev/null || echo "none"` |
| 32 | - [ ] Get all tags sorted: `git tag --sort=-v:refname | head -10` |
| 33 | - [ ] Determine range: `{last-tag}..HEAD` (or all commits if no tag) |
| 34 | - [ ] Ask user for the new version number or suggest based on changes: |
| 35 | - Has `feat` → minor bump |
| 36 | - Has `fix` only → patch bump |
| 37 | - Has `BREAKING CHANGE` or `!` → major bump |
| 38 | |
| 39 | ### Step 2: Collect Commits |
| 40 | - [ ] Run: `git log {range} --pretty=format:"%H|%s|%an|%ad" --date=short` |
| 41 | - [ ] Parse each commit into: hash, type, scope, description, author, date |
| 42 | - [ ] Identify breaking changes (footer or `!` in type) |
| 43 | |
| 44 | ### Step 3: Categorize Changes |
| 45 | |
| 46 | | Section | Commit Types | Emoji (optional) | |
| 47 | |---------|-------------|-------------------| |
| 48 | | **Added** | `feat` | | |
| 49 | | **Fixed** | `fix` | | |
| 50 | | **Changed** | `refactor`, `perf` | | |
| 51 | | **Deprecated** | Commits mentioning deprecation | | |
| 52 | | **Removed** | Commits removing features | | |
| 53 | | **Security** | `fix` with security scope | | |
| 54 | | **Documentation** | `docs` | | |
| 55 | | **Internal** | `chore`, `ci`, `test`, `style`, `build` | | |
| 56 | |
| 57 | ### Step 4: Generate Changelog Entry |
| 58 | |
| 59 | ```markdown |
| 60 | ## [X.Y.Z] - YYYY-MM-DD |
| 61 | |
| 62 | ### Added |
| 63 | - **scope:** description ([hash](commit-url)) — @author |
| 64 | |
| 65 | ### Fixed |
| 66 | - **scope:** description ([hash](commit-url)) — @author |
| 67 | |
| 68 | ### Changed |
| 69 | - **scope:** description ([hash](commit-url)) — @author |
| 70 | |
| 71 | ### Breaking Changes |
| 72 | - **scope:** description of what broke and migration path |
| 73 | ``` |
| 74 | |
| 75 | ### Step 5: Handle Edge Cases |
| 76 | - [ ] Commits with no type prefix → categorize as **Internal** |
| 77 | - [ ] Merge commits → skip (use `--no-merges` flag) |
| 78 | - [ ] Multiple scopes → list under primary scope |
| 79 | - [ ] Very long descriptions → truncate to first sentence |
| 80 | |
| 81 | ### Step 6: Assemble Full Changelog |
| 82 | - [ ] If CHANGELOG.md exists, prepend new entry after the header |
| 83 | - [ ] If new file, add header: |
| 84 | ```markdown |
| 85 | # Changelog |
| 86 | |
| 87 | All notable changes to this project will be documented in this file. |
| 88 | |
| 89 | The format is based on [Keep a Changelog](https://keepachangelog.com/), |
| 90 | and this project adheres to [Semantic Versioning](https://semver.org/). |
| 91 | ``` |
| 92 | - [ ] Include comparison link: `[X.Y.Z]: https://github.com/org/repo/compare/vPREV...vX.Y.Z` |
| 93 | |
| 94 | ### Step 7: Validate & Output |
| 95 | - [ ] Verify no PII, secrets, or internal URLs in entries |
| 96 | - [ ] Verify markdown renders correctly |
| 97 | - [ ] Present as copyable output or write to `CHANGELOG.md` |
| 98 | |
| 99 | ## Rules |
| 100 | - **ALWAYS** follow Keep a Changelog format |
| 101 | - **ALWAYS** group by change type, not by date or author |
| 102 | - **NEVER** include merge commits or version bump commits |
| 103 | - **NEVER** include secrets, internal URLs, or PII |
| 104 | - Skip `chore`/`ci`/`style` commits by default (include if user requests) |
| 105 | - Most recent version goes at the top |
| 106 | |
| 107 | ## Completion |
| 108 | CHANGELOG.md entry ready to paste or written to file. Includes version header, grouped changes, and comparison links. |
| 109 | |
| 110 | ## If a Step Fails |
| 111 | - **No tags exist:** Treat all commits as the first release (v0.1.0 or v1.0.0) |
| 112 | - **Non-conventional commits:** Group under "Other" with the raw message |
| 113 | - **Too many commits:** Summarize by scope, list top 20, note "and N more" |
| 114 | - **No new commits since last tag:** Report "No changes since vX.Y.Z" |