start

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:

shell
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

greeting.as
export function greet(name: string): string {
    return "hello, " + name;
}
main.as
import { greet } from "./greeting";

declare function print(s: string): void;

export function main(): i32 {
    print(greet("rasc"));
    return 0;
}

Three things to notice:

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/hostNode, 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:

spin.as
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.

mixing languages

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: