Skip to content
rlsbl monorepo
On this page

Manage monorepo workspaces with multiple independently-versioned projects.

#rlsbl monorepo

Manage monorepo workspaces with multiple independently-versioned projects. Initialize workspaces, add or remove projects, sync CI workflows, check name availability, and analyze dependency graphs. Provides 17 monorepo subcommands: init, add, remove, list, sync, status, check-names, outdated, snapshot, snapshot-check, mirror, graph, impact, extract, absorb, cleanup, rename-releasable. Plus 1 subgroup: release. Supports all 17 release targets in a single workspace.toml (the app help enumerates them).

#monorepo init

Create a new monorepo workspace by generating the .rlsbl-monorepo directory and a workspace.toml at the current directory, carrying the mandatory root member whose kind you declare and a [[releasables]] section. This must be run at the repository root before adding individual projects with the add subcommand. Each workspace tracks multiple independently-versioned projects that share a single git repository.

Effect: mutating

Dry run: not supported — it bootstraps the workspace every other command reads, and there is no workspace to preview against until it exists

#Flags

Flags
NameShortTypePresenceEnvDescription
root-memberchoicerequiredSelection (not typed as a flag). Elect exactly one of --root-dev-node, --root-releasable. What kind of member owns the repository root. Every workspace has exactly one root member, and it owns every tracked file no other member claims; whether those files need changelog coverage is a per-repository decision with no default.
    --root-dev-noderequiredElects root-member = root-dev-node. The root member is a dev node: files at the repository root that no other member claims need no changelog coverage.
    --root-releasablestrrequiredElects root-member = root-releasable. The root member belongs to a named releasable: files at the repository root that no other member claims get changelog coverage under it. Its value: name of the releasable the root member belongs to; it is created in [[releasables]]
        --tag-formatstrrequiredOnly with --root-releasable. tag format for that releasable, e.g. "v{version}" for bare version tags or "{name}@v{version}" for the workspace scheme; a root releasable never inherits a default
--auto-commit, --no-auto-commitbooloptionalAutomatically commit the generated workspace.toml configuration file to git (the handler commits when neither form is passed)

#monorepo add

Register a project directory in the monorepo workspace.toml configuration. The path argument specifies the project's location relative to the repo root. Optional settings cover display name, target registry, inter-project dependencies, releasable membership, registry identity, and flags marking the project as a shared library or a dev-only leaf. A --releasable naming a group [[releasables]] does not declare yet creates it, as absorb creates one for an arriving member: a singleton entry whose tag_format is written out explicitly, derived from the member's primary target scheme unless --tag-format states it. The mirror destination is not among them: it is a releasable-level key, declared in workspace.toml beside the releasable it binds. What CI reacts to is not among them: the router's paths filters are derived from the workspace, never declared per project.

Effect: mutating

#Flags

Flags
NameShortTypePresenceEnvDescription
--namestroptionalDisplay name for the project in workspace.toml (defaults to directory name)
--targetstroptionalRegistry this project publishes to (e.g. npm, pypi, go)
--depends-onstroptionalComma-separated names of workspace projects this project depends on
--librarystroptionalMark as a shared library consumed by other workspace projects (true/false)
--dev-onlystroptionalMark as a dev-only leaf node excluded from the dependency boundary guardrail (true/false)
--releasablestroptionalReleasable group this project belongs to (name of a [[releasables]] entry, which is created when it does not exist yet, or 'false' to opt out of versioning)
--tag-formatstroptionalThe tag format of the releasable this command creates, e.g. "{name}@v{version}" or "pkgs/thing/v{version}". Derived from the member's primary target when omitted; required when its targets span both tag schemes. Illegal when --releasable names a releasable that already exists, which brings its own format, and with --releasable false, which creates none.
--registry-namestroptionalPackage registry identity for this project (used verbatim for name checks; overrides prefix/suffix)
--auto-commit, --no-auto-commitbooloptionalAuto-commit workspace.toml and trigger scaffold/sync commits (the handler commits when neither form is passed)

#Arguments

Arguments
NameTypePresenceDescription
pathstrrequiredRelative path from the repo root to the project directory to register

#monorepo remove

Unregister a project from the monorepo workspace.toml by its path. This removes the project entry from the workspace configuration file but does not delete any files, directories, or git history on disk. The project's code remains intact and can be re-added later with the add subcommand if needed.

Effect: mutating

Dry run: not supported — the whole edit is deleting the one workspace.toml entry you just named, and a preview of it would restate the path back to you

#Arguments

Arguments
NameTypePresenceDescription
pathstrrequiredRelative path from the repo root of the project to unregister from workspace.toml

#monorepo list

