rlyx

Crates.iorlyx
lib.rsrlyx
version0.3.1
created_at2025-10-21 15:46:22.848897+00
updated_at2025-11-14 09:18:41.766645+00
descriptionrlyx is a fast release manager that automatically bumps versions, creates changelogs, tags commits, and publishes GitHub releases across JS, Rust, and Python projects with first class monorepos support.
homepage
repositoryhttps://github.com/rccyx/rlyx
max_upload_size
id1894032
size162,949
(rccyx)

documentation

README

rlyx

rlyx is a smart release manager for Git and GitHub. You run one command and it reads your repo, figures out what changed, and ships a clean release automatically. It bumps versions, writes the tag, pushes, generates real release notes from Git history, updates a changelog if you want one, and can publish GitHub releases through the GitHub CLI.

[!NOTE] Status is still in beta, Interfaces, defaults, and behaviors are still subject to change until the first stable release.

Install

Use Cargo to install the binary.

cargo install rlyx

Git is required. If the GitHub CLI gh is present, rlyx can publish releases and pull PR titles automatically. For JavaScript projects, if a lockfile already exists, rlyx will refresh it using whichever of pnpm, yarn, or npm it finds.

Commands

You can be explicit about the bump or let config decide.

# single repo
rlyx
rlyx patch
rlyx minor
rlyx major

# prereleases
rlyx prerelease --id rc --bump minor
rlyx prerelease --id nightly

# finalize latest prerelease to stable
rlyx finalize

# rollback most recent release work
rlyx rollback
rlyx rollback --local

# update rlyx itself
rlyx selfupdate

# monorepo flows
rlyx --monorepo
rlyx --monorepo patch
rlyx monorepo minor
rlyx monorepo major
rlyx monorepo patch --packages @acme/core,@acme/ui

Global flags are available when you need control during a run.

--no-changelog         skip changelog writes
--repo owner/name      override GitHub repo detection
--dry                  run everything except push and release
--ignore_package       do not write version files
--since <rev>          narrow single-repo finalize baselines
--post_bump_cmd "<CMD>"  run a shell command after bumping
--skip_post_bump       disable the post bump step
--monorepo             force monorepo mode

Configuration

Place rlyx.toml at the repository root. If you only call rlyx with no path, it looks for .rlyxrc first and falls back to rlyx.toml. Environment variables with an RLYX_ prefix can override scalar keys at runtime.

A minimal single repo config looks like this.

default_bump = "patch"
bump_commit_message = "release v{{version}}"
bump_tag_message    = "v{{version}}"
changelog_header    = "# Changelog"

[changelog]
enable = true
path   = "CHANGELOG.md"

# optional
allow_dirty       = false
include_v_prefix  = true
post_bump_command = "pnpm -w build"

A monorepo config adds the package list and a per package tag format. You declare the exact package names rlyx is allowed to manage and you control how tags render. The tag template can reference {{name}}, {{id}}, and {{version}}. When include_v_prefix is true, {{version}} renders with a leading v.

packages = ["@acme/api", "@acme/ui", "cli"]
include_v_prefix = true
pkg_tag_template = "{{name}}@{{version}}"
releases_per_package = true
monorepo_bump_commit_message = "release {{count}} packages\n\n{{list}}"

[changelog]
enable = true
path   = "CHANGELOG.md"

You can keep continuity across package renames using a migration map. This matters when tags embed the package name. If @acme/ui becomes @acme/web-ui, add a migration entry with glob patterns that match how tags used to look. rlyx will search those patterns to find the previous tag when it computes diffs.

[migration."@acme/web-ui"]
legacy_tag_patterns = ["@acme/ui@v*", "ui@v*"]

Environment overrides

You can mirror scalar config keys with environment variables.

RLYX_DEFAULT_BUMP
RLYX_BUMP_COMMIT_MESSAGE
RLYX_BUMP_TAG_MESSAGE
RLYX_CHANGELOG_HEADER
RLYX_CHANGELOG_ENABLE=1|0
RLYX_CHANGELOG_PATH
RLYX_PKG_TAG_TEMPLATE
RLYX_INCLUDE_V_PREFIX=1|0
RLYX_RELEASES_PER_PACKAGE=1|0
RLYX_UMBRELLA_RELEASE=1|0
RLYX_MONOREPO_BUMP_COMMIT_MESSAGE
RLYX_POST_BUMP_CMD

Behavior details

What happens in a single repository

