feat(install): one git install command, with the studio behind a studio feature - #343
Merged
Merged
Conversation
`cargo install --git https://github.com/LeadcodeDev/rustmotion` did not work at all before this: cargo refused it with "multiple packages with binaries found: rustmotion, rustmotion-studio". That check is not about the workspace — cargo searches the whole repository for any Cargo.toml and demands that exactly one package declare a `[[bin]]`. Verified, not assumed: neither `default-members` nor `required-features` changes the count. So one package has to own both binaries, and it has to be `rustmotion`, because `cargo install rustmotion` from crates.io must keep delivering a command. The studio was a package that depended on `rustmotion` for `loader` and `encode`, so making it a dependency of `rustmotion` was a cycle — which cargo refuses even for an optional dependency. It becomes a module instead: `crates/rustmotion/src/studio/`. With no second package there is no cycle, and because `lib.rs` already declares `extern crate self as rustmotion`, all of the studio's `rustmotion::loader::…` paths stay valid verbatim. The only code change is requalifying its 82 internal `crate::` paths to `crate::studio::`. The alternative — extracting `loader`, `encode`, `include`, `assets` and the `engine` extensions into a third crate — would have moved 14 900 lines and added two crates to the published set to reach the same command. cargo install --git <url> # CLI cargo install --git <url> --features studio # CLI + studio `studio` is out of the default build on purpose: it pulls gpui and a native GUI toolchain, which do not build everywhere the CLI builds, a headless server being the obvious case. Its seven dependencies are optional and the second `[[bin]]` carries `required-features = ["studio"]`. Two consequences worth naming. CI: `--workspace` used to compile the studio because it was a member. Behind a non-default feature it would not, so clippy and the tests would have stayed green over 11 600 lines nobody checks any more. Both jobs now pass `--features rustmotion/studio`. Test count is unchanged at 1701 with the feature, 1510 without. `serde_json/preserve_order` moves into the `studio` feature rather than the default: the studio rewrites the user's scenario files and must not reorder their keys. `validate --fix` would want the same thing, but turning it on by default would change the key order of every file it rewrites, which is a separate decision.
LeadcodeDev
force-pushed
the
feat/install-cli-and-studio
branch
from
September 26, 2026 22:03
5a1fc40 to
4537732
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Both verified by running them, not by reasoning about them — see Proof below.
Why this needed more than a manifest line
The bare command did not work at all before:
That check is not about the workspace. Cargo scans the whole repository and
demands that exactly one package declare a
[[bin]]. Two candidate escapeswere tested and both failed:
default-members = ["crates/rustmotion", "crates/rustmotion-studio"]required-featuresonrustmotion's bin, to hide it from the scanSo one package owns both binaries, and it has to be
rustmotion:cargo install rustmotionfrom crates.io must keep delivering a command, which a crate reducedto a
[lib]does not.That was blocked by a cycle.
rustmotion-studiodepended onrustmotionforloaderandencode, so making it a dependency ofrustmotionis a cycle —and cargo refuses one even for an optional dependency, which the old manifest
comment already said.
What it does instead
The studio becomes a module:
crates/rustmotion/src/studio/. With no secondpackage there is no cycle. Because
lib.rsalready declaresextern crate self as rustmotion, every one of the studio'srustmotion::loader::…paths staysvalid verbatim — the only code change is requalifying its 82 internal
crate::paths to
crate::studio::, plus rustfmt rewrapping the longer lines.The alternative was extracting
loader,encode,include,assetsand theengineextensions into a third crate that both sides depend on. It reaches thesame command, moves 14 900 lines instead of 11 600 unchanged ones, and adds two
crates to the published set. I started down it and backed out.
studiois out of the default build deliberately: it pulls gpui and a nativeGUI toolchain, which do not build everywhere the CLI builds — a headless server
being the obvious case. Its seven dependencies are optional, and the second
[[bin]]carriesrequired-features = ["studio"].Two consequences worth naming
CI would have gone quietly blind.
--workspacecompiled the studio becauseit was a member. Behind a non-default feature it does not, so clippy and the
tests would have stayed green over 11 600 lines nobody checks any more. Both
jobs now pass
--features rustmotion/studio. Test count is unchanged:--features rustmotion/studioserde_json/preserve_ordermoves into thestudiofeature, not thedefault. The studio rewrites the user's scenario files and must not reorder
their keys.
validate --fixwould want the same guarantee, but enabling it bydefault changes the key order of every file it rewrites, which is a separate
decision and not this PR's.
Proof
Both installed binaries then run:
rustmotion --helplists all twelvesubcommands with their descriptions intact,
rustmotion-studio --helpprintsits own, and the feature-less CLI validates a scenario.
cargo fmt --all --check,cargo clippy --workspace --all-targets --features rustmotion/studio -- -D warningsand both test configurations are clean.Also in here
publish = falseis gone with the package. The studio's git dependency thatblocked publishing is long gone —
Cargo.lockhas zerogit+sources andboth gpui crates resolve from the registry — so the flag was stale.
docs/studio-dioxus-notes.md: the studio'sDIOXUS_NOTES.mdhad nowhere leftto live. It documents a framework the studio no longer uses; moved rather than
deleted, since that is not this PR's call.
CLAUDE.md's "no comments" rule follows the folder now instead of the crate.The reasoning did not change with the merge.
cli/mod.rsnote claiming astudiosubcommand is impossible wasrewritten: it is possible now and still unwanted, because it would have to
vanish from
--helpdepending on the feature.