Run real software inside lightweight WebAssembly sandboxes from JavaScript, Python, or Rust.
The Wasmer SDK turns packages from the Wasmer registry into composable sandboxes. Add Python, PostgreSQL, Edge.js, PHP, shell tools, or your own package; give the sandbox files and capabilities; then run commands or keep long-lived processes under your control.
import { Wasmer } from "@wasmer/sdk/node";
const wasmer = new Wasmer();
const sandbox = await wasmer.sandboxes.create({
packages: ["python/python@=3.13.20"],
files: { "hello.py": "print('Hello from Wasmer')" },
});
const output = await sandbox
.command("python", ["/workspace/hello.py"])
.run();
console.log(output.text());The same package, sandbox, command, process, filesystem, and port model is available in every language SDK.
- Unix commands in an interactive browser shell — wasmer.sh application
- pnpm with outbound browser networking over WISP — wasmer.sh, backed by the WASIX Epoxy package
- A PHP website rendered from a browser WASIX server — JavaScript service-worker example
- Python 3.13 — JavaScript example, Python example, Rust example
- A Node.js-compatible HTTP server with Edge.js — JavaScript example, Python example, Rust example
- PostgreSQL 18 with a standard native
psqlclient — JavaScript example, Python example, Rust example - Python, Edge.js, PHP, and shell tools in one sandbox — JavaScript example, Python example, Rust example
The examples share the guest programs in fixtures/, so each SDK
runs the same Edge.js server, Python program, and PostgreSQL query.
A Wasmer client owns package resolution, workers, networking, and the local
cache. wasmer.packages resolves reusable packages.
wasmer.sandboxes.create() composes packages, files, environment variables,
mounts, and network access into an isolated workspace.
Commands belong to a sandbox:
command(...).run()captures a finite command and fails on an unsuccessful exit by default.command(...).spawn()starts a live process with stdin, stdout, stderr, termination, and exit status.sandbox.fsreads and writes the guest filesystem.sandbox.portswaits for guest services without inventing a separate server abstraction.sandbox.installPackage()adds software after the sandbox has started.
There is deliberately no client-level run() shortcut. Every execution has an
explicit sandbox, which keeps package composition, files, capabilities, and
process lifetime visible.
JavaScript and Python callers can pass check: false or check=False when a
non-zero status is expected. Spawned-process wait() remains unchecked so
applications can inspect every exit reason directly.
| Language | Package | Guide |
|---|---|---|
| JavaScript | npm install @wasmer/sdk |
JavaScript SDK |
| Python | pip install wasmer-sdk |
Python SDK |
| Rust | Workspace/Git while crate publishing is disabled | Rust SDK |
JavaScript runs Wasmer and WASIX directly in WebAssembly through
wasm-bindgen; Node networking is bridged through node:net and node:dns,
not a native addon. Python uses the Rust SDK through a Python-independent
UniFFI library. Rust uses Wasmer natively.
The SDK uses .wasmer in the working directory by default. Native Rust,
Python, and Node.js clients share the same registry metadata and downloaded
package data. Native compiled artifacts live in target-specific cache
partitions, while JavaScript keeps its runtime-specific data separate.
Set a different cache root when an application needs another location. Commit
neither .wasmer nor compiled artifacts to source control.
Each SDK guide contains its own build and test commands:
CI runs the Rust and UniFFI foundation first, then JavaScript and Python in parallel. Cargo outputs, Wasmer registry/package data, and target-specific compiled artifacts are cached independently.
The SDK is currently alpha. Its cross-language shape is intentional, but error codes and less common capabilities may still evolve. For the architectural rationale, read the Universal Wasmer SDK WARP.