release — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited release (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Cuts a versioned release: pick the next semantic version, write proper release notes, tag the commit, and publish the GitHub release.
This sits next to /gh-bootstrap and /gh and answers a different question. /gh-bootstrap wires the release plumbing once (.github/release.yml, the tag-driven workflow). /gh is the raw gh release command reference. This skill is the ceremony you run each time you ship: decide the bump, draft the notes, tag, publish.
| Concern | Skill |
|---|---|
| One-time release-notes config + tag-driven workflow | /gh-bootstrap |
Raw per-command gh release create / view / upload | /gh |
| Deciding the version, drafting notes, tagging, publishing | `/release` (this skill) |
| Local commit before any of this | /commit |
If the repo has a tag-driven release workflow (from /gh-bootstrap), pushing the tag is enough — the workflow publishes the release. This skill still decides the version and (optionally) drafts curated notes; it just stops after the tag push and reports that the workflow takes over. Otherwise it publishes the release itself with gh release create.
Refuse to release from a dirty or diverged state — a release tag is permanent and public.
git fetch --tags origin
BRANCH=$(git branch --show-current)
DEFAULT=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)
git diff-index --quiet HEAD || { echo "uncommitted changes — commit or stash first"; exit 1; }
[ "$BRANCH" = "$DEFAULT" ] || echo "WARNING: not on $DEFAULT (on $BRANCH) — releases normally tag the default branch"
read -r AHEAD BEHIND < <(git rev-list --left-right --count "origin/$DEFAULT...HEAD")
[ "$BEHIND" = 0 ] || { echo "HEAD is $BEHIND commits behind origin/$DEFAULT — pull/rebase before tagging"; exit 1; }
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")Confirm with the user:
$LAST_TAG) — the baseline for the version bump and the notes range. If the repo has no tags yet, this is the first release.Stop and tell the user — don't tag — if the tree is dirty, or HEAD is behind origin/$DEFAULT.
Read references/semver.md for the full decision rules. The short version: scan the Conventional Commits since the last tag and map the highest-impact change to a bump.
git log "${LAST_TAG:+$LAST_TAG..}HEAD" --no-merges --pretty='%s'| Highest-impact change since last tag | Bump (≥ 1.0.0) | Bump (0.x pre-1.0) |
|---|---|---|
feat!: / fix!: / BREAKING CHANGE: footer | major | minor |
feat: | minor | patch |
fix: / perf: | patch | patch |
only docs / chore / refactor / test / ci | patch (or skip — ask) | patch |
Match the repo's existing tag scheme — if $LAST_TAG is v1.2.3, the next is v1.3.0, not 1.3.0. Detect and reuse the v prefix (or its absence). Detect prerelease identifiers (-rc.1, -beta.2) and keep the user's convention.
Propose the computed version and the one-line reason ("3 feats, no breaking → minor → v1.3.0"). Let the user confirm or override. Never tag a version the user hasn't seen.
Read references/release-notes.md for the three strategies and how to choose. Summary:
gh release create --generate-notes) — best when the repo merges via PRs and has .github/release.yml. GitHub groups merged PRs into the configured category buckets by label. Cheapest, and complete as long as every change landed as a labelled PR..github/release.yml, when commits (not PRs) are the unit of change, or when the release needs editorial highlights. Group by Conventional Commit type; lead with a Highlights section and, for any breaking change, an Upgrade notes section with the concrete migration step. assets/release-notes-template.md is the starting structure.When curating, derive the entries from the commit log, not from imagination — every bullet must trace to a real commit. Link PRs/commits where the audience would want the detail.
If CHANGELOG.md exists, keep it in sync. Most repos follow Keep a Changelog: move the ## [Unreleased] entries under a new ## [VERSION] - YYYY-MM-DD heading, leave a fresh empty Unreleased, and update the comparison links at the bottom. If there's no changelog and the user doesn't want one, skip this — don't introduce a changelog they didn't ask for.
Annotated tag (carries a message, author, and date — lightweight tags don't, and git describe treats them differently). Tag the agreed commit, then push only the tag.
VERSION=v1.3.0
git tag -a "$VERSION" -m "$VERSION" # add -s to GPG-sign if the repo signs tags
git push origin "$VERSION"If a tag-driven release workflow exists (.github/workflows/release.yml), stop here — the workflow publishes the release on tag push. Report the workflow run URL and skip step 6.
Only when there's no tag-driven workflow doing it for you.
# Auto-generated notes:
gh release create "$VERSION" --title "$VERSION" --generate-notes --latest
# Curated notes from a file:
gh release create "$VERSION" --title "$VERSION" --notes-file NOTES.md --latest
# Prerelease (rc/beta/alpha) — do NOT mark --latest:
gh release create "$VERSION" --title "$VERSION" --notes-file NOTES.md --prerelease
# Draft for review before going public:
gh release create "$VERSION" --title "$VERSION" --notes-file NOTES.md --draftAttach build artifacts by listing them after the tag (gh release create "$VERSION" ... dist/*.tar.gz) when the project ships binaries.
Read the published state back — don't claim success from the create command's exit code alone.
gh release view "$VERSION" --json tagName,isLatest,isDraft,isPrerelease,url --jq .
git ls-remote --tags origin "$VERSION"Report to the user: the version and why, the notes strategy used, the release URL, and whether it's draft/prerelease/latest. Call out anything skipped (e.g. "workflow is publishing — release not yet visible") and why.
.github/release.yml or the release workflow — that's /gh-bootstrap (run once, first).gh release flags outside a release ceremony — that's /gh./commit + /gh.just/CI step.git tag -f + git push -f to move a published tag breaks every consumer who already fetched it. If you tagged the wrong commit, cut a new patch version instead.--generate-notes.release.yml are the lever — fix them via /gh-bootstrap, not here.-rc build as latest makes it the default download and the target of releases/latest. Use --prerelease and omit --latest.0.x, breaking changes bump the minor, not the major. See references/semver.md.git config tag.gpgSign true or a project convention), use git tag -s; an unsigned tag on a signed-release repo fails verification downstream.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.