TachiSnap
TachiSnap — Pixel Snapper for animation pixel artists. Rust + WebAssembly client-side tool for cleaning up AI-generated…
WASI-powered modding for the Bevy engine
git clone https://github.com/wasvy-org/wasvy.gitwasvy-org/wasvy
Thanks AreKayHen for the lovely banner art!
🪺 Just hatched: This project is in the process of stabilization. Some features are still missing and breaking API changes are likely to happen as we approach a 1.0 release. Use at your own risk!
🎯 Community Feedback: Your ideas, suggestions, and contributions are highly valued! Come and talk with us in the Bevy Discord. Report bugs and discuss new features on Github. Together, we can shape this into something great!
💡 TIP: Check out the
justfilefor useful commands and as a reference for common operations in the project.
Wasvy is an experimental Bevy modding engine, enabling the execution of WebAssembly (WASM) binaries within Bevy applications. It's powered by WebAssembly System Interface (WASI), enabling full access to the Bevy ECS, network, filesystem, system clock and more!
wasvy CLI: cargo install wasvy_cliInstall the wasvy CLI:
cargo install wasvy_cli
If you are developing rust mods, install the necessary target:
rustup target add wasm32-wasip2
Add the crate to your dependencies:
cargo add wasvy
use bevy::prelude::*;
use bevy::{DefaultPlugins, app::App};
// Get started by importing the prelude
use wasvy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// Adding the [`ModLoaderPlugin`] is all you need 😉
// And enable the devtools for CLI access ⚡
.add_plugins(ModLoaderPlugin::default().devtools("My moddable Bevy app"))
.run();
}
Start your app with Wasvy devtools enabled (shown above). Make sure to enable asset hot-reloading!
cargo run --features bevy/file_watcher
The wasvy new command helps creating new Mods. In another terminal, scaffold a new Rust mod:
wasvy new my-bevy-mod # Or in another language, such as python (requires poetry) wasvy new another-bevy-mod -l py
The wasvy CLI connects to your running Bevy app, and uses metadata such as the wit interfaces of your game to scaffold a new mod that is compatible.
Now, here comes the fun part! Let's build and load the mods you've created:
wasvy dev
If you make changes to your Mod's code, wasvy dev will automatically rebuild the Mod and instruct the game to load it!
Search for compatible mod sources within the current directory. Note that not all mods are compatible with all games.
wasvy list
Watch matching mods and reload them when their sources change:
wasvy dev --mods my-bevy-mod
Build and load a matching mod into the running app:
wasvy load --mods my-bevy-mod
Unload a matching mod:
wasvy unload --mods my-bevy-mod
Common options:
--path <PATH>: search or create from a different directory. Defaults to the current directory.--app <APP>: require the connected devtools app name to contain this pattern.--uri <URI>: connect to an alternate remote address.--mods <MODS>: filter source names for list, load, unload, and dev.For local development in this repository, you can use just cli
just cli search --path examples/mods
Mods are just compiled WebAssembly binaries using the wasvy wit interface (or your own).
wasvy new can help scaffolding new Mods, but it doesn't support all languages and use-cases. You can also create a mod manually by using the WebAssembly Component Model and defining your interfaces with WIT (WebAssembly Interface Types). Here's how to get started with a new mod written in Rust:
cargo new my-mod --lib cd my-mod
cargo.toml:[package]
name = "my-mod"
version = "0.1.0"
edition = "2024"
[dependencies]
# Hassle-less codegen for wit
wit-bindgen = "0.58.0"
# Wasvy uses json for serializing components. We use serde instead
# of bevy_reflect since at the moment bevy-reflect bloats the wasm binary considerably
serde = "1.0"
serde_json = "1.0"
# Import any bevy-sub crates for any components you will be using
# Note: enable the serialize feature to allow using serde
bevy_transform = { version = "0.19.0", features = ["serialize"], default-features = false }
bevy_math = { version = "0.19.0", features = ["serialize"], default-features = false }
[lib]
crate-type = ["cdylib"] # necessary for wasm
wit/world.wit. Here's a basic example:package component:my-mod;
/// An example world for the component to target.
world example {
/// This is the wit definition for wasvy's ecs access interface
use wasvy:ecs/app.commands;
/// An example system with a Commands system params
export my-system: func(commands: commands);
/// This is important.
/// This makes it so the WASM module must implement the guest required functions by the Bevy host.
include wasvy:ecs/guest;
}
For the latest version (v0.0.9) download and add the wit/*.wit file inside your wit folder manually like so (any file in this deps folder should be picked up during compile-time).
Note: Due to #40, and with the addition of the Cli in #60, usage of
wkg wit fetchpulling from wa.dev/wasvy:ecs is deprecated
my-mod/src/lib.rs as shown:wit_bindgen::generate!({
path: ["./wit"],
world: "component:my-mod/example",
with: {
"wasvy:ecs/app": generate,
}
});
use wasvy::ecs::app::{App, Commands, Schedule, System};
struct MyMod;
impl Guest for MyMod {
fn setup(app: App) {
// This must match the system we have defined in world.wit
// If you want more systems, just define more in wit
let system = System::new("my-system");
system.add_commands();
// Register the system, similarly as you would in a Bevy App
app.add_systems(&Schedule::ModStartup, vec![system]);
}
fn my_system(commands: Commands) {
println!("Hello from my mod!");
commands.spawn(&[
("example::Component".to_string(), "{}".to_string())
]);
}
}
export!(MyMod);
cargo build --target wasm32-wasip2 --release
The resulting .wasm file will be in target/wasm32-wasip2/release/my-mod.wasm.
Hint: The binary must be in your game's assets library for it to be visible to Bevy. By default this is assets in the same directory as src. Then, make sure to load it via Mods::load as shown above (e.g. mods.load("mods/my-mod.wasm")).
Want to see Wasvy in action? Start by running the basic app.
just run basicjust cli devIn the basic mod lib.rs, try altering the rotation direction of the cube.
Wasvy offers some example host apps to get started:
ModLoaderPlugin and the devtools to enable modding with Bevy. This also serves as a good sandbox for testing your mods.Since Wasvy is built on the wasm component model, mods can be written in almost any language. We provide a few examples for reference and experimentation:
MyMarker component. Spawns a custom component. Intended to be run with the Basic example app.MyMarker component. Spawns a custom component. Intended to be run with the Basic example app.MyMarker component. Spawns a custom component. Intended to be run with the Basic example app.Don't see an example in your favorite language? Consider contributing it to our repo! See the guidelines below.
Contributions come in many forms, and we welcome all kinds of help! Here's how you can contribute:
Using the project's Nix flake is the simplest way to get a working development environment.
direnv allow
Once allowed, direnv will automatically enter the development shell for this repository and provision the required tooling.
If you are not using Nix, install the required tooling manually:
justjust enable-git-hooksFor additional project commands, see the justfile.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)We're actively looking for:
You don't need to write code to help out! If you have an idea or suggestion, please:
Please make sure to:
wasvy CLIThis project (all code and files, excluding the assets directory) is dual-licensed under either:
The banner is by AreKayHen, Copyright 2026.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
more like this
TachiSnap — Pixel Snapper for animation pixel artists. Rust + WebAssembly client-side tool for cleaning up AI-generated…
.Net 10 (.Net 8+) webassembly starter project using raylib-cs nuget 7.0.2 and raylib 5.5
search projects, people, and tags