# Changelog Writer

> >

- **Type:** Skill
- **Install:** `agentstack add skill-alissonlinneker-claude-skills-changelog-writer`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [alissonlinneker](https://agentstack.voostack.com/s/alissonlinneker)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [alissonlinneker](https://github.com/alissonlinneker)
- **Source:** https://github.com/alissonlinneker/claude-skills/tree/main/plugins/changelog-writer/skills/changelog-writer

## Install

```sh
agentstack add skill-alissonlinneker-claude-skills-changelog-writer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Changelog Writer

The definitive changelog and release notes skill. Transforms raw git history, commit messages,
PR descriptions, and code diffs into polished, production-ready changelogs and release notes.
Produces up to five output formats simultaneously: developer-facing CHANGELOG.md, human-facing
GitHub release notes, internal Slack summary, customer-facing email/newsletter, and package
registry release notes. Every output is ready to paste — zero editing required.

---

## Workflow

Follow these phases in order. Do not skip phases. Do not produce output until Phase 5.

---

### Phase 1 — Acquire Changes

Determine input type and acquire all material needed to generate the changelog.

| Input Type | Action |
|---|---|
| No input provided | Run `git tag --sort=-v:refname` to find the latest tag, then `git log ..HEAD --oneline --no-merges` to get unreleased commits. If no tags exist, use `git log --oneline --no-merges -50` and ask the user for the version range. |
| User says "generate changelog" / "what changed" with no specifics | Auto-detect: find latest two tags with `git tag --sort=-v:refname`, run `git log .. --oneline --no-merges`. If HEAD is ahead of the latest tag, use `..HEAD` instead. |
| User specifies version range (e.g., "v1.2.0 to v1.3.0") | Run `git log v1.2.0..v1.3.0 --oneline --no-merges`. |
| Pasted git log | Parse directly. Detect conventional commit format automatically. |
| PR titles / descriptions | Parse each PR as a change entry. Use PR labels for categorization if available. |
| Diff or file list | Analyze the diff to understand what changed. Summarize by functional area. |
| Free-form description | Parse natural language into structured change entries. |
| Existing messy changelog | Parse, validate, clean up, and reformat to Keep a Changelog standard. |
| Single commit message | Expand into a full, context-rich release note. |
| GitHub PR URL or number | Use `gh pr view  --json title,body,labels,mergedAt,files` to fetch PR details. Use `gh pr diff ` for the code diff. |
| Monorepo with path prefix | Filter commits by path: `git log  --oneline --no-merges -- `. See Phase 1b. |

**Git integration commands to run automatically** (when in a git repository):

```bash
# Detect latest tags
git tag --sort=-v:refname | head -5

# Get repo remote URL (for comparison links)
git remote get-url origin 2>/dev/null

# Get current branch
git rev-parse --abbrev-ref HEAD

# Count commits since last tag
git rev-list --count $(git describe --tags --abbrev=0 2>/dev/null)..HEAD 2>/dev/null
```

If any git command fails (not a git repo, no tags), fall back gracefully to whatever
input the user provides and note the limitation.

#### Phase 1b — Monorepo Detection and Handling

When the repository appears to be a monorepo (multiple package.json files, workspace
configuration, `packages/` or `apps/` directory structure, Lerna/Nx/Turborepo config),
or when the user specifies a package/workspace:

1. **Detect workspace structure:**
   ```bash
   # Check for monorepo indicators
   ls packages/ apps/ modules/ libs/ 2>/dev/null
   cat package.json | grep -c "workspaces" 2>/dev/null
   ls lerna.json nx.json turbo.json pnpm-workspace.yaml 2>/dev/null
   ```

2. **Filter commits by path prefix:**
   ```bash
   git log  --oneline --no-merges -- packages//
   ```

3. **Handle independent versioning:**
   - Each package may have its own version. Check `packages//package.json` or equivalent.
   - If the user says "release @scope/package-name", filter to that package only.
   - If the user says "release all packages", generate a changelog per package that has changes.

4. **Cross-package changes:**
   - Commits touching multiple packages get listed in each affected package's changelog.
   - Root-level changes (CI, tooling) go in a "Tooling" or "Infrastructure" section of a root changelog.

5. **Output format for monorepo:**
   Present each package with changes as a separate section:
   ```markdown
   # Release Notes — 2026-03-14

   ## @myorg/core (1.5.0 → 1.6.0)
   ### Added
   - ...

   ## @myorg/ui (2.1.0 → 2.1.1)
   ### Fixed
   - ...

   ## @myorg/api (no changes)
   ```

---

### Phase 2 — Detect Project Conventions

Before categorizing, detect the project's conventions to calibrate parsing:

**Conventional commits detection:**
```bash
# Sample recent commits to detect format
git log --oneline -20
```

| Pattern Detected | Behavior |
|---|---|
| Most commits use `type:` or `type(scope):` | Full conventional commit parsing. Use type for category, scope for grouping. |
| Mixed — some conventional, some not | Parse conventional commits by type. Classify others by keyword analysis. |
| No conventional commits | Classify entirely by keyword analysis and diff inspection. |

**Existing CHANGELOG.md detection:**
```bash
# Check for existing changelog
ls CHANGELOG.md CHANGELOG changelog.md HISTORY.md RELEASES.md NEWS.md 2>/dev/null
```

If an existing changelog file is found:
1. Read it to understand the project's changelog style and conventions.
2. Match the existing format exactly (heading levels, bullet style, date format, link format).
3. Validate it against Keep a Changelog format and note inconsistencies (see Phase 2b).
4. Determine the correct insertion point for the new entry.

**Version format detection:**
```bash
# Check existing tags for version format
git tag --sort=-v:refname | head -10
```

Detect and match the project's version format:
- `v1.2.3` vs `1.2.3` (with or without `v` prefix)
- Calendar versioning: `2026.03`, `2026.03.1`
- Build numbers: `build-1042`
- Codenames: detect if tags or releases use codenames alongside semver

#### Phase 2b — Changelog Validation

When an existing CHANGELOG.md is found, validate it before inserting new content:

**Validation checks:**

| Check | Pass | Warn | Fail |
|---|---|---|---|
| Keep a Changelog format compliance | Follows standard headings | Minor deviations | Completely non-standard |
| Version ordering | Newest first, monotonically decreasing | One entry out of order | Multiple entries out of order |
| Date format | ISO 8601 (YYYY-MM-DD) consistently | Mixed formats | No dates at all |
| Comparison links | All versions have diff links at bottom | Some missing | No links |
| Duplicate versions | No duplicates | — | Same version appears twice |
| Unreleased section | Present and correctly placed | Missing but otherwise OK | Unreleased below released entries |
| Empty sections | No empty categories | One or two empty headings | Many empty headings |

Report validation results before proceeding:
```
Changelog validation:
  [PASS] Format follows Keep a Changelog standard
  [WARN] Missing comparison links for v1.1.0 and v1.0.0
  [PASS] Versions correctly ordered (newest first)
  [PASS] Dates in ISO 8601 format
```

If issues are found, offer to fix them: "I found 2 issues in the existing CHANGELOG.md. Want me to fix them while adding the new entry?"

---

### Phase 3 — Parse, Categorize, and Group

Read all changes and categorize them. Apply intelligent grouping.

#### Category Rules

Categories follow [Keep a Changelog](https://keepachangelog.com) standard:

| Category | Triggers | Priority |
|---|---|---|
| **Breaking Changes** | `!` in conventional commit type, `BREAKING CHANGE:` in commit body or footer, "BREAKING", removes or renames a public API, changes return format, removes endpoints, changes required parameters, incompatible schema migration | 1 (always first) |
| **Security** | `security`, `CVE-`, `vulnerability`, `auth bypass`, `XSS`, `injection`, `CSRF`, `SSRF`, `exposure`, `advisory`, `patch security`, commits touching auth/security files | 2 |
| **Added** | `feat:`, `feature`, `add`, `implement`, `introduce`, `support for`, `new`, `enable` | 3 |
| **Changed** | `refactor:`, `change`, `update`, `modify`, `improve`, `enhance`, `rework`, `revamp`, `migrate` | 4 |
| **Deprecated** | `deprecate`, `will be removed`, `legacy`, `sunset`, `end of life`, `EOL` | 5 |
| **Removed** | `remove`, `drop support`, `delete`, `eliminate`, `strip`, `prune` | 6 |
| **Fixed** | `fix:`, `fix`, `resolve`, `patch`, `correct`, `repair`, `handle`, `prevent`, `bug` | 7 |
| **Performance** | `perf:`, `faster`, `optimize`, `reduce latency`, `cache`, `improve performance`, `speed up`, `benchmark` | 8 |
| **Dependencies** | `deps:`, `chore(deps):`, `bump`, `upgrade`, `update [package-name]`, `renovate`, `dependabot` | 9 |
| **Documentation** | `docs:`, `readme`, `update docs`, `add documentation`, `JSDoc`, `docstring`, `API docs` | 10 |
| **Internal** | `chore:`, `ci:`, `build:`, `test:`, `style:`, `refactor:` (when purely internal) — include only when audience is contributors | 11 |

#### Grouping Rules

- **Merge related commits into one bullet.** Ten commits for one feature = 1 bullet, not 10.
  Use the first `feat:` commit as the anchor and absorb subsequent `fix:`, `refactor:`, `test:`
  commits that share the same scope or touch the same files.
- **Group dependency updates.** "Updated React (17 → 18.3), TypeScript (4.9 → 5.4), and 12 other dependencies" not 14 separate bullets.
- **Drop noise.** Skip: `wip`, `tmp`, `minor`, `fix typo`, `fix lint`, `update .gitignore`,
  `merge branch`, `Merge pull request`, commits that only touch test infrastructure or CI
  config — unless the audience is contributors.
- **Preserve PR/issue references.** Attach `(#123)` or `(fixes #456)` to the relevant bullet.
- **Detect scope from conventional commits.** `feat(auth): add OAuth` → the bullet goes under
  "Added" with context that it is in the auth module.

#### Diff-Based Change Detection

When commit messages are poor quality (all say "fix", "update", "wip", or similar):

1. **Analyze the actual diff:**
   ```bash
   git diff  --stat
   git diff  --  (for key files)
   ```

2. **Infer changes from code:**
   - New files → likely new features. Read the file to understand what it does.
   - Deleted files → likely removed features. Check the file name/path for context.
   - Modified files → examine the diff to understand what changed functionally.

3. **Disclose the limitation:**
   Include a note: "Commit messages were minimal — these notes were inferred from code analysis
   and may be incomplete. Review the diff for full accuracy."

---

### Phase 4 — Version Bump Recommendation

If the user has not specified a version number, calculate and recommend one.

#### Semver Rules

| Changes Detected | Bump | Rationale |
|---|---|---|
| Any breaking change | **MAJOR** | `1.x.x → 2.0.0` |
| New features, no breaking changes | **MINOR** | `1.2.x → 1.3.0` |
| Only bug fixes, patches, deps, docs | **PATCH** | `1.2.3 → 1.2.4` |

#### Pre-1.0 Special Rules

- Breaking changes in `0.x.y` bump MINOR (not MAJOR): `0.3.0 → 0.4.0`
- New features in `0.x.y` bump MINOR: `0.3.0 → 0.4.0`
- Bug fixes in `0.x.y` bump PATCH: `0.3.1 → 0.3.2`
- Note: "Pre-1.0 versioning — breaking changes are expected and do not require a major bump."

#### Calendar Versioning

If the project uses calver (detected from tags like `2025.03`, `2026.01.2`):
- Use `YYYY.MM` or `YYYY.MM.PATCH` based on existing convention.
- Increment PATCH within the same month. New month = reset PATCH.

#### Recommendation Format

Present clearly and ask for confirmation:

```
Version recommendation: MINOR release → v1.3.0
  Rationale: 3 new features, 5 bug fixes, no breaking changes.
  Previous version: v1.2.0 (released 2026-02-01, 41 days ago, 47 commits)

Use v1.3.0? Or specify a different version.
```

#### Release Cadence Awareness

When git history is available, calculate and report:
- Days since last release
- Number of commits since last release
- Average release cadence (from last 5 releases)

If the release is unusually large or overdue, note it:
```
Note: This release includes 127 commits over 89 days. Your average release cadence is
every 14 days with ~20 commits. Consider releasing more frequently to reduce risk per release.
```

---

### Phase 5 — Release Readiness Check

Before generating the final changelog, perform a release readiness assessment.
Run these checks automatically when in a git repository:

```bash
# Check for uncommitted changes
git status --porcelain

# Check for TODO/FIXME/HACK in recently changed files
git diff  --name-only | head -20
# Then search those files for TODO/FIXME/HACK

# Check for unreleased migrations
ls **/migrations/ db/migrate/ 2>/dev/null | head -5

# Check if tests pass (only suggest, don't run without permission)
ls package.json Makefile Cargo.toml pyproject.toml go.mod 2>/dev/null
```

**Readiness report (include before the changelog outputs):**

```
Release readiness check:
  [PASS] No uncommitted changes
  [WARN] 3 TODO comments found in changed files (auth.ts:45, cart.js:112, api.py:89)
  [PASS] No unreleased database migrations detected
  [INFO] Test suite detected (Jest) — run `npm test` before releasing
  [WARN] Branch is 2 commits behind origin/main — pull before releasing
```

If any checks fail critically (uncommitted changes that should be included, branch divergence),
warn prominently before proceeding.

---

### Phase 6 — Generate Contributor Acknowledgments

For open-source projects or when the user requests it, generate a contributors section.

```bash
# Get unique authors in the range
git log  --format='%aN ' --no-merges | sort -u

# Get co-authors from commit bodies
git log  --format='%b' | grep -i 'co-authored-by' | sort -u

# Get GitHub usernames (if remote is GitHub)
git log  --format='%aN' --no-merges | sort -u
```

**Auto-detect if open source:**
- Check for LICENSE file
- Check for CONTRIBUTING.md
- Check if the remote URL is a public GitHub repo

**For open-source projects, always include the contributors section.**
**For private/internal projects, include only if the user requests it.**

Format:
```markdown
### Contributors

Thanks to the following people who contributed to this release:

- @username1 — OAuth implementation (#218, #219)
- @username2 — Bug fixes (#227, #231)
- @username3 — Documentation updates (#220)
- @username4 (first-time contributor!) — Safari date picker fix (#219)
```

Rules:
- Map git author names to GitHub usernames when possible (check `git log --format='%aN'`
  against `gh api` if available).
- Highlight first-time contributors (not found in `git log` before the range start).
- Group contributions by what they did, not just list names.
- Include co-authors from `Co-authored-by:` trailers.

---

### Phase 7 — Produce Outputs

Always produce **Output A** (CHANGELOG.md format). Produce other outputs based on context:

| Output | When to Include |
|---|---|
| **A: CHANGELOG.md** | Always |
| **B: GitHub/GitLab Release Notes** | Always (unless user specifies otherwise) |
| **C: Internal/Slack Summary** | Always (unless user specifies otherwise) |
| **D: Email/Newsletter** | When user requests it, or when the project appears to have end users (web app, mobile app, SaaS) |
| **E: Package Registry** | When user requests it, or when `package.json`, `Cargo.toml`, `pyproject.toml`, `setup.py`, or `*.gemspec` is detected |

Separate each output with a clear header.

---

## Output A: CHANGELOG.md (Keep a Changelog Format)

Follows [keepachangelog.com](https://keepachangelog.com) exactly. Suitable for committing
directly to the repository.

```markdown
## [1.3.0] - 2026-03-14

### Breaking Changes
- **Renamed `/api/v1/users` to `/api/v2/users`** — update all API clients before upgrading. The v1 endpoint returns a deprecation warning in this release and will be removed in v2.0.0 (#234)

### Security
- Patched XSS vulnerability in user-generated content rendering (CVE-2026-XXXX) — upgrade immediately if you render user HTML (#233)

### Added
- OAuth2 login with Google and GitHub — click "Continue with Google" on the login page (#218)
- Dark mode support — respects system preference and includes manual toggle in Settings > Appearance (#225)
- Bulk export to CSV for all report types (#229)

### Fixed
- Cart total calculated incorrectly when multipl

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [alissonlinneker](https://github.com/alissonlinneker)
- **Source:** [alissonlinneker/claude-skills](https://github.com/alissonlinneker/claude-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-alissonlinneker-claude-skills-changelog-writer
- Seller: https://agentstack.voostack.com/s/alissonlinneker
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