Display every member registered in the monorepo workspace.toml file, one row each: the member's name, its path relative to the repo root, the releasable it is versioned under (or false when it is opted out of versioning, or -- when it declares none), and the member flags it carries (library, dev-only, test-only). A release target is not among them -- targets are detected from each member's own manifests, never declared in workspace.toml -- and neither is a mirror destination, which belongs to the releasable rather than the member.

Effect: read_only

#monorepo sync

Inline every project's CI jobs into a single generated ci-router.yml (and publish jobs into publish.yml) in the shared .github/workflows directory at the repository root. Jobs are inlined rather than routed via reusable-workflow calls because GitHub rejects workflows that reference 20 or more reusable workflows. Stale per-project workflow copies at the root are removed via saferm.

Effect: mutating

#Flags

Flags
NameShortTypePresenceEnvDescription
--auto-commit, --no-auto-commitbooloptionalAuto-commit merged workflow files in .github/workflows/ (the handler commits when neither form is passed)

#monorepo status

Show the current version, last release tag, and changelog coverage for every project in the monorepo workspace. Coverage is the real JSONL figure -- the commits since the project's last tag, scoped to the project and minus the exempt ones, rendered covered/tracked with an (N exempted) suffix, or 'no changelog' when the project has no changes directory. A publish-suppressed member's version comes from its releasable's version file, annotated (version file): nothing publishes such a member, so nothing bumps its manifest and the version-consistency check reads the same file rather than the manifest. Provides a quick overview of which projects have pending changes and are ready for their next release.

Effect: read_only

#monorepo check-names

Check package name availability on a target registry for all projects in the monorepo workspace. Queries the registry API for each project name and reports whether it is available or already taken. Supports optional prefix and suffix arguments to test naming conventions like scoped packages, with a configurable delay between registry queries to avoid rate limiting.

Effect: read_only

#Flags

Flags
NameShortTypePresenceEnvDescription
--targetstrrequiredRegistry to query for name availability across all workspace projects Values: npm (the npm registry), pypi (the Python Package Index), go (the Go module proxy), github (GitHub repository names).
--prefixstroptionalString to prepend to each project name before checking availability
--suffixstroptionalString to append to each project name before checking availability
--delaystrdefault: 200Milliseconds to wait between consecutive registry API queries

#monorepo outdated

Scan all projects in the monorepo workspace for intra-workspace dependencies that reference older versions than what is currently available in the workspace. Lists each outdated dependency with the referenced version and the latest available version, helping identify which downstream projects need a version bump after upstream releases.

Effect: read_only

#monorepo snapshot

Regenerate the committed JSON artifact at .rlsbl-monorepo/snapshot.json summarizing all packages, versions, dependencies, and graph structure, and commit it. Verifying without regenerating is a separate command, rlsbl monorepo snapshot-check. Under --dry-run the artifact is computed but neither written nor committed, and the preview names both steps.

Effect: mutating

#monorepo snapshot-check

Verify that .rlsbl-monorepo/snapshot.json matches the workspace it describes, without regenerating it. Exits 1 when the artifact is stale or missing. This is the read-only half of the former monorepo snapshot --check flag; rlsbl monorepo snapshot is the half that writes.

Effect: read_only

#monorepo mirror

Reconcile a monorepo project's subtree mirror toward its desired state. The mirror is a tool-owned, derived artifact: it observes the remote, then converges it to exactly one scaffold commit atop the current deterministic subtree split, force-pushing (with lease) as the routine write. A tripwire refuses to touch a mirror carrying foreign (hand-authored) commits. Use --dry-run to print a plan (converged, scaffold-stale, behind, scaffold-missing, contract-violated, ancestry-undetermined, or virgin) without writing.

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

#Arguments

Arguments
NameTypePresenceDescription
projectstrrequiredName of the workspace project to split and push as a standalone mirror repo

#monorepo graph

Export the monorepo dependency graph as DOT (Graphviz) or an indented text tree; the framework-owned --json yields the same graph as a structured document. Supports filtering by a root package (transitive deps) or reverse package (transitive rdeps), with optional depth limiting. Use --output to write the rendering to a file instead of stdout.

Effect: mutating

#Flags

Flags
NameShortTypePresenceEnvDescription
--formatstroptionalRendering for the dependency graph (the handler renders text when omitted) Values: text (an indented text tree), dot (a Graphviz DOT document).
--outputstroptionalFile path to write the graph output to instead of printing to stdout
--rootstroptionalFilter to show only transitive dependencies reachable from this package
--reversestroptionalFilter to show only transitive reverse dependencies of this package
--depthintoptionalMaximum number of dependency hops to traverse from the root or reverse node

#monorepo impact

Analyze the impact of changes to a package, file, or git diff range on the monorepo dependency graph. Shows direct and transitive dependents, test scope, and release candidates as a human report, or as a structured document under the framework-owned --json. Supports package names, file paths, and --since for git-based change detection.

Effect: read_only

#Flags

Flags
NameShortTypePresenceEnvDescription
--depthintoptionalMaximum number of dependency hops to traverse when computing transitive impact
--sincestroptionalGit ref to diff against HEAD (e.g. HEAD~3, v1.0.0)

#monorepo extract

Extract a releasable out of the monorepo into its own repository. The releasable is the portable unit: its members' history is filtered into a new repo (hoisted to the root when it has a single member), its whole release state -- version, changelog, release archives with their release commits, config and hooks -- is transplanted, the release commits and changelog hashes are remapped onto the rewritten commits, and its tags are translated to the destination's scheme with one boundary alias at the current version. The source loses the members, the releasable and its state in one commit, with the CI router re-synced and the snapshot regenerated. A mirrored releasable is extracted by promotion instead of by filtering: the destination is cloned from the mirror and adopts the standalone history consumers already resolve, with the monorepo-to-mirror commit correspondence derived by subtree split and recorded in the destination's transition record. A promotion refuses a mirror whose contract is violated or whose split ancestry cannot be established, and one whose tree is behind the source. Refuses a releasable owning the root member, and a remaining member that depends on a departing one (naming the rewrite command that severs the edge). Use --dry-run to see the whole plan first.

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

#Flags

Flags
NameShortTypePresenceEnvDescription
--delete-with-rm, --no-delete-with-rmbooloptionalDelete the departed members' directories with a plain recursive rm instead of saferm (which is what an unset flag means). Without it, a missing saferm is a hard error rather than a silent downgrade to an unrecoverable delete.

#Arguments

Arguments
NameTypePresenceDescription
releasable_namestrrequiredName of the releasable group in workspace.toml to extract, with every member it owns
target_pathstrrequiredFilesystem path where the new repository will be created (must not exist)

#monorepo absorb

Absorb an external repository into this workspace as a releasable. The source's history is rewritten under the destination path and merged in (full history, rewritten paths), its version tags are imported under the destination's tag scheme with one boundary alias at the current version, and its whole release state -- changelog, release archives with their release commits, config and version -- moves into a releasable's state directory with every hash and release commit remapped onto the rewritten commits. Without --releasable a singleton releasable named after the member is created, with its tag_format written explicitly. Nothing is fetched as a tag, so a tag this repository already owns is never moved or deleted; a colliding tag name or version is refused before anything is written. A crashed run is completed by re-running it. Use --dry-run to see the whole plan first.

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

#Flags

Flags
NameShortTypePresenceEnvDescription
--namestroptionalWorkspace member name for the absorbed package (the basename of the destination path when omitted)
--registry-namestroptionalPackage registry identity recorded in workspace.toml (used verbatim for name checks)
--releasablestroptionalAn existing releasable group to join. When omitted, a singleton releasable named after the member is created for it.
--tag-formatstroptionalThe tag format of the releasable this command creates, e.g. "{name}@v{version}" or "pkgs/thing/v{version}". Derived from the member's primary target when omitted; required when its targets span both tag schemes. Illegal with --releasable, which brings its own format.
--delete-with-rm, --no-delete-with-rmbooloptionalDelete the per-package release state that moves to the releasable with a plain recursive rm instead of saferm (which is what an unset flag means). Without it, a missing saferm is a hard error rather than a silent downgrade to an unrecoverable delete.

#Arguments

Arguments
NameTypePresenceDescription
source_repostrrequiredFilesystem path to the external git repository to absorb
dest_pathstrrequiredDestination directory (and workspace member path) the source repo's history is rewritten under

#monorepo cleanup

Remove per-package release-state residue from releasable member packages: .rlsbl/changes/, .rlsbl/releases/, .rlsbl/bases/, .rlsbl/lint/, .rlsbl/version, per-package CHANGELOG.md, and .rlsbl/config.json when identical to the releasable-level config. Per-package hooks/ directories are preserved (live feature), and members whose path is the workspace root are exempt. Deletions go through saferm (audit trail, recoverable) and are committed automatically. Detect residue first with rlsbl check --name releasable-residue.

Effect: mutating

#monorepo rename-releasable

Rename a releasable group. Rewrites the [[releasables]] name and every member's releasable field in workspace.toml (preserving comments), moves the state directory, drops the stale changelog validation cache, re-runs monorepo sync, and commits it all as one commit. When tag_format contains {name}, a boundary alias tag for the current version is created at the old tag's commit and pushed; historical releases stay under the old prefix. Idempotent: re-running heals a crash between the commit and the tag push.

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

#Arguments

Arguments
NameTypePresenceDescription
old_namestrrequiredCurrent name of the releasable group in workspace.toml
new_namestrrequiredNew name for the releasable group in workspace.toml and state directories

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