Changelog Command

View release notes and changelogs for updated packages directly in your terminal — for a single package, or aggregated across every package that changed in your project. cli-changelog.png

Usage

whatsdiff changelog [package] [version] [options]

Omit the package argument to aggregate changelogs for every package that was updated (or downgraded) between two refs.

Arguments

  • [package] - Optional. Package name (e.g., symfony/console for Composer, react for npm). When omitted, the command shows changelogs for every updated package in your project.
  • [version] - Optional version or version range (e.g., 5.1.0 or 5.0.0...5.1.0). Only valid when a package is specified.

Options

You can filter by changes made in your project:

  • --from=FROM - Git commit, branch, or tag to get the starting version from
  • --to=TO - Git commit, branch, or tag to get the ending version from (defaults to HEAD)
  • --ignore-last - Ignore last uncommitted changes

Or if you want a changelog for a specific package even outside of your project:

  • -t, --type=TYPE - Specify package manager type (composer or npm)

Filtering options (aggregate mode only):

  • --include=INCLUDE - Include only specific package manager types (comma-separated: composer, npmjs)
  • --exclude=EXCLUDE - Exclude specific package manager types (comma-separated: composer, npmjs)

Other options:

  • -f, --format=FORMAT - Output format: text (default), json, or markdown
  • -s, --summary - Show summarized changelog (combines all releases into one view)
  • --no-cache - Disable caching for this request
  • --include-prerelease - Include pre-release versions (beta, alpha, RC, etc.)

Option Conflicts

  • --include and --exclude are mutually exclusive
  • The positional version argument requires a package argument

Three Modes of Operation

The changelog command works in three distinct modes depending on how you invoke it:

Aggregate Mode (All Updated Packages)

Run the command without a package argument to aggregate release notes for every package that was updated or downgraded between two refs:

whatsdiff changelog

The command:

  • Uses the same comparison logic as analyse to find every changed package between --from and --to (defaults to comparing your working tree against the previous commit)
  • Resolves release notes for each updated/downgraded package and prints them grouped by package
  • Can be scoped to one ecosystem with --include=composer or --include=npmjs
  • Supports the same --format options (text, JSON, markdown) and the --summary flag

This mode is the easiest way to review everything a composer update or npm update brought in — without having to invoke changelog once per package.

Single Package, Inside a Project (Git-Based)

When you run the command inside a git repository with lock files:

whatsdiff changelog symfony/console

The command:

  • Detects the package in your composer.lock or package-lock.json
  • Automatically determines version changes from your git history
  • Compares the current version with the previous version in your commits
  • Perfect for reviewing changes after composer update or npm update

Single Package, Outside a Project (Direct Query)

When you want to check any package's changelog without having it in your project:

whatsdiff changelog symfony/console --type=composer
whatsdiff changelog react --type=npm

The command:

  • Queries the package registry directly (Packagist or npm)
  • Requires the --type flag to specify the package manager
  • You can specify exact versions or ranges
  • Useful for researching packages before adding them to your project

Output Formats

The changelog command supports three output formats that can be selected with the --format option.

Text Format (Default)

Human-readable format with clear sections for each release:

whatsdiff changelog guzzlehttp/guzzle 7.8.1 --type=composer

Output:

Release Notes
--------------------------------------------------------------------------------

7.8.1 - Release 7.8.1
Date: 2023-12-03
URL: https://github.com/guzzle/guzzle/releases/tag/7.8.1

Changes:
  • Updated links in docs to their canonical versions
  • Replaced `call_user_func*` with native calls

--------------------------------------------------------------------------------

JSON Format

Structured data format perfect for automation and CI/CD pipelines:

whatsdiff changelog guzzlehttp/guzzle 7.8.1 --type=composer --format=json

Output:

{
    "total_releases": 1,
    "releases": [
        {
            "tag_name": "7.8.1",
            "title": "Release 7.8.1",
            "date": "2023-12-03T20:36:10Z",
            "url": "https://github.com/guzzle/guzzle/releases/tag/7.8.1",
            "body": "### Changed\r\n\r\n- Updated links in docs to their canonical versions\r\n- Replaced `call_user_func*` with native calls\r\n",
            "changes": [
                "Updated links in docs to their canonical versions",
                "Replaced `call_user_func*` with native calls"
            ],
            "fixes": [],
            "breaking_changes": []
        }
    ]
}

Markdown Format

Formatted markdown ready to copy into documentation:

whatsdiff changelog guzzlehttp/guzzle 7.8.1 --type=composer --format=markdown

Output:

# Release Notes

## 7.8.1 - Release 7.8.1

**Date:** 2023-12-03
**URL:** https://github.com/guzzle/guzzle/releases/tag/7.8.1

### Changes
- Updated links in docs to their canonical versions
- Replaced `call_user_func*` with native calls

Summary View

Use the --summary flag to aggregate changes across multiple releases:

whatsdiff changelog guzzlehttp/guzzle 7.7.0...7.8.1 --type=composer --summary

Output:

Release Notes Summary
--------------------------------------------------------------------------------

Total Releases: 3

Changes:
  • Updated links in docs to their canonical versions
  • Replaced `call_user_func*` with native calls
  • Added support for PHP 8.3
  • Improved error handling for network timeouts
  • Fixed issue with header parsing

--------------------------------------------------------------------------------

This is useful for getting a quick overview of all changes without the detail of individual releases.

Aggregate Mode Output

When no package argument is given, the command emits one section per updated package using the same three formats.

Text:

guzzlehttp/psr7 (2.8.0 → 2.9.0)
================================================================================

2.9.0
Date: 2026-03-10

Changes:
  • Added nested array expansion support to `MultipartStream`
  • Added `@return static` to `MessageTrait` methods
  • Updated MIME type mappings

