Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Cut Release

ASecurity

Cut a new TMDb release — work out the next SemVer version from the evidence, do the pre-tag housekeeping a tag would otherwise freeze in place, draft release notes, then tag and publish the GitHub release. Presents the version (with its reasoning) and the full notes for approval and STOPS; nothing is tagged or published until you say go.

176 stars
0 votes
0 copies
1 views
Added 9/20/2026
developmentgoswiftbashtestinggitapidatabasesecurity

Works with

api

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add adamayoung/TMDb --skill cut-release --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cut Release?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Cut Release
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adamayoung-cut-release/badge)](https://www.skillsdirectory.com/skills/adamayoung-cut-release)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: cut-release
description: Cut a new TMDb release — work out the next SemVer version from the evidence, do the pre-tag housekeeping a tag would otherwise freeze in place, draft release notes, then tag and publish the GitHub release. Presents the version (with its reasoning) and the full notes for approval and STOPS; nothing is tagged or published until you say go.
---

# Cut Release

Takes `main` from "a pile of merged PRs" to "a tagged, published release".

**This skill is never headless.** Every other skill in this repo may decide for
itself; this one may not. A tag is the one artifact consumers resolve against,
and publishing one is effectively irreversible: SwiftPM hands a new **minor or
patch** to everyone inside the current `from:` range the moment it exists, a new
**major** reaches everyone who has since bumped, and deleting a tag does not
un-fetch it from anyone who already resolved. Phases 1–5 are read-only and local.
Phase 6 is a **hard stop**. Phases 7–9 run only on an explicit go-ahead.

If invoked with no human able to answer, run to the hard stop, print the summary,
and exit. Do not tag.

## Phase 1 — Preflight

Stop on any failure; report which one and what to do.

- On `main`, clean tree, in sync with `origin/main`
  (`git status --porcelain`, `git rev-list --count main..origin/main`).
- `git fetch --tags`; establish the last release:
  `git tag --sort=-v:refname | head -1`.
- CI is **green on the current `main` tip**:
  `gh api repos/adamayoung/TMDb/commits/<sha>/check-runs`. This is the *entry*
  check — the commit that actually gets tagged does not exist yet (Phase 7
  creates it), and Phase 7 re-checks that one. Starting from a red `main` just
  means finding out later.
- There is something to release — at least one commit since the last tag that is
  not purely a tag-housekeeping commit.

## Phase 2 — Work out the version

Two independent signals. They must agree, or you stop.

**Signal A — the CHANGELOG (authoritative).** The open `## [X.Y.Z]` section at
the top (no date = unreleased) is the *proposal*. Count `**Breaking:**` markers
inside it, and read the section headings:

- any `**Breaking:**` → **major**
- otherwise any `### Added` content → **minor**
- otherwise (`### Fixed` / `### Changed` only) → **patch**

**Signal B — the commits (cross-check).** `git log <lasttag>..HEAD`, bucketed by
gitmoji. Consumer-visible: `✨` feature, `🐛` fix, `♻️` refactor, `🔒` security,
`⚡️` perf. Not consumer-visible: `🔧` chore, `📝` docs, `👷` CI, `✅` tests,
`📦` build. Count multibyte-safely — `sort | uniq -c` over emoji collapses
distinct ones in a non-UTF-8 locale and will hand you a confidently wrong tally.

**Gitmoji alone is not enough to pick a version in this repo, and you must not
try.** A `🐛` here is routinely source-breaking: "🐛 Surface task cancellation as
`TMDbError.cancelled`" (PR #433) was filed as a fix and added an enum case, which
breaks every exhaustive `switch` downstream. Signal B exists to catch *omissions*
from the CHANGELOG, not to compute the bump.

Then reconcile:

- The proposed section heading must match what Signal A computes from its own
  content. A section headed `[20.0.0]` containing no `**Breaking:**` is a
  mis-labelled release — **stop and report**, do not silently downgrade it.
- `knowledge/next-major.md`'s status line names the open window. If it disagrees
  with the CHANGELOG heading, stop.
- The computed tag must not already exist.

**Coverage check.** Every commit since the last tag that touches `Sources/` and
carries a consumer-visible gitmoji should be represented somewhere in the open
CHANGELOG section. List any that are not. This is the check that catches a real
change shipping invisibly; the not-consumer-visible buckets legitimately have no
CHANGELOG entry and are not flagged.

## Phase 3 — Pre-tag housekeeping

**Branch first.** `git checkout -b chore/prepare-<version>-release`. Phase 1 put
you on a clean `main`, and CLAUDE.md forbids editing there — but the practical
reason is re-entrancy: if the run is abandoned at the Phase 6 stop, edits made on
`main` leave a dirty tree that fails this skill's *own* Phase 1 preflight on the
next attempt. Branching now costs nothing and makes an abort free.

**A tag snapshots the tree**, so anything that says "unreleased" is frozen
saying it, forever, inside the very release it describes. These four are not
optional, and all of them were needed for 19.0.0 (PR #406):

1. **`README.md` install snippet.** `from: "<previous major>"` resolves to
   `>=prev, <prev+1` — on a **major**, readers following the README would never
   resolve to the new version at all. Bump it. (This is the one with real user
   impact; the other three are hygiene.)

   `Scripts/check-readme-version.py` enforces this from `make lint` and CI: the
   snippet must match either the newest **dated** CHANGELOG section (the last
   release) or the newest **undated** one (the release being prepared). That
   second arm exists so this housekeeping PR is not blocked by the tag it is
   preparing — bump the snippet and date the section in the same commit and both
   arms stay satisfied. Forget the bump entirely and the check goes red on the
   next PR after the release.
2. **`CHANGELOG.md`.** Date the section — `## [X.Y.Z] - YYYY-MM-DD` — and add
   the link definition at the foot:
   `[X.Y.Z]: https://github.com/adamayoung/TMDb/releases/tag/X.Y.Z`. Check the
   *previous* version's definition is there too; they have been missed before.
3. **`knowledge/next-major.md`.** Rewrite the status line: this version has
   shipped, and the next major's window is now open. Remove every backlog entry
   that shipped in this release (the file's own rule). An entry left behind
   claiming to await a window that just closed is invisible exactly when it
   should fire.
4. **ADR statuses.** Every `knowledge/decisions/*.md` reading
   `Accepted (in X.Y.Z, unreleased)` becomes `Accepted (shipped in X.Y.Z)` — in
   the file **and** in the `decisions/README.md` index. Leave
   `unreleased — tooling only` ADRs alone; they describe `.claude/` machinery
   with no library impact and no version to ship in.

Make these edits on the branch but **do not commit yet** — they are shown at the
hard stop, and they go up as a PR, never straight to `main`.

## Phase 4 — Draft the release notes

Structure, in this order:

1. **The opener.** Two or three sentences, warm and a little funny. Write a new
   one every time — see *Voice* below.
2. **Upgrade impact**, if this is a major or has any `**Breaking:**` entry. What
   breaks, and the one-line fix for each. This sits *above* the feature list.
3. **What's new** / **What's fixed** / **What changed** — consumer-facing prose,
   drawn from the CHANGELOG (which is already written for humans), not from
   commit subjects.
4. **Commits**, inside a `<details>` block: every commit since the last tag, one
   line each — `<sha> <subject>`. Collapsed, because it is a reference, not a
   read.
5. **Full Changelog** compare link:
   `https://github.com/adamayoung/TMDb/compare/<lasttag>...<newtag>`.

### Voice

Slack's iOS notes are the reference: they open with something human, and they
never pretend a bugfix release is a moon landing. Aim for a colleague writing
to other developers — dry, specific, occasionally silly, never markety.

- Good: naming the actual absurdity. *"This release is mostly about a movie
  database telling us, with total confidence, that Bryan Cranston has never been
  in a TV series."*
- Good: cheerful understatement. *"Eighteen of twenty tagged images were quietly
  going in the bin. They are no longer going in the bin."*
- Avoid: "We're excited to announce", "packed with", "🚀", exclamation marks in
  rows, and any claim the diff does not support.
- Avoid: whimsy about the *breaking* part. Joke about the bug you fixed, not
  about the work you have just made someone do. If this release breaks builds,
  the opener stays light but stays short — then get straight to the impact.

Length: the opener is 2–3 sentences. If it needs a fourth, it is a paragraph,
and paragraphs are what section 3 is for.

## Phase 5 — Assemble the summary

Put together, for one message:

- **Version** and the **reasoning** — the deciding evidence, not a recitation.
  "Major: 14 `**Breaking:**` entries, including four public enums gaining cases"
  beats "there were breaking changes".
- Anything Signal B flagged as missing from the CHANGELOG.
- The four housekeeping edits, as a diff summary.
- **The complete release notes**, verbatim as they will be published.

## Phase 6 — STOP

Present the summary and **wait**. Do not tag, push, or publish anything.

Ask plainly whether to go ahead. Treat anything short of a clear yes as a no —
"looks good" about the *notes* is not approval to *publish*. If the answer is a
change request, apply it and return to this phase; the gate re-arms every time.

## Phase 7 — Land the housekeeping

Only after approval. The branch already exists from Phase 3.

Commit the Phase 3 edits as `🔧 Prepare the <version> release`, open the PR via
`/pr`, and let its CI run. The narrowed docs/config gate usually applies here —
the diff is Markdown only — but `/pr` owns that call; do not pre-empt it.

Merge once green.

**Then wait for `main`'s own run.** `ci.yml` triggers on push to `main` with
`**/*.md` among its paths, so the squashed merge commit gets a CI run of its
own — a *different* commit from the PR head, and the one the tag will point at.
Phase 1's "green on the exact commit being tagged" means this run, not the PR's.
Poll it:

```bash
gh api repos/adamayoung/TMDb/commits/$(git rev-parse HEAD)/check-runs \
  --jq '[.check_runs[] | {name, status, conclusion}]'
```

Red or still running → do not tag. This is the cheapest place in the whole skill
to be patient.

## Phase 8 — Tag

On the merged `main`, at the housekeeping commit:

```bash
git checkout main && git pull
git tag -a <version> -m "<version>"
git push origin <version>
```

Annotated, not lightweight — a release tag should carry an author and a date.

**Regenerate the commit list before publishing.** The notes were drafted in
Phase 4, before the housekeeping merge existed — so their `<details>` list is
short by exactly the commit being tagged, while the compare link below it
includes it. Re-run the log against the new tag and refresh that block.

## Phase 9 — Publish

```bash
gh release create <version> --repo adamayoung/TMDb \
  --title "<version>" --notes-file <path> --verify-tag --latest
```

`--verify-tag` refuses to invent a tag that does not exist, which is what turns a
typo into a failed command instead of a phantom release.

Then confirm: print the release URL, and re-read the published notes once to
check nothing was mangled in transit.

## After

Report the tag, the release URL, and what the next window is now open for. If any
`knowledge/next-major.md` entries were deliberately carried forward rather than
shipped, name them — that is the moment someone can still object.

## Failure modes worth knowing

- **A red tag.** Tagging a commit whose CI never passed. Phase 1 exists for this;
  do not skip it because "the PR was green" — the merge commit is a different
  commit, and it gets its own run.
- **Assuming a bad tag is cheap to undo.** Two active tag rulesets cover `~ALL`
  tags with `creation`, `update` and `deletion` rules. The repository-role bypass
  means the owner *can* force it, but nothing here is a casual `git push --delete`
  — and SwiftPM consumers who already resolved the version are unaffected by any
  of it. Get it right going in.
- **A frozen "unreleased".** Skipping Phase 3 ships ADRs and a `next-major.md`
  that insist, inside the release, that the release has not happened.
- **A README nobody can follow.** The `from:` bump is invisible in testing and
  breaks discovery for every new consumer on a major.
- **Version invented from commits.** Deriving the bump from gitmoji rather than
  the CHANGELOG will under-call a major in this repo, roughly every time.

Attribution

adamayoungadamayoung
View sourceMore from adamayoung →
SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284972 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →