semantic-release

Automate versioning with Node.js semantic-release v25+. TRIGGERS - npm run release, version bump, changelog, conventional commits, release automation.

terrylica/cc-skills213 installsMITSynced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: semantic-release
description: Automate versioning with Node.js semantic-release v25+. TRIGGERS - npm run release, version bump, changelog, conventional commits, release automation.
license: MIT
---

# semantic-release

> **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.

## Overview

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.

## When to Use This Skill

Invoke when:

- Setting up local releases for a new project (any language)
- Creating shareable semantic-release configuration for organization-wide use
- Migrating existing projects to 2025 semantic-release patterns
- Troubleshooting semantic-release setup or version bumps
- Setting up Python projects (use Node.js semantic-release, NOT python-semantic-release)
- Configuring GitHub Actions (optional backup, not recommended as primary due to speed)
- Rust workspaces using release-plz (see [Rust reference](./references/rust.md))

## Why Node.js semantic-release

**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.

---

## Release Workflow Philosophy: Local-First

**Default approach: Run releases locally, not via GitHub Actions.**

### Why Local Releases

**Primary argument: GitHub Actions is slow**

- ⏱️ GitHub Actions: 2-5 minute wait for release to complete
- ⚡ Local release: Instant feedback and file updates
- 🔄 Immediate workflow continuity - no waiting for CI/CD

**Additional benefits:**

- ✅ **Instant local file sync** - `package.json`, `CHANGELOG.md`, tags updated immediately
- ✅ **No pull required** - Continue working without `git pull` after release
- ✅ **Dry-run testing** - `npm run release:dry` to preview changes before release
- ✅ **Offline capable** - Can release without CI/CD dependency
- ✅ **Faster iteration** - Debug release issues immediately, not through CI logs

### GitHub Actions: Optional Backup Only

GitHub Actions workflows are provided as **optional automation**, not the primary method:

- Use for team consistency if required
- Backup if local environment unavailable
- **Not recommended as primary workflow due to speed**

### Authentication Setup

```bash
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.

### Multi-Account Authentication via mise [env]

For multi-account GitHub setups, use mise `[env]` to set per-directory GH_TOKEN:

```toml
# ~/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](../mise-configuration/SKILL.md#github-token-multi-account-patterns) for complete setup.

### mise Task Detection

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](./references/python.md#mise-4-phase-workflow) for complete mise workflow example.

### GitHub Actions Policy

**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 |

---

## Separation of Concerns (4-Level Architecture)

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

### Configuration Precedence

```
Level 4 (Project) → overrides → Level 3 (Org) → overrides → Level 2 (User) → overrides → Defaults
```

---

## Conventional Commits Format

semantic-release analyzes commit messages to determine version bumps:

```
<type>(<scope>): <subject>
```

### Version Bump Rules (Default)

- `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)

### Release Notes Visibility (Important)

**Warning**: The `@semantic-release/release-notes-generator` (Angular preset) only includes these types in release notes:

- `feat:` → **Features** section
- `fix:` → **Bug Fixes** section
- `perf:` → **Performance Improvements** section

Other 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).

### Marketplace Plugin Configuration (Always Bump)

For Claude Code marketplace plugins, **every change requires a version bump** for users to receive updates.

**Option A: Shareable Config (if published)**

```yaml
# .releaserc.yml
extends: "@terryli/semantic-release-config/marketplace"
```

**Option B: Inline Configuration**

```yaml
# .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.

### MANDATORY: Every Release Must Increment Version

**Pre-release validation**: Before running semantic-release, verify releasable commits exist since last tag. A release without version increment is invalid.

**Autonomous check sequence**:

1. List commits since last tag: compare HEAD against latest version tag
2. Identify commit types: scan for `feat:`, `fix:`, or `BREAKING CHANGE:` prefixes
3. If NO releasable commits found → **STOP** - do not proceed with release
4. Inform user: "No version-bumping commits since last release. Use `feat:` or `fix:` prefix for releasable changes."

**Commit type selection guidance**:

- Use `fix:` for any change that improves existing behavior (bug fixes, enhancements, documentation corrections that affect usage)
- Use `feat:` for new capabilities or significant additions
- Reserve `chore:`, `docs:`, `refactor:` for changes that truly don't warrant a release

**Why 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.

### MAJOR Version Breaking Change Confirmation

**Trigger**: `BREAKING CHANGE:` footer or `feat!:` / `fix!:` prefix in commits.

When MAJOR is detected, this skill runs a **3-phase confirmation workflow**:

1. **Detection**: Scan commits for breaking change markers
2. **Analysis**: Spawn 3 parallel subagents (User Impact, API Compat, Migration)
3. **Confirmation**: AskUserQuestion with proceed/downgrade/abort options

See [MAJOR Confirmation Workflow](./references/major-confirmation.md) for complete details including subagent prompts, decision tree, and example output.

### Examples

**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.
```

---

## Documentation Linking

Auto-include doc changes in release notes. Add to `.releaserc.yml`:

```yaml
- - "@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](./references/doc-release-linking.md).

> **Note**: The `@semantic-release/exec` plugin uses Lodash templates (`${var}`). This conflicts with bash default syntax (`${VAR:-default}`) and subshell syntax (`$(cmd)`). **Preferred fix**: remove `successCmd` entirely if your task runner already handles post-release steps. See [Troubleshooting: Lodash Template Conflicts](./references/troubleshooting.md#semantic-releaseexec-lodash-template-conflicts).

---

## Quick Start

### Prerequisites

| Check                   | Command                       | Fix                                                                                       |
| ----------------------- | ----------------------------- | ----------------------------------------------------------------------------------------- |
| gh CLI authenticated    | `gh auth status`              | `gh auth login`                                                                           |
| GH_TOKEN for directory  | `gh api user --jq '.login'`   | See [Authentication](./references/authentication.md)                                      |
| Git remote is HTTPS     | `git remote get-url origin`   | `git-ssh-to-https`                                                                        |
| semantic-release global | `command -v semantic-release` | See [Troubleshooting](./references/troubleshooting.md#macos-gatekeeper-blocks-node-files) |

### Initialize Project

```bash
./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
```

### Run Release

| 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](./references/local-release-workflow.md) for the complete 4-phase process.

### Python Projects

semantic-release handles versioning. For PyPI publishing, see [`pypi-doppler` skill](../pypi-doppler/SKILL.md).

**Version pattern** (importlib.metadata - never hardcode):

```python
from importlib.metadata import PackageNotFoundError, version
try:
    __version__ = version("your-package-name")
except PackageNotFoundError:
    __version__ = "0.0.0+dev"
```

See [Python Projects Guide](./references/python.md) for complete setup including Rust+Python hybrids.

### GitHub Actions (Optional)

Not recommended as primary (2-5 minute delay). Repository Settings → Actions → Workflow permissions → Enable "Read and write permissions".

---

## Reference Documentation

| Category      | Reference                                                        | Description                                              |
| ------------- | ---------------------------------------------------------------- | -------------------------------------------------------- |
| **Setup**     | [Authentication](./references/authentication.md)                 | HTTPS-first setup, multi-account patterns                |
| **Workflow**  | [Local Release Workflow](./references/local-release-workflow.md) | 4-phase process (PREFLIGHT → RELEASE → POSTFLIGHT)       |
| **Languages** | [Python Projects](./references/python.md)                        | Python + Rust+Python hybrid patterns                     |
|               | [Rust Projects](./references/rust.md)                            | release-plz, cargo-rdme README SSoT                      |
| **Config**    | [Version Alignment](./references/version-alignment.md)           | Git tags as SSoT, manifest patterns                      |
|               | [Monorepo Support](./references/monorepo-support.md)             | Polyglot monorepo with Pants + mise, pnpm/npm workspaces |
| **Advanced**  | [MAJOR Confirmation](./references/major-confirmation.md)         | Breaking change analysis workflow                        |
|               | [Doc Release Linking](./references/doc-release-linking.md)       | Auto-link ADRs/specs in release notes                    |
| **Help**      | [Troubleshooting](./references/troubleshooting.md)               | All common issues consolidated                           |
|               | [Evolution Log](./references/evolution-log.md)                   | Skill change history                                     |

**Cross-skill references**:

- [`mise-tasks` skill: polyglot-affected](../mise-tasks/references/polyglot-affected.md) - Complete Pants + mise integration guide
- [`mise-tasks` skill: bootstrap-monorepo](../mise-tasks/references/bootstrap-monorepo.md) - Autonomous polyglot monorepo setup
- [`pypi-doppler` skill](../pypi-doppler/SKILL.md) - Local PyPI publishing with Doppler

---

## Post-Change Checklist

After modifying THIS skill (semantic-release):

1. [ ] SKILL.md and references remain aligned
2. [ ] New references documented in Reference Documentation table
3. [ ] All referenced files in references/ exist
4. [ ] Append changes to [evolution-log.md](./references/evolution-log.md)
5. [ ] Validate with `bun scripts/validate-plugins.mjs`
6. [ ] Run `npm run release:dry` to verify no regressions

---

## Troubleshooting

| 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](./references/troubleshooting.md)   |
| 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                 |


## Post-Execution Reflection

After this skill completes, check before closing:

1. **Did the command succeed?** — If not, fix the instruction or error table that caused the failure.
2. **Did parameters or output change?** — If the underlying tool's interface drifted, update Usage examples and Parameters table to match.
3. **Was a workaround needed?** — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.

Only update if the issue is real and reproducible — not speculative.

More Writing & Documentation skills

paper-context-resolver

lllllllama/rigorpilot-skills

Rigor Paper Context helper for README-first deep learning repo reproduction. Use only when the README and repository files leave a narrow reproduction-critical gap and the task is to resolve a specific paper detail such as dataset split, preprocessing, evaluation protocol, checkpoint mapping, or runtime assumption from primary paper sources while recording conflicts. Do not use for general paper summary, repo scanning, environment setup, command execution, title-only paper lookup, or replacing README guidance by default.

450.8k

repo-intake-and-plan

lllllllama/rigorpilot-skills

Rigor Intake helper for README-first deep learning repo reproduction. Use when the task is specifically to scan a repository, read the README and common project files, extract documented commands, classify inference, evaluation, and training candidates, and return the smallest trustworthy reproduction plan to the main orchestrator. Do not use for environment setup, asset download, command execution, final reporting, paper lookup, or end-to-end orchestration.

450.0k

minimal-run-and-audit

lllllllama/rigorpilot-skills

Rigor Run skill for README-first deep learning repo reproduction. Use when the task is specifically to capture or normalize evidence from the selected smoke test or documented inference or evaluation command and write standardized `repro_outputs/` files, including patch notes when repository files changed. Do not use for training execution, initial repo intake, generic environment setup, paper lookup, target selection, hidden scientific-meaning changes, or end-to-end orchestration by itself.

449.9k

← All Writing & Documentation skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY