Lightweight semantic release tool with GitHub Copilot release notes. A single binary reimplementation of semantic-release — no Node.js required, works with any project.
- Conventional commit parsing (Angular preset) with full spec compliance
- GitHub Copilot release notes via
ghCLI - Template-based release notes as fallback (no AI key required)
- Custom keyword-to-bump mappings in config
- GitHub release creation with asset uploads (glob patterns)
- GitHub Actions auto-detection (token, repo, branch from env)
- Dry-run mode with full output preview
- Large repo support — streaming git log, batched AI notes, truncated templates
- Safety guards — PR skip, behind-remote detection, auto dry-run outside CI
Download from GitHub Releases.
# Preview without publishing
conventional-release --dry-run
# With Copilot release notes
conventional-release --copilot
# In GitHub Actions (auto-detects token, repo, branch)
conventional-releaseWhen --copilot is set (or ai.enabled: true in config), release notes are generated by calling the GitHub Copilot API via the gh CLI.
- Install the
ghCLI: https://cli.github.com - Authenticate (local only — not needed in GitHub Actions):
gh auth login
- Set
COPILOT_GITHUB_TOKENto a GitHub classic PAT with Copilot access. In GitHub Actions this is typically a PAT stored as a repository secret.
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
run: conventional-release --copilotIf COPILOT_GITHUB_TOKEN is not set, gh falls back to its own authenticated session (GH_TOKEN / GITHUB_TOKEN in Actions).
Create .conventional-release-prompt in your project root to append instructions to the base system prompt sent to Copilot. The file is optional — if it doesn't exist it is silently ignored.
Always write in a friendly tone.
Group breaking changes first and highlight them clearly.
Keep each bullet point to one sentence.
The path can be changed in config via ai.promptFile.
By default Copilot only sees what is explicitly passed in the prompt (version, commits). Pass --repo-context to also grant Copilot shell access to git commands, allowing it to pull richer information about the repository:
conventional-release --copilot --repo-context
# or just --repo-context (implies --copilot)
conventional-release --repo-contextWhen --repo-context is active, Copilot may run any of the following during note generation:
| What Copilot accesses | Why |
|---|---|
git log --oneline |
Full commit history for context |
git diff <tag>..HEAD |
Detailed diff of changes |
git show |
Commit bodies and metadata |
cat README.md |
Project description and context |
These are read-only git commands. No writes, pushes, or network calls are made by the tool access itself.
If --copilot is not set, template-based release notes are generated with no external calls.
Create .conventional-release.yaml in your project root:
tagPrefix: "v"
branch: "main"
firstVersion: "1.0.0"
ai:
enabled: true # same as --copilot flag
promptFile: ".conventional-release-prompt" # custom prompt appended to system prompt (default)
keywords:
big: "major"
problem: "major"
assets:
- "dist/*.tar.gz"
- "dist/*.zip"
commitsPerSection: 50 # max commits per section in template notes (0 = unlimited)CLI flags > environment variables > CI-detected values > config file > defaults.
| Variable | Description |
|---|---|
GITHUB_TOKEN |
GitHub API token for creating releases |
COPILOT_GITHUB_TOKEN |
GitHub token with Copilot access (classic PAT) |
| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview without publishing |
--config |
-c |
Config file path (default .conventional-release.yaml) |
--copilot |
Generate release notes with GitHub Copilot | |
--repo-context |
Allow Copilot to run git commands for possibly more repo aware knowledge (implies --copilot) |
|
--github-token |
GitHub token | |
--no-ci |
Force real release when not in CI | |
--verbose |
-V |
Enable debug logging |
--version |
-v |
Print version |
- Detect CI environment (GitHub Actions)
- Load config (file + env + flags)
- Find latest semver tag
- Collect commits since last tag
- Parse conventional commits
- Determine bump type (major/minor/patch)
- Generate release notes (Copilot via
gh apior template) - Create git tag + GitHub release
- Upload assets
| Type | Bump |
|---|---|
feat |
minor |
fix, perf |
patch |
revert |
patch |
Breaking change (! or BREAKING CHANGE footer) |
major |
Everything else (chore, docs, non-conventional, merge commits, etc.) |
none |
[skip release]or[release skip]in commit message: excluded from analysis- PR builds: automatically skipped (exit 0)
- Behind remote: skipped to prevent conflicts
- Not in CI: auto dry-run (override with
--no-ci)
By default, any branch named main, master, next, next-major, beta, or alpha is a release branch, matching the semantic-release defaults. Maintenance branches (1.x, 2.3.x, etc.) are also detected automatically.
Override with an explicit branches list in config:
branches:
- name: main
- name: next
- name: beta
prerelease: true # produces v1.1.0-beta.1, v1.1.0-beta.2, …
- name: alpha
prerelease: trueA branch named 1.x or 1.1.x restricts releases to that version line:
main: v2.1.0
1.x: v1.5.2 → fix: patch → v1.5.3 (never reaches 2.0.0)
1.1.x: v1.1.9 → fix: patch → v1.1.10 (never reaches 1.2.0)
branches:
- name: beta
prerelease: true # identifier = branch name
- name: rc-candidate
prerelease: "rc" # explicit identifierVersions produced: v2.0.0-beta.1, v2.0.0-beta.2, …, v2.0.0-rc.1, …
A prerelease branch has no version range constraint. Once merged to a release branch, the next run on that branch cuts the stable release.
Change the tag format with tagFormat (default: v${version}):
tagFormat: "${version}" # no prefix: 1.2.3
tagFormat: "app/v${version}" # scoped: app/v1.2.3The format is also used to filter which existing tags are treated as releases for this project.
branches:
- name: "release/*"
channel: "${name}"${name} is substituted with the matched branch name. Non-existent remote branches are silently dropped.
The tool validates the branch config at startup and exits with a descriptive error on:
- Duplicate branch names
- Maintenance branch patterns that overlap
- Prerelease branches sharing the same identifier
- Fewer than 1 or more than 3 release branches
- Invalid branch names (containing
~or^)
MIT