Getting Started
From a single .as file to a running wasm module, and
from there to a script living inside a Rive file.
Compiling directly
rasc is one binary. Point it at an entry file:
rasc main.as -o main.wasm --runtime stub --lib /abs/path/to/std/assembly
Anything that allocates a managed object — strings, arrays, classes — needs a
--runtime. Without one, new C() is a compile error
(“managed classes need a runtime”). Pass --lib as an
absolute path unless you run from the compiler’s package root.
A first module
export function greet(name: string): string {
return "hello, " + name;
}
import { greet } from "./greeting";
declare function print(s: string): void;
export function main(): i32 {
print(greet("rasc"));
return 0;
}
Three things to notice:
exporton entry-file declarations becomes a wasm export; compilation is whole-program from the entry file, so only what its exports reach gets compiled.- Relative imports resolve against the importing file; bare specifiers
resolve against
--lib. declare functionbecomes a wasm import — from moduleenvby default, or from a named import module when declared inside an ambient namespace (see Host Bindings).
Writing a Rive script
Inside a Rive project, scripts are .as files in a project with
scripting: wasm set in rive.yaml, plus a
rascStd: key (or RIVE_RASC_STD) pointing at rasc’s
std/assembly. A script is an exported class extending one of the
protocol bases in rive/host — Node,
Layout, Converter, PathEffect,
ListenerAction, TransitionCondition or
Interpolator. The base is the protocol the host drives the script
as, and only the hooks the class overrides are ever called:
import { Layout, Context } from "rive/host";
export class Spin extends Layout {
total: f64 = 0;
@input speed: f64 = 1;
override init(context: Context): bool {
context.log("hello from rasc");
return true;
}
override advance(seconds: f64): bool {
this.total += seconds * this.speed;
return true;
}
}
Each file’s scripts compile into their own script module asset; the
editor synthesizes the entry file that imports every script and registers it. An
.as file without an exported protocol class is a
library — importable from other scripts, never emitted as a script asset.
A Rive file can carry Luau and rasc scripts side by side — one module per language per file. There is one runtime underneath (WAMR on native, the browser engine on web); the languages are compilers targeting the same substrate, and the library ecosystem stays shared.
Iterating
The default compile is deliberately unoptimized and fast — about 10 ms for a 375 KB module, a couple hundred milliseconds for a project-scale build. That is the edit loop: compile, instantiate (~1 ms), running on the interpreter in a fraction of a second. Production speed comes from AOT, which the editor compiles in the background — see Execution Lanes.
Useful while iterating:
--wat— also print the module as WebAssembly text.rasc check file.as— diagnostics only; add--strictto fail on warnings,--jsonfor tooling.--tokens/--ast— dump the lexer or parser view of a file.