Statically typed
Catch mistakes at compile time, not during a play session. No runtime type errors.
Statically typed
Catch mistakes at compile time, not during a play session. No runtime type errors.
Clean Rust interop
Derive WritObject on any Rust struct. Pass it straight into scripts — no wrappers, no copying.
Sandboxed by default
Scripts get zero access until you register it. File I/O, networking, syscalls — all opt-in.
Hot reload
Swap script bytecode mid-session without restarting. VM state and live coroutines survive.
Coroutines
yield suspends a function and resumes it next tick — no threads, no callbacks, no state machines.
Familiar syntax
Classes, structs, traits, enums, and when — if you know C# or GDScript, you’ll feel at home in minutes.
struct Vec2 { x: float y: float
func length() -> float { return sqrt(x * x + y * y) }}
class Player extends Entity { public health: float = 100.0 set(value) { field = clamp(value, 0.0, 100.0) }
public func takeDamage(amount: float) { health -= amount if health <= 0 { die() } }
func respawn() { yield seconds(3.0) // wait without blocking the host health = 100.0 setActive(true) }}use writ::Writ;
let mut vm = Writ::new(); // create a sandboxed VMvm.set_tick_source(|| engine.delta_time()); // drive coroutine timers from your enginevm.load("scripts/game.writ").unwrap(); // compile and load a scriptvm.call("onStart", &[]).unwrap(); // call any top-level function by name