v0.1.16 · a fast standalone runtime for wren

Wren scripts, now standalone and portable.

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!.

standalone · no host required tiered JIT zero runtime deps
Wrenlift mascot — a wren bird strapped to twin rocket boosters, trailing flame and smoke

Quick setup.

One curl 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.

  1. Run the script. The default install dir is ~/.local/bin; override with INSTALL_DIR.
  2. Open a new shell so wlift and hatch land on your PATH.
  3. Run wlift hello.wren. That's it!
# install (macos · linux)
$ curl -fsSL wrenlift.com/install.sh | sh

# verify
$ wlift --version
  wrenlift 0.1.16 (release, jit)

# 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.

targets

Runs everywhere.

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.

Desktop

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
Web

webassembly · tier-up wasm JIT

  • WebAssembly   wasm32-unknown
  • Browser   main + worker, WebGPU canvas
  • Async bridges   fetch, setTimeout, WebSocket
packages & libraries

Pair with Hatch
for libraries.

Wrenlift 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
diagnostics

Errors that read like prose.

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.

  • 1Located. File, line, and column.
  • 2Source-anchored. Caret on the failing identifier.
  • 3Class-aware. Names the type, not just the symbol.
  • 4Actionable. Suggests the fix when it can.
counter.wren RUNTIME ERROR
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 `()`?
────╯
host embedding

Or embed it in your C host.

Drop-in for the upstream Wren C API. Same WrenVM, same WrenConfiguration. Grab the wrenlift.h shim, link libwrenlift.a, and your existing host keeps working.

  • API-compatible. wrenNewVM, wrenInterpret, wrenCall, foreign methods, slots: all of it.
  • One library, two modes. Same build powers wlift on the CLI and embeds inside your game, editor, or daemon.
  • Bring your own loader. WrenLoadModuleFn is honoured. Ship Hatch packages or your own modules.

Or embed it in your Rust host.

Wrenlift ships first-class Rust bindings. Reach for hatch_runner when you want the Hatch-aware runtime in two lines, or drop down to the raw capi externs for full VM control.

  • High level: hatch_runner. One HatchRunner::new(), then run_file(). Resolves Hatch packages automatically.
  • Low level: capi. extern "C" bindings to wrenNewVM, wrenInterpret, slots, foreign methods. unsafe when you need it.
  • Cargo-native. Add wren_lift to your Cargo.toml; the build links the static lib for you.

Or embed it in the browser.

One ES-module import, no build step, no toolchain. https://wrenlift.com/dist/wlift.js is the canonical CDN URL — call createWlift() and run Wren in the page or a worker. Same runtime, same diagnostics, async bridges already wired (fetch, setTimeout, WebSocket, DOM). An npm package with versioned tags is on the roadmap.

  • One factory: createWlift({ mode }). main for the page thread, worker for off-main; canvas + DOM bridges round-trip transparently.
  • Hatchfile-aware. runProject(wlift, src, hatchfileText) walks deps, fetches each .hatch bundle, and installs them before the user source runs.
  • Tier-up wasm JIT. Hot functions are emitted as fresh wasm modules at runtime (via wasm-encoder) and instantiated alongside the runtime — no extra dependency on the host browser's JIT.
#include "wrenlift.h"   // drop-in for <wren.h>
#include <stdio.h>

static void writeFn(WrenVM* vm, const char* text) {
  printf("%s", text);
}

int main(void) {
  WrenConfiguration cfg;
  wrenInitConfiguration(&cfg);
  cfg.writeFn = writeFn;

  WrenVM* vm = wrenNewVM(&cfg);

  wrenInterpret(vm, "main",
    "import \"greet\" for Greeter\n"
    "Greeter.hello(\"world\")\n");

  wrenFreeVM(vm);
  return 0;
}
// greet.wren — loaded by your host
class Greeter {
  static hello(name) {
    System.print("hello, %(name) ✦")
  }
}
# link against wrenlift
$ cc host.c -o host \
     -Iexamples \
     target/release/libwren_lift.a

$ ./host
  hello, world 
editor setup

Wire up your editor.

One-click install from the VS Code marketplace. Diagnostics, hover, goto-definition (cross-package), member completion after ., and an inline ▶ Run codelens — all driven by wlift-lsp, the language server bundled with every release.

  • Diagnostics + hover. Inline errors, type-aware hover cards on identifiers and calls.
  • Goto-definition. Local, workspace, and @hatch: dep sources — bundled .hatch sources extracted on demand.
  • Member completion after .. Receiver-aware suggestions.
  • Inline ▶ Run codelens. On main.wren and *.spec.wren; routes through hatch run when a hatchfile is in scope.
  • Auto-installs wlift-lsp. If the binary's missing, the extension offers a one-click install.sh and auto-restarts when the binary lands.

Or any LSP-speaking editor.

The same wlift-lsp binary the VS Code extension drives ships in every install tarball — drop it on PATH, point your editor at it, get the same diagnostics, hover, completion, and goto-definition surface.

  • Bundled. One install.sh drops wlift, hatch, and wlift-lsp on ~/.local/bin.
  • stdio transport. No socket setup, no daemon — your editor spawns the binary per workspace.
  • Editors. Helix, Neovim (vim.lsp 0.10+), and Zed configs in the panel; Sublime, Emacs, and Kakoune work from the same shape.
# install from a terminal
$ code --install-extension Wrenlift.vscode-wrenlift
  installed wrenlift v0.1.2

# open a .wren file — the LSP starts on first open.
# missing the wlift-lsp binary? the extension offers
# a one-click install and auto-restarts.
$ code hello.wren
# or install from the Extensions panel
  search Wrenlift · click Install

# direct marketplace URL
  marketplace.visualstudio.com
    /items?itemName=Wrenlift.vscode-wrenlift

# settings to override binary paths (optional):
  wrenlift.serverPath  // wlift-lsp
  wrenlift.wliftPath   // wlift
  wrenlift.hatchPath   // hatch