Release orchestration and project scaffolding for npm and PyPI
Project description
rlsbl
Release orchestration and project scaffolding CLI for npm and PyPI.
Install
From npm:
npm i -g rlsbl
From PyPI (requires Node.js 18+):
uv tool install rlsbl
Quick start
rlsbl scaffold
rlsbl release minor
Commands
All commands work at the top level -- registries are auto-detected from project files (package.json, pyproject.toml). Use the registry-specific form (rlsbl <registry> <command>) only when you need to target a single registry.
scaffold [--force] [--update]
Scaffolds CI/CD infrastructure and release tooling for all detected registries.
rlsbl scaffold
rlsbl npm scaffold # target npm only
rlsbl pypi scaffold --force # overwrite existing files
Context-aware behavior when files already exist (without --force):
| File | Behavior |
|---|---|
CLAUDE.md |
Appends rlsbl sections if the marker is not present |
.gitignore |
Merges missing entries from the template |
.github/workflows/ci.yml |
Preserves existing file, prints a note to review manually |
| All others | Skipped |
release [patch|minor|major] [--dry-run] [--quiet]
Bumps version, commits, pushes, and creates a GitHub Release. Defaults to patch.
rlsbl release minor
rlsbl npm release major --dry-run
The version is synced across all detected project files (package.json, pyproject.toml) regardless of which registry is primary.
If scripts/pre-release.sh exists, it runs before any changes are made. A non-zero exit aborts the release.
status
Shows project status: package name, version (per registry), git branch, last tag, working tree state, changelog coverage, and CI workflow presence.
rlsbl status
rlsbl pypi status
check-name <name>
Checks name availability on both npm and PyPI, and warns about confusingly similar names.
rlsbl check-name my-cool-lib
rlsbl npm check-name my-cool-lib # npm only
npm checks variant spellings (hyphens, underscores, dots, no separator). PyPI normalizes per PEP 503 and checks common alternatives.
Global flags: --help, --version.
Release flow
When you run release, the following happens in order:
- Verifies
ghCLI is installed and authenticated - Checks that the git working tree is clean
- Reads the current version from the primary project file
- Computes the new version and confirms the git tag does not already exist
- Validates that
CHANGELOG.mdcontains a## <new-version>section - Runs
scripts/pre-release.shif present (non-zero exit aborts) - Writes the new version to the primary project file
- Syncs the new version to all other detected project files
- Commits the version bump (uses
safegitif available, otherwisegit) - Pushes the branch to
origin - Creates a GitHub Release tagged
v<new-version>with the changelog entry as notes - The GitHub Release triggers
publish.yml, which publishes to the registry
What scaffold creates
| File | Source | Purpose |
|---|---|---|
.github/workflows/ci.yml |
Registry-specific | CI workflow (lint, test) |
.github/workflows/publish.yml |
Registry-specific | Publish on GitHub Release (OIDC) |
CHANGELOG.md |
Shared | Version changelog |
LICENSE |
Shared | MIT license (author and year filled in) |
.gitignore |
Shared | Standard ignores for the ecosystem |
CLAUDE.md |
Shared | AI assistant instructions |
.claude/settings.json |
Shared | Claude Code settings |
scripts/check-prs.sh |
Shared | PR review helper |
scripts/pre-release.sh |
Shared | Pre-release hook (runs before each release) |
scripts/record-gif.sh |
Shared | Terminal recording helper |
scripts/pre-push-hook.sh |
Shared | Pre-push changelog enforcement |
All .sh files in scripts/ are made executable automatically. The pre-push hook is installed into .git/hooks/pre-push during scaffold.
Pre-push hook
The scaffolded scripts/pre-push-hook.sh is installed as a git pre-push hook during scaffold. It prevents pushing when CHANGELOG.md lacks an entry for the current version.
How it works:
- Detects project type (
package.jsonorpyproject.toml) - Extracts the current version
- Checks that
CHANGELOG.mdcontains a heading## <version> - Blocks the push with an error if the entry is missing
To reinstall manually:
cp scripts/pre-push-hook.sh .git/hooks/pre-push && chmod +x .git/hooks/pre-push
First publish
The first version must be published manually before CI can take over:
| Registry | Manual first publish | Then configure |
|---|---|---|
| npm | Add an NPM_TOKEN secret to your GitHub repo (Settings > Secrets > Actions), then push a release |
CI handles subsequent publishes |
| PyPI | Run uv publish |
Set up Trusted Publishing on pypi.org |
After configuration, all subsequent releases are handled by CI when rlsbl release creates a GitHub Release.
Requirements
- Node 18+
- GitHub CLI (
gh), installed and authenticated - git
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rlsbl-0.1.1.tar.gz.
File metadata
- Download URL: rlsbl-0.1.1.tar.gz
- Upload date:
- Size: 24.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
314a5ec814a261adda99ff6017c138dfc525da99c3f454d4c084c13900935435
|
|
| MD5 |
5cc9aca549fe1c48287f117e0e57bf18
|
|
| BLAKE2b-256 |
060303d2dadf33ebf809ed4592273e5a64fc0021ba6204326105a3f402b027c9
|
Provenance
The following attestation bundles were made for rlsbl-0.1.1.tar.gz:
Publisher:
publish.yml on smm-h/rlsbl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rlsbl-0.1.1.tar.gz -
Subject digest:
314a5ec814a261adda99ff6017c138dfc525da99c3f454d4c084c13900935435 - Sigstore transparency entry: 1409355201
- Sigstore integration time:
-
Permalink:
smm-h/rlsbl@348636db47d5b19f6a04aa8994ee5bb735e9aa33 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/smm-h
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@348636db47d5b19f6a04aa8994ee5bb735e9aa33 -
Trigger Event:
release
-
Statement type:
File details
Details for the file rlsbl-0.1.1-py3-none-any.whl.
File metadata
- Download URL: rlsbl-0.1.1-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06a61f59da30552da70540bccb359ed8bea5326c1ff176e6d3b539e7816c2dee
|
|
| MD5 |
9fbbae27e652fd52faa8beddc95de123
|
|
| BLAKE2b-256 |
663cc532cdd3a5173e17fa863bb50db13ecd3e584ce6a200eb46a02eeddaf34f
|
Provenance
The following attestation bundles were made for rlsbl-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on smm-h/rlsbl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rlsbl-0.1.1-py3-none-any.whl -
Subject digest:
06a61f59da30552da70540bccb359ed8bea5326c1ff176e6d3b539e7816c2dee - Sigstore transparency entry: 1409355205
- Sigstore integration time:
-
Permalink:
smm-h/rlsbl@348636db47d5b19f6a04aa8994ee5bb735e9aa33 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/smm-h
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@348636db47d5b19f6a04aa8994ee5bb735e9aa33 -
Trigger Event:
release
-
Statement type: