Skip to content
rlsbl release
On this page

Release orchestration commands covering the full release lifecycle.

#rlsbl release

Release orchestration commands covering the full release lifecycle. Provides 11 subcommands: run, resume, init, retry, edit, undo, deprecate, yank, scrub, backfill, reconcile.

#release run

Bump version, validate the JSONL changelog, run tests and lint, commit, tag, push, and create a GitHub Release. Reads the bump type (patch, minor, major, or infra) and target selection from .rlsbl/releases/unreleased.toml, which can be scaffolded with rlsbl release init. Supports dry-run preview, --approve-consequential to skip the confirmation prompt in non-interactive contexts, and --allow-dirty to skip the clean working tree check.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--push-timeoutintoptionalTimeout in seconds for each git push. Overrides the push_timeout config key; when omitted, push_timeout applies, else the shipped default.
--ci-timeoutintoptionalTimeout in seconds for the release CI gate (the wait for CI to conclude on the pushed release candidate). Overrides the ci_timeout config key; when omitted, ci_timeout applies, else the shipped default.
--check-timeoutintoptionalTimeout in seconds for each preflight check subprocess (tests, lint, external checks). Overrides the check_timeout config key; when omitted, check_timeout applies, else the shipped default.
--hook-timeoutintoptionalTimeout in seconds for each release hook. Overrides the hook_timeout config key; when omitted, hook_timeout applies, else no timeout.
--watch, --no-watchboolrequiredAfter release, automatically watch CI runs to completion (--no-watch to skip)
--allow-dirty, --no-allow-dirtyboolrequiredSkip the clean working tree check and allow releasing with uncommitted changes
--releasablestroptionalWhich releasable to release. Required when running at a monorepo workspace root, where the directory names the whole workspace rather than one releasable; rejected anywhere else, since the directory already names it.

#release resume

Resume a previously failed release from where it left off. Reads the in-progress state file (.rlsbl/releases/in-progress.json, or .rlsbl-monorepo/releasables//releases/in-progress.json for releasable releases), validates that the current branch matches the saved state, and re-enters the release flow, skipping already-completed steps.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--push-timeoutintoptionalTimeout in seconds for each git push. Overrides the push_timeout config key; when omitted, push_timeout applies, else the shipped default.
--ci-timeoutintoptionalTimeout in seconds for the release CI gate (the wait for CI to conclude on the pushed release candidate). Overrides the ci_timeout config key; when omitted, ci_timeout applies, else the shipped default.
--check-timeoutintoptionalTimeout in seconds for each preflight check subprocess (tests, lint, external checks). Overrides the check_timeout config key; when omitted, check_timeout applies, else the shipped default.
--hook-timeoutintoptionalTimeout in seconds for each release hook. Overrides the hook_timeout config key; when omitted, hook_timeout applies, else no timeout.
--watch, --no-watchboolrequiredAfter release, automatically watch CI runs to completion (--no-watch to skip)

#release init

Scaffold a .rlsbl/releases/unreleased.toml file by auto-detecting project targets. The generated file contains a default bump type (patch), an include list of all detected targets, and per-target configuration sections for Flutter targets.

Effect: mutating

Dry run: not supported — the command scaffolds a file whose point is that you edit it before releasing; printing that file instead of writing it leaves nothing to edit

#release retry

Dispatch CI/CD workflows for a completed release via gh workflow run. Reads the dispatch list and ref from .rlsbl/releases/retry.toml, which is auto-scaffolded with sensible defaults if missing. Verifies the GitHub Release exists before dispatching. Each workflow in the dispatch list is triggered against the configured ref (defaults to the release tag).

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--watch, --no-watchboolrequiredAfter retry, automatically watch CI runs to completion (--no-watch to skip)

#release edit

Sync the GitHub Release notes for a given version with the corresponding CHANGELOG.md entry. Defaults to the current version if none is specified. Use --dry-run to preview changes without updating GitHub.

Effect: mutating

#Arguments

Arguments
NameTypePresenceDescription
versionstroptionalVersion whose GitHub Release notes to sync (defaults to current version)

#release undo

Revert a release. Without --version, reverts the latest release (deletes GitHub Release, removes git tag, reverts version bump commit). With --version, reverts a non-latest release if it is provably unpublished (probes registries for evidence, deletes GitHub Release + tag only, un-finalizes changelog).

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--targetstroptionalTarget a specific registry for version detection (auto-detected if omitted)
--versionstroptionalVersion to undo (for non-latest releases that are provably unpublished)

#release deprecate

Mark a past release as deprecated. Sets the GitHub Release pre-release flag and prepends a deprecation notice to the release notes. Use --reason to explain why and --use to suggest a replacement version.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--reasonstroptionalHuman-readable explanation of why this version is being deprecated
--usestroptionalSuggest this version as a replacement in the deprecation notice

#Arguments

Arguments
NameTypePresenceDescription
versionstrrequiredSemver string of the release to deprecate, with or without v prefix (e.g. 0.9.1)

#release yank

Remove a published version from package registries. Probes each configured target's registry to determine publication status, then executes registry-specific removal: npm deprecate, Go retract, or PyPI manual checklist. Also marks the GitHub Release as pre-release with a yank notice.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--reasonstroptionalHuman-readable explanation of why this version is being yanked
--usestroptionalSuggest this version as a replacement in the yank notice

#Arguments

Arguments
NameTypePresenceDescription
versionstrrequiredSemver string of the release to yank, with or without v prefix (e.g. 0.9.1)

#release scrub

Scrub sensitive content from git history and update release metadata to match the rewritten commits. Supports 3 modes: match (--pattern), file (--file), or recipe (--recipe). After rewriting, remaps commit hashes in JSONL changelog files, regenerates CHANGELOG.md, force-pushes, re-points the tags, and rewrites each tag's GitHub Release document in place. A Release is never deleted, so a failure mid-step leaves the previous document standing rather than a tag with no Release at all.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
modechoicerequiredSelection (not typed as a flag). Elect exactly one of --pattern, --file, --recipe. Which scrub mode to run: match a regex, rewrite one file, or execute a recipe TOML. Exactly one must be elected, and the elected one decides which further flags exist.
    --patternstrrequiredElects mode = pattern. Match mode: rewrite every occurrence of a regular expression throughout the repository's history, in every file of every commit the chosen range covers Its value: regular expression matched against file contents in every commit of the chosen range; each match is replaced by --replace, or by same-length random ASCII under --mangle
        --replacestroptionalOnly with --pattern. literal text to substitute for each match (mutually exclusive with --mangle)
        --manglebooloptionalOnly with --pattern. replace matched content with random ASCII of the same length (mutually exclusive with --replace)
    --filestrrequiredElects mode = file. File mode: rewrite one file throughout the repository's history, replacing every past version of it with the copy on disk now Its value: repository-relative path of the file to rewrite throughout history; every commit's version of it is replaced with its current on-disk content, or removed from that commit if the file is absent on disk (requires --from-commit)
    --recipestrrequiredElects mode = recipe. Recipe mode: execute a scrub recipe TOML via safegit scrub run Its value: path to a scrub recipe TOML file; per-operation pattern/replace/mangle live inside the recipe
commit-rangechoicerequiredSelection (not typed as a flag). Elect exactly one of --from-commit, --entire-history. Which commits the rewrite covers: everything descended from one commit, or the entire history from the initial commit onward. Exactly one must be elected.
    --from-commitstrrequiredElects commit-range = from-commit. Rewrite the commits descended from one named commit onward, leaving every commit before it exactly as it is Its value: SHA of the earliest commit to rewrite; every commit descended from it is rewritten too, and every commit before it keeps its current hash
    --entire-historyrequiredElects commit-range = entire-history. Rewrite every commit in the repository from the initial commit onward (match and recipe modes only; file mode requires --from-commit)
--reasonstrrequiredWhy this content is being scrubbed. Recorded in the rewrite commit message and in the scrub archive, so it is the audit trail for an irreversible history rewrite.

#release backfill

Bring this repository's release archives into the three-fate model from its real history: record each version's release commit from the tag (or the historical spelling its archive names in shipped_as, or its version-bump commit), complete an archive whose required fields are missing or unanswered (a present but empty bump or description is unanswered), materialize an archive for a released version that never got one, and adopt a version tag no store records as the release it is evidence of. A reconstructed description comes from the first source that yields one -- an operator-reviewed --overrides file, the version's GitHub Release body, its CHANGELOG.md section, the commit subjects in its tag range -- and the archive names the source it came from. Every tag the repository cannot account for is listed first and refuses the whole apply; --dry-run prints the plan and writes nothing.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
--overridesstroptionalPath to a TOML file of reviewed descriptions, one [versions."X.Y.Z"] table per version with a description and an optional context. Applied before any derivation. A version the file names that this repository does not have is a hard error.
--auto-commit, --no-auto-commitbooloptionalCommit the written archives with the Autogenerated trailer (the handler commits when neither --auto-commit nor --no-auto-commit is passed)

#release reconcile

Reconcile this project's published release metadata with what its own records say it released: push the refs origin is missing, re-point the ones a recorded rewrite moved, and create the GitHub Releases that are absent. Merges four explanation sources -- safegit's rewrite journal, the release record's release commits, the transition records, and the committed scrub archives -- into one preview whose verdicts are materialize, already-correct, re-point-with-lease, refuse-foreign, or refuse-identity-mismatch. Fail-closed: one ref origin holds that no record explains aborts the whole reconcile, and nothing anywhere is repaired. Consent is file-driven: --plan writes the plan, --apply performs it.

Effect: mutating · consequential (prompts before running; --approve-consequential skips)

#Flags

Flags
NameShortTypePresenceEnvDescription
modechoicerequiredSelection (not typed as a flag). Elect exactly one of --plan, --apply. Which half of the reconcile to run: write the plan, or perform it. Exactly one must be elected.
    --planrequiredElects mode = plan. Observe origin and write the reconcile plan as reconcile-plan.toml beside the release records being reconciled (.rlsbl/releases/ in a standalone repository, the releasable's own releases/ in a workspace). Writes nothing to origin.
    --applyrequiredElects mode = apply. Perform the reconcile-plan.toml beside the release records being reconciled, after re-observing origin and refusing if it moved since the plan was written.
--push-timeoutintoptionalTimeout in seconds for each ref push. Overrides the push_timeout config key; when omitted, push_timeout applies, else the shipped default.
--releasablestroptionalWhich releasable to reconcile. Required when running at a monorepo workspace root, where the directory names the whole workspace rather than one releasable; rejected anywhere else, since the directory already names it.

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • selfdoc Static Site Generator that builds a project's documentation site directly from its source code, so the docs can never drift from the code they describe, with SEO/AEO, first-class blog, search, and cross-project linking built in
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
  • wesktop A Python framework that turns an ASGI web app into a desktop application, serving it from a local Granian server and displaying it in a native OS window via pywebview
Search