Skip to content

feat(install): one git install command, with the studio behind a studio feature - #343

Merged
LeadcodeDev merged 1 commit into
mainfrom
feat/install-cli-and-studio
Sep 26, 2026
Merged

LeadcodeDev merged 1 commit into
mainfrom
feat/install-cli-and-studio

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner
cargo install --git https://github.com/LeadcodeDev/rustmotion                     # CLI
cargo install --git https://github.com/LeadcodeDev/rustmotion --features studio   # CLI + studio

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:

error: multiple packages with binaries found: rustmotion, rustmotion-studio.
When installing a git repository, cargo will always search the entire repo for
any Cargo.toml.

That check is not about the workspace. Cargo scans the whole repository and
demands that exactly one package declare a [[bin]]. Two candidate escapes
were tested and both failed:

Attempt Result
default-members = ["crates/rustmotion", "crates/rustmotion-studio"] same error
required-features on rustmotion's bin, to hide it from the scan same error

So one package owns both binaries, and it has to be rustmotion: cargo install rustmotion from crates.io must keep delivering a command, which a crate reduced
to a [lib] does not.

That was blocked by a cycle. rustmotion-studio depended on rustmotion for
loader and encode, so making it a dependency of rustmotion is 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 second
package there is no cycle. Because lib.rs already declares extern crate self as rustmotion, every one of the studio's rustmotion::loader::… paths stays
valid 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, assets and the
engine extensions into a third crate that both sides depend on. It reaches the
same 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.

studio is out of the default build deliberately: 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 would have gone quietly blind. --workspace compiled the studio because
it 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:

Build Tests
default 1510
--features rustmotion/studio 1701 — the same total as before the merge

serde_json/preserve_order moves into the studio feature, not the
default. The studio rewrites the user's scenario files and must not reorder
their keys. validate --fix would want the same guarantee, but enabling it by
default changes the key order of every file it rewrites, which is a separate
decision and not this PR's.

Proof

$ cargo install --git file://$PWD --locked
   Installed package `rustmotion v0.7.1` (executable `rustmotion`)

$ cargo install --git file://$PWD --features studio --locked
   Installed package `rustmotion v0.7.1` (executables `rustmotion`, `rustmotion-studio`)

Both installed binaries then run: rustmotion --help lists all twelve
subcommands with their descriptions intact, rustmotion-studio --help prints
its own, and the feature-less CLI validates a scenario.

cargo fmt --all --check, cargo clippy --workspace --all-targets --features rustmotion/studio -- -D warnings and both test configurations are clean.

Also in here

  • publish = false is gone with the package. The studio's git dependency that
    blocked publishing is long gone — Cargo.lock has zero git+ sources and
    both gpui crates resolve from the registry — so the flag was stale.
  • docs/studio-dioxus-notes.md: the studio's DIOXUS_NOTES.md had nowhere left
    to 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.
  • The cli/mod.rs note claiming a studio subcommand is impossible was
    rewritten: it is possible now and still unwanted, because it would have to
    vanish from --help depending on the feature.

@LeadcodeDev LeadcodeDev added the enhancement New feature or request label Sep 26, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 26, 2026
@LeadcodeDev
LeadcodeDev added this pull request to stack #346 September 26, 2026 22:03
`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
LeadcodeDev force-pushed the feat/install-cli-and-studio branch from 5a1fc40 to 4537732 Compare September 26, 2026 22:03
@LeadcodeDev
LeadcodeDev merged commit 0fc86d3 into main Sep 26, 2026
4 checks passed
@LeadcodeDev
LeadcodeDev deleted the feat/install-cli-and-studio branch September 26, 2026 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant