Automates semantic versioning, changelog generation, and releases with Node.js semantic-release v25+ for any language via @semantic-release/exec. Local-first workflows.
From itpnpx claudepluginhub terrylica/cc-skills --plugin itpThis skill is limited to using the following tools:
assets/templates/doppler.yamlassets/templates/github-workflow.ymlassets/templates/package.jsonassets/templates/releaserc-pypi-doppler.jsonassets/templates/releaserc.ymlassets/templates/shareable-config/README.mdassets/templates/shareable-config/index.jsassets/templates/shareable-config/package.jsonreferences/authentication.mdreferences/doc-release-linking.mdreferences/evolution-log.mdreferences/local-release-workflow.mdreferences/major-confirmation.mdreferences/monorepo-support.mdreferences/python.mdreferences/rust.mdreferences/troubleshooting.mdreferences/version-alignment.mdscripts/create_org_config.shscripts/generate-doc-notes.mjsSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Automate semantic versioning and release management using semantic-release v25+ (Node.js) following 2025 best practices. Works with all languages (JavaScript, TypeScript, Python, Rust, Go, C++, etc.) via the @semantic-release/exec plugin. Create shareable configurations for multi-repository setups, initialize individual projects with automated releases, and configure GitHub Actions workflows with OIDC trusted publishing.
Important: This skill uses semantic-release (Node.js) exclusively, NOT python-semantic-release, even for Python projects. Rationale: 23.5x larger community, 100x+ adoption, better future-proofing.
Invoke when:
22,900 GitHub stars - Large, active community
1.9M weekly downloads - Proven adoption
126,000 projects using it - Battle-tested at scale
35+ official plugins - Rich ecosystem
Multi-language support - Works with any language via @semantic-release/exec
Do NOT use python-semantic-release. It has a 23.5x smaller community (975 vs 22,900 stars), ~100x less adoption, and is not affiliated with the semantic-release organization.
Default approach: Run releases locally, not via GitHub Actions.
Primary argument: GitHub Actions is slow
Additional benefits:
package.json, CHANGELOG.md, tags updated immediatelygit pull after releasenpm run release:dry to preview changes before releaseGitHub Actions workflows are provided as optional automation, not the primary method:
gh auth login
# Browser authentication once
# Credentials stored in keyring
# All future releases: zero manual intervention
This is the minimum manual intervention possible for local semantic-release with GitHub plugin functionality.
For multi-account GitHub setups, use mise [env] to set per-directory GH_TOKEN:
# ~/your-project/.mise.toml
[env]
GH_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-accountname') | trim }}"
GITHUB_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-accountname') | trim }}"
This overrides gh CLI's global authentication, ensuring semantic-release uses the correct account for each directory.
See the mise-configuration skill for complete setup.
When .mise.toml has release tasks, prefer mise run over npm run:
| Priority | Condition | Command |
|---|---|---|
| 1 | .mise.toml has [tasks.release:*] | mise run release:version |
| 2 | package.json has scripts.release | npm run release |
| 3 | Global semantic-release | semantic-release --no-ci |
See Python Guide for complete mise workflow example.
CRITICAL: No testing or linting in GitHub Actions. See CLAUDE.md for full policy.
| Forbidden | Allowed |
|---|---|
| pytest, npm test, cargo test | semantic-release |
| ruff, eslint, clippy, prettier | CodeQL, npm audit |
| mypy | Deployment, Dependabot |
semantic-release configuration follows a hierarchical, composable pattern:
Level 1: Skill - ${CLAUDE_PLUGIN_ROOT}/skills/semantic-release/ (Generic templates, system-wide tool)
Level 2: User Config - ~/semantic-release-config/ (@username/semantic-release-config)
Level 3: Organization Config - npm registry (@company/semantic-release-config)
Level 4: Project Config - .releaserc.yml in project root
Level 4 (Project) → overrides → Level 3 (Org) → overrides → Level 2 (User) → overrides → Defaults
semantic-release analyzes commit messages to determine version bumps:
<type>(<scope>): <subject>
feat: → MINOR version bump (0.1.0 → 0.2.0)fix: → PATCH version bump (0.1.0 → 0.1.1)BREAKING CHANGE: or feat!: → MAJOR version bump (0.1.0 → 1.0.0)docs:, chore:, style:, refactor:, perf:, test: → No version bump (by default)Warning: The @semantic-release/release-notes-generator (Angular preset) only includes these types in release notes:
feat: → Features sectionfix: → Bug Fixes sectionperf: → Performance Improvements sectionOther types (docs:, chore:, refactor:, etc.) trigger releases when configured but do NOT appear in release notes.
Recommendation: For documentation changes that should be visible in release notes, use:
fix(docs): description of documentation improvement
This ensures the commit appears in the "Bug Fixes" section while still being semantically accurate (fixing documentation gaps is a fix).
For Claude Code marketplace plugins, every change requires a version bump for users to receive updates.
Option A: Shareable Config (if published)
# .releaserc.yml
extends: "@terryli/semantic-release-config/marketplace"
Option B: Inline Configuration
# .releaserc.yml
plugins:
- - "@semantic-release/commit-analyzer"
- releaseRules:
# Marketplace plugins require version bump for ANY change
- { type: "docs", release: "patch" }
- { type: "chore", release: "patch" }
- { type: "style", release: "patch" }
- { type: "refactor", release: "patch" }
- { type: "test", release: "patch" }
- { type: "build", release: "patch" }
- { type: "ci", release: "patch" }
Result after configuration:
| Commit Type | Release Type |
|---|---|
feat: | minor (default) |
fix:, perf:, revert: | patch (default) |
docs:, chore:, style:, refactor:, test:, build:, ci: | patch (configured) |
Why marketplace plugins need this: Plugin updates are distributed via version tags. Without a version bump, users running /plugin update see no changes even if content was modified.
Pre-release validation: Before running semantic-release, verify releasable commits exist since last tag. A release without version increment is invalid.
Autonomous check sequence:
feat:, fix:, or BREAKING CHANGE: prefixesfeat: or fix: prefix for releasable changes."Commit type selection guidance:
fix: for any change that improves existing behavior (bug fixes, enhancements, documentation corrections that affect usage)feat: for new capabilities or significant additionschore:, docs:, refactor: for changes that truly don't warrant a releaseWhy this matters: A release without version increment creates confusion - users cannot distinguish between releases, package managers may cache old versions, and changelog entries become meaningless.
Trigger: BREAKING CHANGE: footer or feat!: / fix!: prefix in commits.
When MAJOR is detected, this skill runs a 3-phase confirmation workflow:
See MAJOR Confirmation Workflow for complete details including subagent prompts, decision tree, and example output.
Feature (MINOR):
feat: add BigQuery data source support
Bug Fix (PATCH):
fix: correct timestamp parsing for UTC offsets
Breaking Change (MAJOR):
feat!: change API to require authentication
BREAKING CHANGE: All API calls now require API key in Authorization header.
Auto-include doc changes in release notes. Add to .releaserc.yml:
- - "@semantic-release/exec"
- generateNotesCmd: "node plugins/itp/skills/semantic-release/scripts/generate-doc-notes.mjs ${lastRelease.gitTag}"
Detects: ADRs, Design Specs, Skills, Plugin READMEs. See Doc Release Linking.
Note: The
@semantic-release/execplugin uses Lodash templates (${var}). This conflicts with bash default syntax (${VAR:-default}) and subshell syntax ($(cmd)). Preferred fix: removesuccessCmdentirely if your task runner already handles post-release steps. See Troubleshooting: Lodash Template Conflicts.
| Check | Command | Fix |
|---|---|---|
| gh CLI authenticated | gh auth status | gh auth login |
| GH_TOKEN for directory | gh api user --jq '.login' | See Authentication |
| Git remote is HTTPS | git remote get-url origin | git-ssh-to-https |
| semantic-release global | command -v semantic-release | See Troubleshooting |
./scripts/init-project.mjs --project # Initialize current project
./scripts/init-project.mjs --user # Create user-level shareable config
./scripts/init-project.mjs --help # See all options
| Priority | Condition | Commands |
|---|---|---|
| 1 | .mise.toml has release tasks | mise run release:version / mise run release:full |
| 2 | package.json has scripts | npm run release:dry (preview) / npm run release |
| 3 | Global CLI | semantic-release --no-ci |
See Local Release Workflow for the complete 4-phase process.
semantic-release handles versioning. For PyPI publishing, see pypi-doppler skill.
Version pattern (importlib.metadata - never hardcode):
from importlib.metadata import PackageNotFoundError, version
try:
__version__ = version("your-package-name")
except PackageNotFoundError:
__version__ = "0.0.0+dev"
See Python Projects Guide for complete setup including Rust+Python hybrids.
Not recommended as primary (2-5 minute delay). Repository Settings → Actions → Workflow permissions → Enable "Read and write permissions".
| Category | Reference | Description |
|---|---|---|
| Setup | Authentication | HTTPS-first setup, multi-account patterns |
| Workflow | Local Release Workflow | 4-phase process (PREFLIGHT → RELEASE → POSTFLIGHT) |
| Languages | Python Projects | Python + Rust+Python hybrid patterns |
| Rust Projects | release-plz, cargo-rdme README SSoT | |
| Config | Version Alignment | Git tags as SSoT, manifest patterns |
| Monorepo Support | Polyglot monorepo with Pants + mise, pnpm/npm workspaces | |
| Advanced | MAJOR Confirmation | Breaking change analysis workflow |
| Doc Release Linking | Auto-link ADRs/specs in release notes | |
| Help | Troubleshooting | All common issues consolidated |
| Evolution Log | Skill change history |
Cross-skill references:
mise-tasks skill: polyglot-affected - Complete Pants + mise integration guidemise-tasks skill: bootstrap-monorepo - Autonomous polyglot monorepo setuppypi-doppler skill - Local PyPI publishing with DopplerAfter modifying THIS skill (semantic-release):
bun scripts/validate-plugins.mjsnpm run release:dry to verify no regressions| Issue | Cause | Solution |
|---|---|---|
| No release created | No releasable commits since tag | Use feat: or fix: prefix for version-bumping commits |
| Wrong version bump | Commit type mismatch | Check conventional commit format and releaseRules |
| GitHub release not created | Missing GH_TOKEN or permissions | Check token is set and has repo scope |
| CHANGELOG not updated | Missing changelog plugin | Add @semantic-release/changelog to plugins array |
| "Authentication failed" | HTTPS vs SSH remote mismatch | Convert to HTTPS: git-ssh-to-https |
| semantic-release not found | Not installed globally | npm install -g semantic-release |
| Gatekeeper blocks on macOS | Unsigned Node files | See Troubleshooting |
| dry-run shows no changes | Already released at HEAD | Make new commits before running release |
| Multi-account token conflict | Wrong GH_TOKEN for directory | Configure mise [env] per-directory token |
After this skill completes, check before closing:
Only update if the issue is real and reproducible — not speculative.