Releasing
Cut a release with no “what number is this” step — your commit messages decide the version. Ongoing merges don’t ship anything; you release deliberately, by merging one pull request when a batch of work is ready.
cckit follows Semantic Versioning driven by Conventional Commits. The version number is automatic — the commit messages since the last tag pick it — and the release is cut by release-please, which keeps a single Release PR open and up to date. Merging that PR is the release.
How the version is decided
Section titled “How the version is decided”release-please reads every Conventional Commit since the last tag and picks the highest bump (the local cckit release fallback applies the same rules via scripts/lib/version-bump.sh):
| Commit | Bump | Example |
|---|---|---|
feat!: / type!: / a BREAKING CHANGE: footer | major | 1.4.2 → 2.0.0 |
feat: | minor | 1.4.2 → 1.5.0 |
fix: / perf: / refactor: / revert: / anything else | patch | 1.4.2 → 1.4.3 |
| no commits since the tag | none | no release |
Check what the next version would be at any time:
cckit release --next # or: scripts/lib/version-bump.sh --nextCutting a release (merge the Release PR)
Section titled “Cutting a release (merge the Release PR)”.github/workflows/release-please.yml runs on every push to main. It doesn’t ship anything on its own — it keeps a single Release PR open (titled chore(main): release X.Y.Z) and rewrites it as more work lands. So you can merge, merge, merge, then release once by merging that PR when the batch is ready.
-
Work reaches
main. Feature branches merge intodevelop; when you’re ready,developmerges intomainvia PR. (mainis protected — releases only.) -
release-please opens/updates the Release PR — it computes the bump from the commits since the last tag, bumps all four version surfaces (
package.json,docs-site/package.json,.claude-plugin/plugin.json,cckit.config.json) plusFormula/cckit.rb, and regeneratesCHANGELOG.md. Review it whenever; nothing ships yet. -
Merge the Release PR. That merge is the release: release-please tags
vX.Y.Zand cuts the GitHub Release, then thepublishjob pushes to npm and bumps the Homebrew tap automatically.
A batch with only chore/docs noise produces no Release PR (bump=none → nothing to release). Because the release is a single PR merge, two feature PRs merging at once can no longer race each other into a corrupted tag.
Publishing to npm + Homebrew
Section titled “Publishing to npm + Homebrew”Publishing is automatic once the Release PR is merged — the publish job in release-please.yml runs npm publish and bumps the jeiemgi/homebrew-cckit tap (recomputing the formula sha256). Each channel is gated on a repo secret and simply skipped if the secret is absent:
NPM_TOKEN— npm Automation token (npmjs.com → Access Tokens → Automation).- Homebrew tap auth — either of:
- GitHub App (preferred) —
HOMEBREW_APP_ID+HOMEBREW_APP_PRIVATE_KEYfor an app with Contents: write installed onhomebrew-cckit. The workflow mints a short-lived, tap-scoped token per run — nothing to expire or rotate by hand. HOMEBREW_TAP_TOKEN— legacy fallback: a PAT with push access to the tap repo (contents:write). Used only when the app secrets are absent.
- GitHub App (preferred) —
Local fallback
Section titled “Local fallback”scripts/publish.sh (aliased as cckit release) still cuts a release from your machine if you ever need to bypass CI. It is dry-run by default — nothing changes until you add --publish.
cckit release X.Y.Z # DRY RUN — prints the full plan, changes nothingcckit release X.Y.Z --publish # tag + GitHub release + Homebrew formula + npm (needs tokens)Commit message rules (the contract)
Section titled “Commit message rules (the contract)”- Every commit on a PR uses a Conventional Commit subject:
type(scope): summary. - Breaking changes use
!after the type/scope or aBREAKING CHANGE:footer — never a silent major. - One logical change per commit so the generated release notes read cleanly.
Independent, educational project — not affiliated with or endorsed by Anthropic. Claude and Claude Code are trademarks of Anthropic PBC. Disclaimer & trademarks ·
From Mexico with love by josegtz