Commands
Releasaurus operates entirely through forge platform APIs — no local clone required — so every command can run from any machine with network access to your forge. An optional hybrid mode uses a local clone for git operations.
The core workflow is two commands:
# 1. Prepare: analyze commits, bump versions, write changelog, open a PR
releasaurus release-pr --repo "https://github.com/owner/repo"
# 2. Review and merge the PR in your forge's UI, then publish:
releasaurus release --repo "https://github.com/owner/repo"
release-direct replaces both steps for repos that don’t want a review PR.
start-next and get are optional helpers covered below.
release-pr
Analyzes commits since the last release, determines the version bump
(patch/minor/major) from conventional commits, updates version files (if
a release_type is configured), generates the changelog, and creates or
updates a release pull request.
# All packages
releasaurus release-pr --repo "https://github.com/owner/repo"
# A single package in a monorepo
releasaurus release-pr --package my-pkg \
--repo "https://github.com/owner/repo"
Supports prereleases, dry-run, and the overrides below.
release
Run after the release PR is merged. Validates the release commit, creates and pushes the git tag, and publishes the release on your forge. Reads the release notes directly from the merged PR body (see Editing Release Notes).
# All packages with merged release PRs
releasaurus release --repo "https://github.com/owner/repo"
# A single package
releasaurus release --package my-pkg \
--repo "https://github.com/owner/repo"
release-direct
Does everything release-pr and release do together, in a single pass
and with no pull request: analyzes commits, bumps versions, writes the
changelog, commits directly to the base branch, tags that commit, and
publishes the release.
# All packages
releasaurus release-direct --repo "https://github.com/owner/repo"
# A single package in a monorepo
releasaurus release-direct --package my-pkg \
--repo "https://github.com/owner/repo"
Use it for trunk-based or fully automated releases where a review step
adds nothing — internal tools, nightly builds, or CI that already gates
on the merge into the base branch. Prefer release-pr + release
whenever you want the version bump and changelog reviewed before they
land.
In a monorepo, every package released in a run shares a single release
commit, and each package’s tag points at that commit. Setting
separate_pull_requests gives
you one commit per package instead, matching how that setting splits
release PRs.
Confirmation
Because there is no PR to review and no way to finish a partially failed
run by repeating it, release-direct stops and asks you to type yes
before it changes anything:
release-direct will make changes that re-running it cannot undo.
repository: https://github.com/owner/repo
branch: main
It commits the version bumps and changelog to that branch, creates and
pushes the release tag(s), and publishes the release(s) on your forge.
No pull request is created and there is no review step.
Type 'yes' to continue:
Pass --auto-approve to skip it. CI must pass --auto-approve — when
stdin is not a terminal the command refuses to run rather than hang or
guess, and tells you to add the flag.
--dry-run never prompts, since it writes nothing.
Warning: This is a separate, out-of-band flow — it never creates a release PR. Do not mix it with the
release-pr/releaseworkflow on the same packages: the tagrelease-directcreates will collide with the onereleaselater tries to create for the merged PR. As a safety net,release-directrefuses to run if a package it is about to release still has a merged release PR waiting to be tagged, but it cannot detect every ordering.
Note: Like
start-next, this commits directly to your base branch, so your branch protection rules must permit it. Unlikerelease, it is not driven byauto_start_nextand will not trigger a follow-up patch bump.
Supports dry-run and the overrides below. Run
it with --dry-run first to see exactly what it would commit, tag, and
publish.
start-next
Bumps the patch version for each previously-tagged package and commits
the manifest changes directly to the base branch as a chore commit.
It does not open PRs or create tags, and skips packages that have never
been tagged. Use it right after a release to keep manifest versions ahead
of the last release.
# All previously-tagged packages
releasaurus start-next --repo "https://github.com/owner/repo"
# Specific packages only
releasaurus start-next --repo "https://github.com/owner/repo" \
--packages pkg-a,pkg-b
Note: This commits directly to your base branch. Ensure your branch protection rules permit it. It can also run automatically after
release— seeauto_start_next.
get
Queries release information as JSON without making any changes — useful
for debugging version detection and for building custom notifications.
(show is kept as an alias.)
get next-release
Projects the next release for each package as JSON.
releasaurus get next-release --repo "https://github.com/owner/repo"
# Single package, or write to a file
releasaurus get next-release --package my-pkg --out-file releases.json \
--repo "https://github.com/owner/repo"
get current-release
Returns the most recent release for each package (packages without a release are omitted).
releasaurus get current-release --repo "https://github.com/owner/repo"
get release
Returns the data for an existing tag — tag, sha, and notes.
releasaurus get release --tag v1.0.0 \
--repo "https://github.com/owner/repo"
get notes
Re-renders release notes from a get next-release JSON file using your
configured Tera template. This lets you transform the data (for example,
replacing author names with Slack IDs) before producing final notes.
(recompiled-notes is kept as an alias.)
# 1. Capture release data
releasaurus get next-release --out-file releases.json \
--repo "https://github.com/owner/repo"
# 2. Transform it however you like (custom script), then re-render:
releasaurus get notes --file releases.json \
--repo "https://github.com/owner/repo"
Output is a JSON array of { name, notes } objects.
Global Options & Forge Selection
These apply to every command:
| Flag | Env fallback | Description |
|---|---|---|
--repo <url> | RELEASAURUS_REPO | Repository URL |
--forge <forge> | RELEASAURUS_FORGE | Forge type (see below) |
--token <token> | RELEASAURUS_<FORGE>_TOKEN, <FORGE>_TOKEN | Auth token |
--local-path <path> | RELEASAURUS_LOCAL_PATH | Local clone for hybrid mode |
--base-branch <branch> | — | Override the base branch |
--debug | RELEASAURUS_DEBUG | Verbose logging |
--config | RELEASAURUS_CONFIG | Custom file path location |
Available forge types: github, gitlab, gitea, forgejo,
azure-devops (experimental), and local (testing). For the full list
of token variables and required scopes, see the
Configuration Reference.
Automatic forge inference
When --repo points at a recognized cloud host, --forge can be
omitted:
| Host | Inferred forge |
|---|---|
github.com | github |
gitlab.com | gitlab |
gitea.com | gitea |
codeberg.org | forgejo |
dev.azure.com | azure-devops |
Self-hosted instances (e.g. https://gitlab.company.com/...) and
--forge local always require the flag, since the host alone can’t
identify the forge software.
Testing Modes
Three ways to run safely or against a local checkout.
Dry-Run Mode
Performs all analysis and validation and logs exactly what would
happen, but makes no changes — no branches, PRs, tags, or releases.
Dry-run automatically enables debug logging (output is prefixed
dry_run:).
releasaurus release-pr --dry-run --repo "https://github.com/owner/repo"
# Or via environment variable
export RELEASAURUS_DRY_RUN=true
Local Repository Mode
--forge local reads commits, tags, and files from your working
directory and never contacts a remote forge — ideal for validating a
releasaurus.toml change before pushing. No token required.
releasaurus release-pr --forge local --repo "."
# Or from a specific path
releasaurus release-pr --forge local --repo "/path/to/repo"
Hybrid Mode (Local Git + Remote Forge)
--local-path performs git operations (reading commits/tags/files,
creating branches, committing, pushing) against a local clone, while
still creating real PRs and releases via the forge API. Use it when you
already have a checkout and want to avoid repeated API calls for data
gathering. A forge token is still required.
releasaurus release-pr \
--repo "https://github.com/owner/repo" \
--token "$GITHUB_TOKEN" \
--local-path /path/to/checkout
CI fetch depth: in hybrid mode the local checkout must include full history and all tags back to the previous release. Most CI systems shallow-clone by default — set
fetch-depth: 0(GitHub/Gitea Actions) orGIT_DEPTH: 0(GitLab CI), or rungit fetch --unshallow. See CI/CD Integration for per-platform setup.
Configuration Overrides
Override config from the command line without editing
releasaurus.toml — handy for testing, one-off releases, and per-branch
CI settings.
| Flag | Effect |
|---|---|
--base-branch <branch> | Override the base branch |
--tag-prefix <prefix> | Global tag prefix for all packages |
--version-type <value> | Global version type for all packages |
--prerelease-suffix <suffix> | Global prerelease suffix (empty "" disables) |
--prerelease-strategy <versioned|static> | Global prerelease strategy |
--skip-sha <sha> | Skip a commit by SHA prefix (repeatable) |
--reword <sha>=<message> | Rewrite a commit message (repeatable) |
--set-package <pkg>.<property>=<value> | Per-package override (repeatable) |
--set-package takes precedence over all other overrides and config.
Supported properties: tag_prefix, versioning.version_type,
versioning.prerelease.suffix, versioning.prerelease.strategy. Setting an
unsupported property prints an error listing valid values.
Precedence (highest to lowest): --set-package → global CLI
overrides → [[package]] config → [defaults] config → built-in
defaults.
# Override base branch and global prerelease suffix
releasaurus release-pr --base-branch develop --prerelease-suffix beta \
--repo "https://github.com/owner/repo"
# Per-package override (e.g. only the frontend gets a beta suffix)
releasaurus release-pr \
--set-package frontend.versioning.prerelease.suffix=beta \
--repo "https://github.com/owner/repo"
# Date-based versioning for just the nightly package
releasaurus release-pr \
--set-package nightly.versioning.version_type=year.month.day \
--repo "https://github.com/owner/repo"
# Skip one commit and reword another
releasaurus release-pr --skip-sha abc123d \
--reword "def456e=feat: improved authentication" \
--repo "https://github.com/owner/repo"
See Configuration for what these settings mean.
Known Limitations
Gitea < v1.26 / Forgejo < v16: Force Push Not Supported
Releasaurus force-pushes the release branch on each run so repeated
runs update the existing release PR in place rather than piling up new
ones. On Gitea and Forgejo this relies on a force-overwrite option on
the /contents API route that was only added in Gitea v1.26 and
Forgejo v16.
Fix (recommended): upgrade your Gitea/Forgejo instance to v1.26 /
v16 or later. Alternative: use
hybrid mode (--local-path),
which pushes the release branch over git and avoids the API limitation
entirely.
Gitea and Forgejo Actions: Injected Token Shadows Your PAT
Gitea and Forgejo Actions runners (including Codeberg) automatically
inject an ephemeral, limited per-job token into the job environment
under the names GITHUB_TOKEN, GITEA_TOKEN, and FORGEJO_TOKEN. If
you supply your own token through one of those environment variables
— for example env: FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }} — the
runner’s injected value can take precedence inside the action, and
Releasaurus authenticates with the limited token instead of your PAT.
That injected token can usually read the repository, so startup
succeeds, but it cannot create a pull request on a private repo.
Gitea/Forgejo return 404 Not Found for the unauthorized write
against the .../pulls endpoint, which is easy to misread as a
missing repository. Public repos hide the problem because reads are
anonymous.
Fix (recommended): supply your token through the
RELEASAURUS_-prefixed environment variable — e.g.
RELEASAURUS_FORGEJO_TOKEN for Forgejo, RELEASAURUS_GITEA_TOKEN for
Gitea. Releasaurus reads it before the bare *_TOKEN name, and the
runner does not inject the prefixed name, so it can’t be shadowed:
env:
RELEASAURUS_FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }}
Alternative: pass the token on the command line with --token,
which takes precedence over every environment variable. Note that
command arguments are more likely to appear in CI logs than env vars:
command_args: >-
--forge forgejo
--repo ${{ github.server_url }}/${{ github.repository }}
--token ${{ secrets.RELEASE_TOKEN }}
Azure DevOps: Release Branch Requires “Allow rewriting history”
When updating a release PR, Releasaurus resets the release branch to the
tip of the base branch and replays the changelog commit. If the existing
release branch has diverged, this is a non-fast-forward update that Azure
DevOps rejects unless Allow rewriting history is granted on the
release branch (typically releasaurus-release-*).
Grant it under Project Settings → Repositories → {repo} → Security →
Branches → {release branch}, setting Allow rewriting history to
Allow for the identity holding the PAT. Azure DevOps release also only
pushes the git tag — there is no native release object, so no release
notes page is published.
Azure DevOps: Merge Commits Are Not Detected
Azure DevOps omits the parents field from its commit list API — only
the single-commit endpoint returns it. Releasaurus reads history in bulk, so
recovering parents would cost one extra API request per commit. Every Azure
commit is therefore reported as a non-merge commit.
Two settings quietly have no effect as a result:
skip_merge_commits(defaulttrue) filters nothing out.- The default
bodytemplate’sfilter(attribute="merge_commit", value=false)clause excludes nothing.
This only matters for completion strategies that create a merge commit. If
you complete PRs with Merge (no fast forward) or Semi-linear merge,
Azure adds a commit titled Merged PR <n>: <PR title> on top of the source
branch’s own commits. That commit becomes its own changelog entry, so the
PR’s change is represented twice — once by the merge commit, once by the
commits it brought in.
Fix (recommended): complete PRs with Squash commit. Azure then adds a single commit per PR, so there is nothing to filter and no duplication. Rebase and fast-forward is likewise unaffected, since it creates no merge commit.
Alternative: drop individual merge commits with skip_shas (see
Skipping or Rewording Commits). That setting applies to the
next release only, so it has to be repeated each cycle.
Getting Help
releasaurus --help # general help
releasaurus <cmd> --help # command-specific help
releasaurus --version # version information