--------------------------------------------------------------------------------

2.8.1
Date: 2026-03-10

Fixes:
  • Encode `+` signs in `Uri::withQueryValue()` and `Uri::withQueryValues()` to prevent them being interpreted as spaces


saloonphp/saloon (3.14.2 → 4.0.0)
================================================================================
… (release entries per version)

Per-package headers use the {package} ({from} → {to}) format followed by an 80-character separator, with a blank line between packages.

JSON:

{
    "total_packages": 2,
    "packages": [
        {
            "package": "guzzlehttp/psr7",
            "type": "composer",
            "from_version": "2.8.0",
            "to_version": "2.9.0",
            "total_releases": 2,
            "releases": [
                {
                    "tag_name": "2.9.0",
                    "title": "2.9.0",
                    "date": "2026-03-10T09:03:43Z",
                    "url": null,
                    "body": "### Added\n- Added nested array expansion support to `MultipartStream`\n",
                    "changes": ["Added nested array expansion support to `MultipartStream`", ""],
                    "fixes": [],
                    "breaking_changes": [],
                    "deprecated": [],
                    "removed": [],
                    "security": []
                }
            ],
            "first_tag": "2.9.0",
            "last_tag": "2.8.1"
        }
    ]
}

Each entry in packages[] carries the package name, manager type, resolved from_version / to_version, the full releases array (same shape as single-package mode), and first_tag / last_tag markers. When --summary is passed, each entry also includes an aggregated summary object.

Markdown:

# guzzlehttp/psr7 (2.8.0 → 2.9.0)

## 2.9.0

**Date:** 2026-03-10

### Added
- Added nested array expansion support to `MultipartStream`
- Added `@return static` to `MessageTrait` methods

---

## 2.8.1

**Date:** 2026-03-10

### Fixed
- Encode `+` signs in `Uri::withQueryValue()` and `Uri::withQueryValues()` to prevent them being interpreted as spaces

# saloonphp/saloon (3.14.2 → 4.0.0)

Each package becomes a top-level # heading; release entries inside reuse the single-package markdown layout.

No updated packages: all three formats emit an empty result rather than failing.

Format Message
Text No updated packages found.
Markdown _No updated packages found._
JSON {"total_packages": 0, "packages": []}

Examples

Aggregate Mode (All Updated Packages)

Show changelogs for every package that changed since the previous commit:

whatsdiff changelog

Aggregate across a release range:

whatsdiff changelog --from=v1.0.0 --to=v2.0.0

Restrict the aggregate to one ecosystem and render markdown:

whatsdiff changelog --include=composer --format=markdown

JSON aggregate for downstream tooling:

whatsdiff changelog --format=json

Show Changelog for Latest Version

Display the changelog for the most recent version change in your lock file:

whatsdiff changelog symfony/console

This automatically detects the version from your composer.lock and shows the release notes.

Specific Version

View the changelog for a specific version release:

whatsdiff changelog laravel/framework 11.0.0

Version Range

See all release notes between two versions:

whatsdiff changelog symfony/console 6.0.0...6.4.0

Between Git Commits of your project

Compare package versions between two commits:

whatsdiff changelog doctrine/orm --from=abc123 --to=def456

Or between a previous commit and current state:

whatsdiff changelog guzzlehttp/guzzle --from=v1.0.0

Different Output Formats

Export changelog in different formats (see Output Formats section for examples):

# Markdown format (great for documentation)
whatsdiff changelog react --format=markdown

# JSON format (useful for automation)
whatsdiff changelog symfony/console --format=json

# Summary view (aggregated changelog)
whatsdiff changelog symfony/console --summary

Get changelog for any package even outside your project

If the package isn't in your lock files or you want to force a specific registry:

whatsdiff changelog react --type=npm
whatsdiff changelog symfony/mailer --type=composer

Option: Include Pre-releases

By default, pre-release versions are excluded. To include them:

whatsdiff changelog laravel/framework --include-prerelease

Use Cases

1. Generate Multi-Package Release Notes for a PR

After a composer update or npm update, capture changelogs for every updated package and drop them straight into your PR description:

whatsdiff changelog --from=origin/main --to=HEAD --format=markdown > pr-notes.md

Aggregate mode means a single command produces the full review surface — no need to invoke changelog once per package.

2. Review Changes Before Upgrading

Before running composer update, check what's new:

# See what's changed in the latest Laravel release
whatsdiff changelog laravel/framework

# Review all changes in a major version upgrade
whatsdiff changelog symfony/console 6.0.0...7.0.0

3. Understand Breaking Changes

Quickly identify breaking changes when debugging after an update:

whatsdiff changelog symfony/http-kernel --summary

The summary view aggregates all changes, making it easier to spot breaking changes.

4. Generate Release Notes

Extract changelogs for your own release documentation:

whatsdiff changelog doctrine/orm --format=markdown > release-notes.md

5. Code Review - Understand PR Dependencies

When reviewing a pull request that updates dependencies:

# Switch to the PR branch
git checkout feature/update-deps

# View changelogs for updated packages
whatsdiff changelog laravel/framework
whatsdiff changelog livewire/livewire

6. Audit Historical Changes

Investigate what changed in dependencies between production releases:

whatsdiff changelog symfony/security-core --from=v2.0.0 --to=v3.0.0

7. CI/CD Integration or Other tools

Use the JSON output for automation in scripts:

#!/bin/bash
echo "Dependency changelogs for this deployment:"
whatsdiff changelog laravel/framework --format=json > deployment-changes.json

Related Commands

  • Use analyse to see all dependency changes in your project
  • Use between to compare all dependencies between commits
  • Use tui for an interactive view with integrated changelog browsing
  • Use check to verify if a specific package changed