rlyx starts by finding your current version. For JavaScript it reads package.json. For Python it reads pyproject.toml, setup.cfg, or setup.py. For Rust it reads Cargo.toml when the repo is not a Cargo workspace. If it cannot find a version in files, it falls back to the most recent lightweight tag that looks like vX.Y.Z.

From that base it computes the next version based on the bump you asked for. It writes that version back into your project files unless you explicitly tell it not to write package files. It renders a commit message from your template and creates a commit if anything changed. It creates an annotated tag like v1.2.3 and includes machine trailers in the tag body so tools can parse it later without guesswork.

The trailers are rlyx:id, rlyx:pkg, rlyx:ver, and rlyx:sha. These are key value lines inside the tag annotation so machines can trace a tag to a package and commit with zero ambiguity.

After tagging, it pushes the commit and the tag. It builds release notes from git log, optionally updates CHANGELOG.md, and if gh is available it creates a GitHub release and sets an explicit title so GitHub does not guess from the body. If your working tree is dirty and you did not allow dirty runs, rlyx stops before doing anything.

What happens in a monorepo

If rlyx detects a monorepo or you force it with --monorepo, it discovers packages for JavaScript, Rust, and Python. It filters that list to whatever you declared in configuration. You can run it headless using config defaults or interactively if you prefer to choose per package.

Headless mode applies the bump you asked for on the CLI or the default_bump from config. Interactive mode prompts for each package so you choose patch, minor, major, or skip. rlyx writes versions for the selected packages, stages once, creates a single summary commit using your template, creates one annotated tag per bumped package using your tag format, pushes the summary commit, pushes all tags, generates per package notes, optionally writes one grouped changelog entry, and can create one GitHub release per package if you enabled that behavior in config.

Rlease cycle

Prereleases are computed from your current version. If you run rlyx prerelease --id rc --bump minor, rlyx increments the minor, appends -rc.1, and tags that. Repeating the command on the same base increments the trailing number. Nightly prereleases use a YYYYMMDD channel and increment a suffix if you create more than one nightly on the same day.

Finalize converts the latest reachable prerelease to a stable vX.Y.Z tag. It refuses to run if that stable tag already exists.

Annotated tags carry the trailer lines so machines can pull the package id, package name, semantic version, and commit SHA without parsing your prose. The GitHub release title is always set explicitly to avoid auto derived titles. In monorepos, rlyx can publish one release per package when releases_per_package is true. In single repo mode it publishes one release per tag.

When rlyx writes the changelog it creates a section for the tag and date, a Changes block with non merge commits in the range, a Pull requests block if it detects PR numbers, an Authors block from git shortlog, and a Compare link to the exact range on GitHub. You can set a static header at the top of the file using changelog_header.

The post bump step can run a command to rebuild lockfiles, run tests, or update docs. You can pass it on the CLI, set it in config, or accept the interactive prompt. You can skip it for a single run with --skip_post_bump.

The dirty tree rule is strict by default. If anything is staged or unstaged, rlyx exits unless allow_dirty is true. Rollback deletes tags at HEAD, rewinds recent release commits, and optionally pushes the forced update unless you used --local.

Package rename handling

Single repo tags are plain vX.Y.Z, so renaming a package does not affect tag continuity. In a monorepo, tags include the package name by design. If you rename a package, update the packages list to the new name and add a migration entry with legacy patterns.

That preserves history across the rename so diffs and author counts stay correct. Scoped JavaScript names are normalized internally by removing the leading @ and replacing slashes with underscores for the machine rlyx:id in trailers. The visible tag format you configure is not changed by that internal id.

Safety and dry runs

You can see the exact plan without touching remotes by adding --dry. rlyx will compute versions, construct notes, and render messages, but it will not push or publish. If you want to inspect the plan without writing version files, add --ignore_package.

Support matrix

JavaScript projects are supported at any package root with package.json. Monorepo discovery walks a few levels deep and ignores node_modules, build directories, and VCS folders. Rust is supported for single crates and workspace layouts. Python is supported for modern pyproject.toml and for older setup.cfg or setup.py when a version can be updated in place. If your layout is unusual but you still keep semantic versions in text files, that is fine. Opening issues is not enabled yet.

Example Workflow

A typical single repo patch.

rlyx

A named prerelease.

rlyx prerelease --id rc --bump minor

A monorepo batch scoped to one package.

rlyx monorepo patch --packages @acme/core

Finalize after a series of prereleases.

rlyx finalize

Rollback and clean up remote tags as well.

rlyx rollback

License

Licensed under MIT © @rccyx

Commit count: 0

cargo fmt