Skip to content
Security
Skill

/release-notes

Generate and publish concise, evidence-based notes in the body of the latest existing GitHub Release. Use only when the user explicitly invokes `$release-notes` or explicitly asks to update the latest existing GitHub Release body. Do not invoke for general release planning,

From plugin
cc-safety-net
1.9k2 skills1 hook

Claude Code

$ npx -y skills add kenryu42/cc-safety-net --skill release-notes --agent claude-code

SKILL.md

release-notes.SKILL.md
name: release-notes
description: Generate and publish concise, evidence-based notes in the body of the latest existing GitHub Release. Use only when the user explicitly invokes `$release-notes` or explicitly asks to update the latest existing GitHub Release body. Do not invoke for general release planning, changelog, tag, or version tasks.
disable-model-invocation: true

Release Notes

Update only the body of the latest existing GitHub Release. Treat the repository diff as the source of truth. Use pull requests and commits only as supporting evidence.

Safety rules

  • Use `gh` for all GitHub Release, pull request, issue, and API operations. Use `git fetch` only when required tag objects or history are missing.
  • Do not create or delete a release.
  • Do not change a tag, title, target, draft state, prerelease state, latest-release state, or other release metadata.
  • Do not publish a draft.
  • Do not use a new release as a fallback when no release exists.
  • Do not infer release order from version text, semantic versions, or Git tag order.
  • Stop when required evidence is unavailable. Do not publish partial or speculative notes.
  • Treat the notes file as a full replacement for the current release body, not as text to append.

1. Verify prerequisites

Run all checks from the repository that the user wants to release:

1. Confirm that the current directory is in a Git worktree:

   git rev-parse --is-inside-work-tree

2. Confirm that `gh` is available:

   command -v gh

3. Confirm that `gh` can resolve and access the current GitHub repository. Save its URL and get the GitHub host from it:

   REPO_URL="$(gh repo view --json url --jq '.url')"
   GH_HOSTNAME="${REPO_URL#*://}"
   GH_HOSTNAME="${GH_HOSTNAME%%/*}"

4. Use the repository URL to get its GitHub host. Confirm the active account for that host:

   gh auth status --active --hostname "$GH_HOSTNAME"

Stop with a clear error if a check fails. Do not initialize a Git repository, change authentication, or select another repository as a fallback.

2. Select the release range

Use GitHub's descending release-list order as the release sequence. Include drafts and prereleases because they are existing releases:

gh release list --limit 2 --order desc \
  --json tagName,name,createdAt,publishedAt,isDraft,isPrerelease,isImmutable,isLatest
  • Select the first item as the latest release.
  • Select the second item as the previous release.
  • If the list is empty, stop and state that no existing GitHub Release was found. Never create one.
  • If there is one item, treat it as the project's first release.
  • Do not re-sort the result. A draft can have no `publishedAt` value.
  • Do not replace either tag with a Git tag that has no GitHub Release.

Set `LATEST_TAG` and, when present, `PREVIOUS_TAG` from this result. Quote both values in every command. Then load and record the latest release before any edit:

gh release view \
  --json tagName,name,body,isDraft,isPrerelease,isImmutable,publishedAt,targetCommitish,url \
  -- "$LATEST_TAG"

Confirm that the returned `tagName` is `LATEST_TAG`. Record `tagName`, `name`, `isDraft`, `isPrerelease`, `isImmutable`, and `targetCommitish` from this result. Also record `isLatest`, `createdAt`, and `publishedAt` from the release-list result. Use these values for the final safety check. If `isImmutable` is true, stop and report that GitHub does not permit the body update.

3. Resolve the tag history

Set full Git refs so that a tag that starts with `-` cannot become a command option:

LATEST_REF="refs/tags/$LATEST_TAG"
PREVIOUS_REF="refs/tags/$PREVIOUS_TAG"

Set `PREVIOUS_REF` only when `PREVIOUS_TAG` exists. Confirm that each selected release tag resolves to a local commit:

git rev-parse --verify "$LATEST_REF^{commit}"
git rev-parse --verify "$PREVIOUS_REF^{commit}"

Run the second command only when `PREVIOUS_TAG` exists. If a tag is missing, inspect the Git remotes, identify the remote for the same GitHub repository, and use `git fetch` to get the required tags. Do not assume that the remote is named `origin`. Stop if the remote is ambiguous or a release tag still does not resolve. Do not guess a replacement range.

Check for a shallow repository:

git rev-parse --is-shallow-repository

If the result is `true`, use the identified GitHub remote to fetch complete history and tags:

git fetch --unshallow --tags "$GITHUB_REMOTE"

Then run the shallow-repository check again. Continue only when the result is `false` and both required tag commits resolve. If the full history cannot be fetched, stop. Do not generate notes from an incomplete history.

When `PREVIOUS_TAG` exists, check whether it is an ancestor of `LATEST_TAG`:

git merge-base --is-ancestor "$PREVIOUS_REF^{commit}" "$LATEST_REF^{commit}"

A non-ancestor result is not an automatic failure. State it in the working notes, use the tree diff to identify the shipped-state change, and inspect both sides of the history so that the commit list does not cause a false claim.

4. Investigate all shipped changes

When a previous release exists, start with:

git log --date=short --format='%H%x09%ad%x09%s' "$PREVIOUS_REF..$LATEST_REF"
git diff --stat "$PREVIOUS_REF" "$LATEST_REF"
git diff --name-status "$PREVIOUS_REF" "$LATEST_REF"
git diff "$PREVIOUS_REF" "$LATEST_REF"

For non-linear history, also inspect:

git log --left-right --graph --oneline "$PREVIOUS_REF...$LATEST_REF"

For the first release, inspect all history reachable from the latest tag and compare its shipped tree with an empty tree:

git log --reverse --date=short --format='%H%x09%ad%x09%s' "$LATEST_REF"
EMPTY_TREE="$(git hash-object -t tree /dev/null)"
git diff --stat "$EMPTY_TREE" "$LATEST_REF"
git diff --name-status "$EMPTY_TREE" "$LATEST_REF"
git diff "$EMPTY_TREE" "$LATEST_REF"

Account for every changed path. Inspect the r

Read more
@kenryu42
Ships withcc-safety-net

A pre-execution guard for AI coding agents. It blocks destructive Git and file system commands, plus common attempts to access sensitive files, before a tool call runs. Supports Amp Code, Antigravity CLI, Claude Code, Codex, Cursor, DeepSeek Harness, Devin CLI, GitHub Copilot CLI, Grok Build, Hermes Agent, Kimi Code, OpenClaw, OpenCode, and Pi.

Stars on GitHub

Momentum

stars in total
1.9k
Star history of kenryu42/cc-safety-net on GitHub, a chart by star-history.com

Other skills on cc-safety-net.

cc-safety-net

cc-safety-net

Operate CC Safety Net: explain why a command was blocked, triage false positives, configure custom rulebooks, manage agent CLI…

More skills from other plugins.

api-security

api-security

Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…

@zhaoxuya520@zhaoxuya520Install Skill
nemoclaw-user-guide

nemoclaw-user-guide

Find official NemoClaw documentation for installation, configuration, operation, or troubleshooting. Also handles requested docs…

nemoclaw13d23k
@nvidia@nvidiaInstall Skill

Questions about release-notes.

Which coding agents can use release-notes?
release-notes installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.