A modular Rust toolkit for Minecraft launchers and reusable application infrastructure.
Elemental provides a typed pipeline for discovering versions, preparing
instances, resolving Java runtimes, and launching vanilla or modded Minecraft.
It also contains standalone building blocks for version-aware persistence and
migrations, type-indexed object pools, download infrastructure, and manifest
schemas. Use elemental-kit end to end, or adopt the individual crates in other
Rust applications.
Note
Elemental is under active development. The support matrix below reflects current workspace coverage, not a stability guarantee. See ROADMAP.md for current scope and known gaps.
- End-to-end lifecycle: catalog, inspect, prepare/install, load, build a launch command, and launch.
- Loader-aware design: dedicated flows for Vanilla, Fabric-like, installer-driven, and profiled legacy distributions.
- Typed storage and layouts: game roots, instances, libraries, assets, and
version artifacts resolve through
StorageandLayout. - Runtime validation: use an explicit Java executable or discover a compatible local runtime from the Minecraft version metadata.
- Reusable infrastructure:
elemental-sharedfor versioned persistence and migrations,elemental-objectfor type-indexed object pools,elemental-infrafor downloads, andelemental-schemafor manifests. - Flexible adoption: use the
elemental-kitfacade end to end or pick the individual async crates for another Rust application.
| Family | Drivers | Catalog | Inspect | Install | Load installed | Launch |
|---|---|---|---|---|---|---|
| Vanilla | Vanilla | Yes | Yes | Yes | Yes | Yes |
| Fabric ecosystem | Fabric, Legacy Fabric, Babric, Quilt | Yes | Yes | Yes | Yes | Yes |
| Installer-driven | Forge, NeoForge, CleanroomMC, Outlands | Yes | Yes | Yes | Yes | Yes |
| Profiled legacy | Rift, LiteLoader | Yes | Yes | Yes | Yes | Yes |
- Rust 1.85 or newer. The workspace uses edition 2024.
- A compatible Java runtime for launching Minecraft. Elemental can discover a
local runtime or use a custom runtime provider supplied with
--runtime-path. - Network access for catalog and artifact downloads. Use
--local-onlywhen the instance is already prepared.
git clone https://github.com/ElectronicWave/Elemental.git
cd Elemental
cargo run -p launchpad -- --help
cargo run -p launchpad -- listLaunchpad writes to .minecraft by default. Running it without launch
arguments opens the interactive wizard:
cargo run -p launchpadFor non-interactive launches, pass the driver id and optional versions directly. Other drivers accept the same storage, runtime, and local-only options:
cargo run -p launchpad -- forge 1.20.1 47.3.1
cargo run -p launchpad -- --local-only fabric 1.20.1 0.16.10 --instance-name MyFabric-1.20.1
cargo run -p launchpad -- vanilla 1.20.1 --instance-name MyVanilla-1.20.1Launchpad defaults live in
crates/launchpad/src/defaults.rs.
[dependencies]
anyhow = "1"
elemental = { package = "elemental-kit", version = "0.2" }
tokio = { version = "1", features = ["macros", "process", "rt-multi-thread"] }Prepare and launch a vanilla instance:
use anyhow::Result;
use elemental::{
core::auth::{authorizer::Authorizer, authorizers::offline::OfflineAuthorizer},
launcher::{DriverSpec, LaunchOptions, Launcher, RuntimeOptions},
};
#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<()> {
let launcher = Launcher::builder()
.storage_root(".minecraft")
.build();
let prepared = launcher
.prepare(
"Vanilla-1.20.1".to_owned(),
DriverSpec::vanilla("1.20.1".into()),
&RuntimeOptions::default(),
)
.await?;
let credential = OfflineAuthorizer {
username: "Player".to_owned(),
}
.authorize()
.await?;
let command = launcher
.build_launch_command(
&prepared,
&credential,
&RuntimeOptions::default(),
&LaunchOptions::default(),
)
.await?;
let mut game = launcher.launch(command)?;
let status = game.child.wait().await?;
println!("Minecraft exited with {status}");
Ok(())
}Offline authentication keeps local development simple. Use a production
Authorizer for real player accounts. Authentication and launch are separate:
obtain a UserCredential, build a LaunchCommand, optionally customize its
arguments, then spawn it. Use prepare_with_session() to supply a configured
session while the launcher finishes and validates it.
Inspect and reopen an existing instance without preparing it again:
let instances = launcher.inspect_instances().await?;
for instance in instances {
println!("{} ({})", instance.instance_name, instance.driver.driver.id);
}
if let Some(instance) = launcher.inspect_instance("MyFabric-1.20.1".to_owned()).await? {
let prepared = launcher.load_instance(instance).await?;
println!("Loaded {}", prepared.driver().id);
}| Crate | Purpose |
|---|---|
elemental-kit |
Re-export facade for the library crates |
elemental-core |
Storage, runtime discovery, authentication, and launch primitives |
elemental-driver |
Distribution catalogs, families, and loader-specific logic |
elemental-launcher |
High-level launcher facade and instance lifecycle |
elemental-infra |
Download planning, materialization, and archive utilities |
elemental-shared |
Version-aware persistence and migrations |
elemental-object |
Type-indexed global and task-local object pools |
elemental-schema |
Mojang and modloader manifest types |
launchpad |
End-to-end CLI launcher |
elemental-kit re-exports the library crates under stable module names. It is
the single dependency for applications that want the launcher stack and the
reusable infrastructure together.
| Module | Package | Feature |
|---|---|---|
elemental::core |
elemental-core |
core |
elemental::driver |
elemental-driver |
driver |
elemental::launcher |
elemental-launcher |
launcher |
elemental::infra |
elemental-infra |
infra |
elemental::object |
elemental-object |
object |
elemental::shared |
elemental-shared |
shared |
elemental::schema |
elemental-schema |
schema |
full enables every module. The default feature set is full plus
shared-json and object-notify.
Common launcher types are available through the prelude:
use elemental::prelude::*;The prelude only re-exports types from enabled modules, so it works with a selective feature set.
For a smaller dependency surface, disable default features and select only the modules an application uses:
[dependencies]
elemental = {
package = "elemental-kit",
version = "0.2",
default-features = false,
features = ["launcher"],
}Forwarded features:
| Feature | Effect |
|---|---|
shared-json |
Enables elemental-shared/json |
shared-toml |
Enables elemental-shared/toml |
infra-serde |
Enables elemental-infra/serde |
object-notify |
Enables elemental-object/notify |
Important
Forwarded features do not enable the facade module itself. With
default-features = false, enable both shared and shared-json when using
JSON persistence, shared and shared-toml for TOML, and object plus
object-notify when waiter support is required. Enable both infra and
infra-serde when downloader events or reports need serialization.