| Crates.io | rlls |
| lib.rs | rlls |
| version | 0.0.40-rc.1 |
| created_at | 2025-10-08 22:42:55.001028+00 |
| updated_at | 2025-10-11 23:48:16.363804+00 |
| description | Cut a version, tag it, and publish a GitHub Release with raw git notes |
| homepage | |
| repository | https://github.com/rccyx/rlls |
| max_upload_size | |
| id | 1874671 |
| size | 162,126 |
rlls is a Rust-first release tool for single repos and monorepos (JS, Python, Rust). It bumps versions, runs a post-bump command (lock refresh / installs), creates annotated Git tags (package-scoped in monorepos), writes a clean CHANGELOG, and (optionally) makes GitHub Releases — powered by Git history, not rituals.
{{name}}@v{{version}} (e.g. @scope/core@v1.4.2). Fully configurable (keep slashes, keep @).rlls.lock records baselines (including SHAs) so you can rebuild even if tags vanish or history shifts.cargo install --locked rlls
Requires: git.
Optional: gh (GitHub CLI) to resolve PR titles and create GitHub Releases.
Optional (JS projects): pnpm / yarn / npm if you want lockfiles refreshed when versions change.
package.json, pyproject.toml/setup.*, or Cargo.toml.pnpm i, bun install, yarn install --mode update-lockfile, pip-compile, etc.).vX.Y.Z{{name}}@vX.Y.Z (configurable)git log from the correct baseline (last_tag..HEAD or per-package).gh is available).# rlls.toml
default_bump = "patch"
bump_commit_message = "chore(release): bump to {{version}}"
bump_tag_message = "release {{version}}"
# IMPORTANT for JS/Python: refresh locks after version bump
# choose what your repo needs (examples):
post_bump_command = "pnpm i"
[changelog]
enable = true
path = "CHANGELOG.md"
rlls patch # or: rlls minor | rlls major
# rlls.toml
default_bump = "patch"
# tag/message shapes
pkg_tag_template = "{{name}}@v{{version}}"
include_v_prefix = true
bump_tag_message = "{{name}}@{{version}}"
# run after bumping versions (pick one that fits your workspace)
post_bump_command = "pnpm i"
# IMPORTANT: only manage these packages (exact manifest names)
packages = ["@acme/core", "@acme/adapters"]
# optional, used for multi-package commits
monorepo_bump_commit_message = "chore(release): bump {{count}} packages\n\n{{list}}"
[changelog]
enable = true
path = "CHANGELOG.md"
# optional migration (discover old tag shapes)
[migration."@acme/core"]
legacy_tag_patterns = ["core-v*", "core@*"]
First time (or after migrations):
rlls lock rebuild \
--baseline @acme/core:v1.2.3 \
--baseline @acme/adapters:v0.8.0 # only if a package lacks a discoverable baseline
Release:
rlls --monorepo # interactive per-package bumps
# subset:
rlls monorepo --packages "@acme/core,@acme/adapters"
Want tags to match your package names exactly (keep slashes and
@)?
Use:pkg_tag_template = "{{name}}@{{version}}"and setinclude_v_prefixas you prefer.
rlls will push tags safely even with@and/.
rlls.toml)All keys are optional unless noted. Defaults are shown.
# ===== General =====
# Default semver bump when CLI omits one
default_bump = "patch" # "patch" | "minor" | "major"
# Commit message when bumping (used in single or multi, see below)
# Vars: {{name}} {{version}} {{count}} {{list}}
# Default is multi-friendly; override if you prefer a single-repo style.
bump_commit_message = "chore(release): bump {{count}} packages\n\n{{list}}"
# Multi-package (monorepo) commit message; falls back to bump_commit_message if unset
monorepo_bump_commit_message = "chore(release): bump {{count}} packages\n\n{{list}}"
# Tag annotation (tag *message/body*, not the tag name)
# Vars: {{name}} {{version}}
bump_tag_message = "release {{version}}"
# Header inserted at top of the changelog if missing
changelog_header = "# Changelog"
# Tag *name* template for monorepo tags
# Use {{name}} to keep exact pkg name (including @scope and /).
# Use {{id}} to use a sanitized id (slashes -> _; leading @ removed).
pkg_tag_template = "{{name}}@v{{version}}"
# Whether to include "v" in {{version}} when building tags: v1.2.3 vs 1.2.3
include_v_prefix = true
# Allow releasing with a dirty working tree (not recommended)
allow_dirty = false
# Limit rlls to packages listed here (exact manifest "name" values)
packages = ["@acme/core", "@acme/adapters"]
# Command to run after bumping versions, before changelog/tag (optional)
post_bump_command = "pnpm i"
# ===== Changelog =====
[changelog]
enable = true
path = "CHANGELOG.md"
# ===== Migration hints (optional) =====
# Helps rlls discover historical baselines when tag shapes changed.
[migration."@acme/core"]
legacy_tag_patterns = ["core-v*", "core@*"]
All optional; values mirror TOML:
RLLS_DEFAULT_BUMPRLLS_BUMP_COMMIT_MESSAGERLLS_MONOREPO_BUMP_COMMIT_MESSAGERLLS_BUMP_TAG_MESSAGERLLS_CHANGELOG_HEADERRLLS_CHANGELOG_ENABLE (true/false)RLLS_CHANGELOG_PATHRLLS_PKG_TAG_TEMPLATERLLS_INCLUDE_V_PREFIX (true/false)RLLS_POST_BUMP_COMMANDrlls [KIND] [FLAGS] # single repo release (KIND: patch | minor | major)
rlls --monorepo [FLAGS] # monorepo (interactive, filters to config packages)
rlls monorepo [--packages CSV] # monorepo (interactive), subset override
rlls prerelease [--id <str>] [--bump KIND] # single repo prerelease
rlls finalize # single repo: convert last prerelease to stable
rlls rollback [--local] # remove tags at HEAD; rewind release commits; default also updates remote
rlls selfupdate # install latest from crates.io / prefer GH prerelease if on prerelease
rlls lock rebuild [--force] [--baseline NAME:REF ...] [--from-file PATH]
rlls lock verify
rlls tag synthesize --baseline NAME:REF [...]
Common flags
--dry : perform everything except pushing--no-changelog : skip changelog write for this run--repo owner/repo : override detected GitHub repo (for URLs and GH release creation)--monorepo : force monorepo mode if auto-detect is ambiguous--packages "<a,b>" : monorepo subcommand only; filter a subset--ignore_package : single repo only; bump/tag without rewriting manifest (tag-only)prerelease notes
--id default: rc. Examples: v1.2.3-rc.1, v1.2.3-nightly.20250131[.N].--bump controls the base bump (defaults to default_bump).finalize (single repo)
-pre suffix, and creates vX.Y.Z.lock rebuild
rlls.lock by discovering packages and anchoring per-package baselines.--baseline NAME:REF lets you pin a baseline: REF may be v1.2.3, 1.2.3, or a raw commit SHA.--force overwrites an existing lock file.--from-file is reserved for future use.tag synthesize
rlls tag synthesize --baseline @acme/core:v1.2.3 --baseline @acme/adapters:deadbeef
rollback
--local, removes remote tags at HEAD and force-pushes branch after rewinding obvious release commits.--local, operates locally only.Monorepo is currently interactive. Non-interactive per-package bump flags are on the roadmap. For CI flows today, run
rlls lock rebuildin a preparatory step and userlls --monorepoonly when a human is present, or scripttag synthesizefor tag-only flows.
## <tag> <YYYY-MM-DD><base>: git log --no-merges --pretty=- %h %s(#123) optionally resolved via gh to titlesgit shortlog -sn (singular/plural friendly)Monorepo: a single batch section (e.g. ## batch-20250131235959) with one sub-section per package tagged, each with its scoped commit window.
v<semver>.pkg_tag_template. To keep slashes and @ in tag names, use {{name}} (not {{id}}).rlls:id=<sanitized-tag-id>
rlls:pkg=<package-name>
rlls:ver=<version-core>
rlls:sha=<target-commit-sha>
If your remote/refspec complains about special chars, push the explicit ref:
git push origin "refs/tags/@scope/pkg@0.2.0"
package.json (and lockfile refresh if pnpm/yarn/npm exist)pyproject.toml (PEP 621 / Poetry), setup.cfg, setup.pyCargo.toml (single crate or workspace; workspace members are updated)allow_dirty = true (use sparingly).rlls lock rebuild --baseline <name>:<v1.2.3|sha> or add migration.<name>.legacy_tag_patterns.pkg_tag_template = "{{name}}@{{version}}", and if necessary push refs/tags/<tag>.packages = [...] allowlist names exactly match each manifest’s "name". Use rlls monorepo --packages "a,b,c" for ad-hoc subsets.allow_dirty).lock verify/rebuild.rlls lock rebuild
git add rlls.lock && git commit -m "chore: refresh rlls.lock" || true
rlls tag synthesize --baseline @acme/core:v1.2.3
rlls --monorepo locally or in a TTY-enabled runner.# Single repo
rlls patch|minor|major
rlls prerelease --bump minor --id rc
rlls finalize
rlls rollback [--local]
rlls selfupdate
# Monorepo
rlls lock rebuild [--force] [--baseline NAME:REF ...]
rlls lock verify
rlls --monorepo
rlls monorepo --packages "@acme/core,@acme/adapters"
# Tags without bumping files
rlls tag synthesize --baseline @acme/core:v1.2.3
chore(release): bump to 1.2.3, override bump_commit_message accordingly (the default is multi-package friendly).@scope/ and /):pkg_tag_template = "{{name}}@{{version}}" and choose your include_v_prefix.