ワンクリックで
release
// Determine the next version, update the marketing site, and run the full release pipeline for Mac or iOS.
// Determine the next version, update the marketing site, and run the full release pipeline for Mac or iOS.
| name | release |
| description | Determine the next version, update the marketing site, and run the full release pipeline for Mac or iOS. |
Cut a new release of Clearly. Mac and iOS ship independently — see CLAUDE.md "Versioning" and "Commit message rule". This skill picks a platform, derives the version from that platform's git tag history, and runs the matching release pipeline.
Ask with mcp__conductor__AskUserQuestion:
If "Both", run the Mac flow end-to-end, then the iOS flow. If either platform fails, stop — do NOT auto-continue to the other.
When running "Both", the un-scoped commit range on iOS overlaps Mac's (older commits show up in both <latest-mac-tag>..HEAD and <latest-ios-tag>..HEAD). If the user already answered "proceed anyway" for those commits on the Mac flow, do NOT re-ask on iOS — inherit the answer. Only ask again if iOS has new un-scoped commits that Mac's range didn't include.
Mac flow:
.env exists at the project root. If not, stop and tell the user:
"Missing .env file. Copy .env.example to .env and fill in APPLE_TEAM_ID, APPLE_ID, and SIGNING_IDENTITY_NAME."notarytool keychain profile AC_PASSWORD works. If not, stop and tell the user to run:
xcrun notarytool store-credentials "AC_PASSWORD" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "<app-specific-password>"
iOS flow:
.env exists and contains APPLE_TEAM_ID.Both flows:
3. Working tree clean (git status --porcelain). If dirty, stop and ask the user to commit or stash.
4. On the main branch. If not, stop.
Pick the tag query and commit filter based on platform:
| Platform | Latest tag query | Commit scope filter |
|---|---|---|
| Mac | git tag -l 'v*' | grep -vE '^ios-' | sort -V | tail -1 | ^\[(mac|shared)\] |
| iOS | git tag -l 'ios-v*' | sort -V | tail -1 | ^\[(ios|shared)\] |
Steps:
git log <latest_tag>..HEAD --oneline --format='%s'
[mac], [ios], [shared], or [chore], stop and list those commits to the user:
"Found commits without a scope prefix. Fix with
git commit --amendorgit rebase -ibefore releasing, or tell me to proceed anyway (commits will fall through the filter and may land in the wrong changelog)." Usemcp__conductor__AskUserQuestionto ask whether to halt or proceed anyway.
feat: or feat( after the scope → minor bumpfix: / chore: / docs: style → patch bumpBREAKING CHANGE or !: → ask the usermcp__conductor__AskUserQuestion:
Confirm before proceeding. Show the tag (v<VERSION> for Mac, ios-v<VERSION> for iOS) and the scoped commit list. Use mcp__conductor__AskUserQuestion:
If "Use a different version", ask for the version. If "Cancel", stop.
Changelog file depends on platform:
CHANGELOG.mdCHANGELOG-iOS.md## [Unreleased] section with content.## [Unreleased] is empty or missing, draft entries from the scoped commit list (same regex used above):
[scope] prefix and any feat:/fix: markers.mcp__conductor__AskUserQuestion.## [Unreleased] to ## [VERSION] - YYYY-MM-DD (today's date).## [Unreleased] above it.Updates depend on platform:
Mac:
project.yml. Update MARKETING_VERSION in all three Mac-side targets: Clearly, ClearlyQuickLook, ClearlyCLI. Do NOT touch Clearly-iOS.website/index.html. Update the class="requires" line — match the existing minimum-macOS wording, do not hardcode a name:
<p class="requires">v<VERSION> · Requires macOS Sequoia or later</p>
git add project.yml website/index.html CHANGELOG.md
git commit -m "[mac] Update marketing site version to v<VERSION>"
git push
iOS:
project.yml. Update MARKETING_VERSION in the Clearly-iOS target only. Do NOT touch the Mac-side targets.git add project.yml CHANGELOG-iOS.md
git commit -m "[ios] Update iOS version to v<VERSION>"
git push
Mac:
./scripts/release.sh <VERSION>
Handles: xcodegen → archive → export → DMG → notarize → staple → git tag v<VERSION> → appcast → push → GitHub Release.
iOS:
./scripts/release-ios.sh <VERSION>
Handles: xcodegen → archive → upload to App Store Connect (→ TestFlight) → git tag ios-v<VERSION> → push tag.
Let each script run to completion. On failure, report the error and stop. Do NOT retry automatically.
iOS stops at TestFlight for now — no App Store submission step.
For Mac, after the Sparkle release succeeds, ask:
If yes:
Output three blocks as raw plain text (no markdown, no code fences) so the user can paste into App Store Connect:
What's New in This Version — Cumulative release notes for the listing body. Structure:
vX.Y.Z — , summarizing that version's theme in a single sentence. Do NOT repeat every bullet — collapse feature sets into a short list. The goal is a scannable version history, not a 200-line dump.• bullets for the current release.Promotional Text (170 characters max) — One sentence. Tone: confident, no fluff.
Description — Full App Store description. Structure:
Label each block so the user knows which ASC field it's for.
./scripts/release-appstore.sh <VERSION>
Handles: strip Sparkle from project.yml → archive → export → upload → wait for processing → create version → set "What's New" from CHANGELOG.md → attach build → submit for App Review.
On failure after upload, the build is already in ASC — tell the user they can finish manually.
Recovery from mid-run abort. The script strips Sparkle keys from Clearly/Info.plist at the top and restores them at the bottom. If it dies between those steps (entitlement check fails, archive fails, upload fails, etc.), the working tree is left dirty with Sparkle keys removed from Info.plist AND the Xcode project pointing at the App Store variant. Before retrying or running any other build, restore with:
git checkout Clearly/Info.plist
xcodegen generate
Then fix the root cause and retry. A clean git status is the signal that recovery is complete.
Ensure all commits are on the remote:
git push
Tell the user:
https://github.com/Shpigford/clearly/releases/tag/v<VERSION>.env is missing or the working tree is dirtyCHANGELOG.md and CHANGELOG-iOS.md in the same release — one platform, one changelogMARKETING_VERSION entries during an iOS release (and vice versa)[mac]/[ios]/[shared]/[chore] prefix) halt the release until resolved