autohand "Generate release notes for version 2.4.0 from the git log since the v2.3.0 tag. Group changes by type (features, fixes, improvements). Include PR numbers and contributor names."

What you'll learn

  • How to generate structured release notes from a git log between two tags
  • How to set up conventional commits for better classification
  • How to customize the output format for GitHub releases, emails, or JSON
  • How to automate release note generation in a CI pipeline

Before you start

  • Autohand Code installed. Run autohand --version to confirm. See Your First Autohand Session if you need to install it.
  • Git tags for previous releases. Run git tag --list to check what tags exist. Adjust the prompt if your project uses a different tagging convention like release/2.3.0.
  • Commit messages with context. Clear messages like feat: add dark mode toggle produce much better output than wip or misc changes.
  • PR numbers in commits (optional). GitHub and GitLab add PR numbers automatically when you use squash merge or merge commit. Autohand extracts and links them.

Set up conventional commits

Conventional commits are a lightweight standard that makes release notes generation much more reliable. If your project does not use them yet, it takes about five minutes to set up.

The format is simple: type(scope): description. Common types are feat, fix, docs, refactor, test, and chore.

Add a commit message linter to enforce the format.

Ask Autohand to generate the configuration files.

Run the release notes prompt

Navigate to your repository root and start Autohand. No special flags are needed.

Run the prompt with your actual version numbers and tag names.

Autohand runs the git log internally, parses the commits, classifies them by type, and writes the Markdown. The whole process takes under a minute for a typical release with 30-80 commits.

Review the output

Autohand produces a Markdown block you can copy directly into your GitHub release or CHANGELOG.md. Here is what a typical output looks like.

Read through the output and check that nothing important is missing. If a significant change was not captured, follow up in the same session.

Customize the format

The default output is GitHub Markdown. You can ask for a different format in the same session.

Plain text for an email announcement.

JSON for a programmatic pipeline.

Append to an existing CHANGELOG.md file using the Keep a Changelog format.

Automate in CI

You can run this as part of your release pipeline using Autohand's headless mode. Add a step to your GitHub Actions workflow that triggers when a version tag is pushed.

Tip: Use fetch-depth: 0 in the checkout step. Without it, GitHub Actions does a shallow clone and the git log since the previous tag will be empty.

Best practices for commit messages

The single highest-leverage thing you can do to improve release notes quality is write better commit messages. Here are the patterns that work best.

  • Describe the change from the user's perspective. "Add bulk export" is better than "implement export controller method".
  • Put breaking changes in the commit body. Add BREAKING CHANGE: in the commit body for any change that breaks the public API. Autohand surfaces these prominently in the release notes.
  • Use imperative mood. "Fix login bug" not "Fixed login bug" or "Fixes login bug". This is the git convention and it reads naturally in a list.
  • Reference issues and PRs. Including (#123) at the end of a commit message gives Autohand and readers a direct link to the discussion context.

What you learned

  • Generated structured release notes from a git log grouped by change type
  • Set up conventional commits with commitlint and husky for consistent messages
  • Customized the output format for GitHub releases, plain text emails, and JSON
  • Automated release note generation in a GitHub Actions pipeline on tag push

Try next

autohand "Generate a GitHub Actions workflow that runs release notes generation, creates a GitHub release, and posts a summary to our Slack channel on every version tag push"