Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions .claude/skills/release-notes/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
name: release-notes
description: Generate GitHub release notes from git tags. Usage - /release-notes <from_tag> <to_tag>. Runs the changelog script, then rewrites the output into polished GitHub release notes.
disable-model-invocation: true
argument-hint: <from_tag> <to_tag>
description: Generate GitHub release notes from git refs (tags, commits, or HEAD). Usage - /release-notes <from> <to>. Runs the changelog script, then rewrites the output into polished GitHub release notes.
argument-hint: <from_ref> [to_ref]
user-invocable: true
allowed-tools: Bash(git log *), Bash(git tag *), Bash(git describe *), Bash(bash scripts/changelog.sh *), Bash(gh release *), Read, Agent
---
Expand All @@ -18,12 +17,14 @@ Generate polished GitHub release notes for the code-android-app repository.

## Input

Parse the two tags from `$ARGUMENTS`, e.g.:
Parse the two refs from `$ARGUMENTS`. Each ref can be a tag, a commit SHA, a commit number (Nth commit in repo history), or `HEAD`:
- `/release-notes fcash/2026.4.10 fcash/2026.4.11`
- `/release-notes fcash/2026.4.9 HEAD`
- `/release-notes a3f2417 HEAD`
- `/release-notes 3599 HEAD` (from the 3599th commit to HEAD)

If only one tag is provided, use it as `<from>` and default `<to>` to `HEAD`.
If no tags are provided, use the pre-flight latest tag as `<from>` and `HEAD` as `<to>`.
If only one ref is provided, use it as `<from>` and default `<to>` to `HEAD`.
If no refs are provided, use the pre-flight latest tag as `<from>` and `HEAD` as `<to>`.

## Steps

Expand All @@ -42,14 +43,15 @@ Use the Agent tool with `model: "haiku"`. Pass the raw changelog output with thi
> Given these git commits (conventional commit format), write user-facing release notes.
>
> Rules:
> - Group under: **Features**, **Bug Fixes**, **Improvements** (omit empty sections)
> - Group under: **Features**, **Bug Fixes**, **Improvements**, **Dependencies** (omit empty sections)
> - Write for end users — no jargon, file names, or internals
> - One short sentence per item
> - Group related commits into a single bullet when they address the same area
> - Use scope as context but write in plain language; keep scope in **bold** prefix when it adds clarity
> - Drop internal-only changes (pure refactors, CI tweaks, build config) unless user-facing
> - ALWAYS include bug fixes — only drop pure refactors, CI pipeline changes, and release/manifest bookkeeping
> - Feature bullets start with a lowercase verb (e.g., "add", "support", "enable")
> - Bug fix bullets start with "Fixed" (capitalized)
> - **Dependencies** section: list each dependency bump as `Name X.Y.Z → A.B.C` (use the human-readable library name, not the Maven coordinate). Include targetSdkVersion and Gradle wrapper bumps in this section too.
> - Use 2-space indent before each bullet (` - `)
> - Do NOT include commit hashes
> - If no user-facing changes, output: Bug fixes and performance improvements.
Expand Down
23 changes: 21 additions & 2 deletions scripts/changelog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,27 @@

set -euo pipefail

FROM="${1:?Usage: changelog.sh <from> <to>}"
TO="${2:-HEAD}"
# Resolve a ref that might be a commit number (e.g. 3599 = the 3599th commit).
# Pure numbers with fewer than 7 digits are always treated as commit ordinals
# (7 is the minimum git short-SHA length, so this avoids ambiguity).
# Everything else (tags, SHAs, HEAD) passes through as-is.
resolve_ref() {
local ref="$1"
if [[ "$ref" =~ ^[0-9]+$ ]] && [ "${#ref}" -lt 7 ]; then
local sha
sha=$(git rev-list --reverse HEAD | sed -n "${ref}p")
if [ -z "$sha" ]; then
echo "Error: commit #$ref not found (repo has $(git rev-list --count HEAD) commits)" >&2
exit 1
fi
echo "$sha"
else
echo "$ref"
fi
}

FROM=$(resolve_ref "${1:?Usage: changelog.sh <from|commit#> [to|commit#]}")
TO=$(resolve_ref "${2:-HEAD}")

# Collect commits (skip merges)
COMMITS=$(git log --no-merges --format="%H %s" "$FROM".."$TO")
Expand Down
Loading