This skill automates the full release workflow for a single-package GitHub repository,
from analysis through changelog authoring and PR creation. It relies exclusively on
gh (GitHub CLI) and git no other tools needed.
Steps 1 - 4 are read-only reconnaissance nothing is written to the repo until
Step 5, once the version number is confirmed.
Use this skill whenever the user wants to cut a new release, publish a new version,
bump a version, create a release branch, generate a changelog, or open a release PR
on a GitHub repository. Trigger even if the user says something casual like “let’s
ship a new version” or “time to release”.
Examples below include both Bash and PowerShell variants; Windows users should prefer
the PowerShell blocks.
Before starting, verify the environment:
bash
gh auth status # must be authenticatedgh repo view --json nameWithOwner # must be inside a GitHub repogit status # working tree should be clean
If any check fails, stop and tell the user what to fix before continuing.
Then ask the user one question:
“Which directory contains your library’s public-facing source code?
(e.g. src/, lib/, pkg/ - used to focus the diff on what consumers
actually see. Press Enter to scan the whole repo.)”
Store the answer as PUBLIC_PATH. If empty, PUBLIC_PATH is . (repo root).
Exclude these paths from all diffs regardless: tests/, test/, spec/,
__tests__/, docs/, *.lock, *-lock.json, *.sum, generated files
(files with a “do not edit” header comment), and build artefacts.
Work through every step in order. Show the user what command you’re about to run and
its output. Pause and ask for confirmation only when explicitly noted.
Why not gh release list? GitHub Releases are an optional layer on top of Git
tags. Many repos tag releases with git tag without ever creating a GitHub Release,
so gh release list can return empty even when version tags exist. Reading tags
directly from git is the reliable source of truth.
bash
# Fetch all tags from remote to ensure local view is currentgit fetch --tags# Find the latest version tag, sorted semantically# --sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' | head -1)echo "Latest tag: $PREV_TAG"
powershell
# Fetch all tags from remote to ensure local view is currentgit fetch --tags# Find the latest version tag, sorted semantically# --sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)$prevTag = git tag --sort='-version:refname' | ` Select-String '^[vV]?\d+\.\d+\.\d+' | ` Select-Object -First 1 -ExpandProperty Lineif ($prevTag) { $prevSha = git rev-list -n 1 $prevTag} else { $prevSha = git rev-list --max-parents=0 HEAD}Write-Output "Latest tag: $prevTag"
Then verify the tag exists on the remote (not just locally):
If the remote check returns nothing, warn the user that the tag appears to be local-only
and hasn’t been pushed - they may want to push it before continuing.
PREV_TAG is the tag name exactly as found (e.g. v1.4.2). Strip any leading v
when doing arithmetic; preserve it when naming things.
If no tags exist at all, treat PREV_TAG as (none), set PREV_SHA to the
first commit, and default the new version to 1.0.0 (skip Step 4 versioning logic;
go straight to Step 5).
If the tag does not point to a real commit (orphaned tag), fall back to
git rev-list --max-parents=0 HEAD and warn the user.
Focus your detailed reading on files with the most changes and files whose names
suggest they define public interfaces (e.g. index.*, api.*, exports.*,
public.*, mod.*, __init__.*).
Apply these rules to your analysis from Step 3 (full rules in references/semver-rules.md):
Condition
Bump
Any breaking change to public API (removal, signature change, behaviour change)
MAJOR
New exported symbol or feature, no breaking changes
MINOR
Bug fix, perf improvement, security fix, docs, chore only
PATCH
When a release contains a mix, the highest precedence wins:
MAJOR > MINOR > PATCH.
Compute NEXT_VERSION:
Split PREV_TAG into MAJOR.MINOR.PATCH integers.
Apply the appropriate bump.
Format as vMAJOR.MINOR.PATCH.
Present the proposed version to the user with a brief rationale that cites
specific code findings, not just commit messages. Example:
“I’m proposing v2.1.0. The diff shows two new exported functions (NewClient and
WithTimeout) in src/client.go, and no existing public symbols were removed or
changed. Commit messages corroborate this as feature additions.”
Ask: “Does this version look right, or would you like to adjust it?”
Wait for confirmation before proceeding.
Omit sections that have no entries - don’t leave empty headings.
Write entries in plain English from a user’s perspective, derived primarily
from what the code diff shows, supplemented by commit message context.
Good: “Added WithTimeout option to HTTP client constructor.”
Bad: “feat: add timeout cfg param”
Map findings to sections:
New exported symbol ? Added
Breaking removal ? Removed
Breaking change to existing API ? Changed (flag it as breaking)
Bug/logic fix, perf ? Fixed
Security fix ? Security
Internal refactor, docs, chore, test ? omit unless user-visible
If a commit message revealed intent that the code diff alone wouldn’t convey
(e.g. a security fix disguised as a one-line change), include that context in
the changelog entry.
Also update the diff link at the bottom of the file:
Show the user the proposed changelog section before writing it to disk.
If any signal conflicts were found in Step 3c, flag them here so the user can verify.
Ask: “Does this changelog look accurate? Any entries to add, remove, or reword?”
Incorporate feedback, then write to disk.
?? IMPORTANT: Always use --body-file to pass PR body text, never --body with inline text.
Inline escape sequences like \n are not interpreted as newlines by PowerShell and will appear
as literal text in the PR. Using a file ensures proper markdown formatting.
bash
gh pr create \ --base main \ --head release/vX.Y.Z \ --title "Release vX.Y.Z" \ --body "$(cat <<'EOF'## Release vX.Y.ZThis PR prepares the **vX.Y.Z** release.### What's included<!-- paste the changelog section here -->### Checklist- [ ] Changelog reviewed- [ ] Version bump verified- [ ] CI passingAfter merging, create the tag on the merge commit:\`\`\`git tag vX.Y.Z <merge-commit-sha>git push origin vX.Y.Z\`\`\`EOF)"
powershell
# Create PR body using here-string (preserves actual newlines, not escape sequences)$prBody = @"## Release vX.Y.ZThis PR prepares the **vX.Y.Z** release.### What's included<paste changelog here>### Checklist- [ ] Changelog reviewed- [ ] Version bump verified- [ ] CI passingAfter merging, create the tag on the merge commit:```git tag vX.Y.Z <merge-commit-sha>git push origin vX.Y.Z```"@# Write to file and use --body-file (do NOT use inline --body with escape sequences)$prBody | Out-File -FilePath release_pr_body.md -Encoding utf8 -NoNewlinegh pr create --base main --head release/vX.Y.Z --title "Release vX.Y.Z" --body-file release_pr_body.md
Paste the changelog section into the PR body’s “What’s included” block (or leave placeholder for manual review).
If a command that works locally prints gh usage or treats a subcommand as separate token, ensure you’re
invoking the gh.exe on PATH (Get-Command gh) and avoid passing unexpanded nested substitutions; use the PowerShell
patterns above.
Recommend tests: gh --version; git fetch --tags; run the PowerShell snippet to set $prevTag and run git diff --name-only $prevSha..HEAD – src/
MIT — the text of every skill is reproduced unmodified, frontmatter included, under the upstream licence.
Discovery
200 skills found by walking the repository tree for SKILL.md, not by matching a directory convention. 2 distinct layouts observed: .github/skills/*/SKILL.md, skills/*/SKILL.md.
Authorship
3 of 200 skills are installed into the repository rather than published from it. They are shelved in the closing “Credited skills” part and remain the work of their own authors. A skill counts as credited when its only copy lives under one agent’s dot directory; visible directories, per-agent mirror sets, and skills installable from this repository on skills.sh all count as published.
Issue colours
Resolved from a curated brand profile — hue 295°, chroma 0.190. Two accent tones are generated per issue and each is proven against its own ground before it ships: a single accent that passes AA on both light and dark paper is arithmetically impossible.
Heading repairs
1 repair applied to this skill so the document has one h1 and no skipped levels:
Shifted “20 headings” from h1 to h2 so the skill title is the only h1.
Images inside a skill come from the upstream repository. Where the author gave no alternative text we mark the image decorative rather than inventing a description — a plausible caption we made up is worse than none for the reader who depends on it.
Marketplace
A plugin manifest is published at .github/plugin/marketplace.json by GitHub, declaring 162 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree.
Signal
Install counts come from skills.sh. They measure downloads, not quality, and an unranked repository is not an unread one.
Agent surfaces
The whole issue is available as one markdown document at /github/awesome-copilot.md, and each skill at its own .md URL.
Publication
Set by Skills Docs from the source repository. Body text is Literata at the reader’s chosen size and measure; code is Geist Mono. Nothing on this page was written by us except this paragraph.