Skip to content

cortesi/grunt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Grunt

Compile Rust scripts fast. Run them safely.

Grunt is a Rust runtime for generated or user-authored Rust scripts. It compiles scripts to wasm32-wasip2, returns structured diagnostics on compile errors, and executes successful builds inside a bounded Wasm sandbox.

It is built for tight loops:

  • Write or generate script code.
  • Compile and read machine-friendly diagnostics.
  • Retry quickly.
  • Execute with strict runtime limits.

Why Grunt

  • Fast rebuild loop with persistent artifact caching.
  • Structured compile errors (line/column, error codes, warnings, raw output).
  • Strong default limits (timeout, memory cap, deny-all WASI policy).
  • Typed host/guest contract with serde + postcard.
  • Concurrency support for parallel script preparation.

Architecture at a Glance

Rust source
   |
   v
Forge: template workspace + cargo build + diagnostics + artifact cache
   |
   v
Wasm component
   |
   v
Vault: Wasmtime engine + limits + timeout + host dispatch
   |
   v
Typed Rust result (or structured error)

For the full design, see docs/spec.md.

Quick Start (Demo CLI)

Prerequisites

  • Rust toolchain with Cargo.
  • wasm32-wasip2 target installed:
rustup target add wasm32-wasip2

Run the demo

From the repository root:

cargo run -p demo -- run demo/examples/success.rs

Try failure paths:

cargo run -p demo -- run demo/examples/compile_error.rs
cargo run -p demo -- run demo/examples/trap.rs

Inspect or reset demo cache:

cargo run -p demo -- cache info
cargo run -p demo -- cache reset

Notes:

  • Demo state defaults to ./demo_data.
  • Use --root-dir <path> to isolate state.
  • Use --no-warmup to skip startup warmup build.

Library Quick Start

use std::path::PathBuf;
use std::time::Duration;

use grunt::{Config, Grunt, TemplateSpec, WasiPolicy};

#[tokio::main]
async fn main() -> Result<(), grunt::Error> {
    let mut config = Config::new(
        PathBuf::from("./grunt_data"),
        TemplateSpec::default(),
        Box::new(()),
    );
    config.wasi_policy = WasiPolicy::deny_all();
    config.execution_timeout = Duration::from_secs(5);

    let grunt = Grunt::new(config).await?;

    let source = r#"
use prelude::*;

#[grunt_guest::main]
fn execute(req: u32) -> Result<u32, String> {
    Ok(req * 2)
}
"#;

    let compiled = grunt.prepare(source).await?;
    let prepared = compiled.bind::<u32, u32>();
    let value = prepared.execute(21, ()).await?;
    assert_eq!(value, 42);

    Ok(())
}

Host Functions

Define host functions in the runtime with register_host_fn!, then call them from scripts with grunt_guest::declare_host_fns!.

See a full end-to-end example in crates/grunt/tests/db_example.rs.

License

MIT.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages