native runtime · tier-up cranelift JIT · AOT to a single binary
- Linux
x86_64,aarch64 - macOS Intel + Apple Silicon
- Windows
x86_64 - AOT
wlift --aot— ship a self-contained binary, no runtime install
Wren
was intended to be small and embedded. Wrenlift flips that:
it runs your .wren files directly as standalone, portable scripts
and apps. Zero runtime deps!.
One line gives you wlift (the runtime), hatch (the package + build tool), and wlift-lsp (the language server), pulled from the latest GitHub Release, SHA256-verified, and dropped into ~/.local/bin — or %LOCALAPPDATA%\Programs\wlift\bin on Windows, where the PowerShell installer also puts that directory on your PATH.
INSTALL_DIR.wlift and hatch land on your PATH.wlift hello.wren. That's it!# install (macos · linux) $ curl -fsSL wrenlift.com/install.sh | sh # install (windows, powershell) > irm wrenlift.com/install.ps1 | iex # verify $ wlift --version wlift 0.1.22 # run a script $ wlift hello.wren hello, world
macOS, building from source: cargo install strips
binaries, which invalidates the linker-generated adhoc
codesignature so macOS SIGKILLs them on spawn. Run
codesign --force --sign - ~/.cargo/bin/{wlift,hatch,wlift-lsp}
once after install.
Same source, multiple ABIs. The native build cross-compiles to Linux, Windows, and macOS; the wasm build runs interpreted or tier-up JIT'd in any modern browser. wlift --target wasm swaps the backend.
native runtime · tier-up cranelift JIT · AOT to a single binary
x86_64, aarch64x86_64wlift --aot — ship a self-contained binary, no runtime installwebassembly · tier-up wasm JIT
wasm32-unknownfetch, setTimeout, WebSocketWrenlift powers Hatch, and Hatch brings the ecosystem. Add a package, lock the version, and hatch run takes care of the rest. Same runtime under the hood.
# add a hatch package $ hatch add @hatch:http resolved 3 packages # run with the hatch cli — it wraps wlift $ hatch run path/to/myApp loading @hatch:http@0.3.0 loading @hatch:json@0.1.0 > standalone · serving :8080
When something goes wrong, Wrenlift doesn't just say "method not found." It points at the exact identifier, names the type involved, and tells you what to try next when it can.
Error: Counter does not implement 'tally' ╭─[counter.wren:22:34] │ 22 │ System.print("Final count: " + c.tally.toString) │ ─────┬─────── │ ╰─────── error occurred here │ │ Note: `Counter` has no getter or method `tally`. │ Did you mean to call it with `()`? ────╯