Get started in the browser (WASM)#
Run the Bashkit sandbox in the browser, at the edge, or in any JavaScript
runtime that can’t load a native addon. @everruns/bashkit-wasm is a slim,
single-threaded wasm-bindgen module: unlike a WASI-threads build it needs
no SharedArrayBuffer and no cross-origin isolation (COOP/COEP)
headers, so it drops into any web app — including embedded and third-party
iframe contexts where those headers can’t be set — and into edge/serverless
runtimes (Cloudflare Workers, Vercel Edge, Deno Deploy) that can’t use threads.
For server-side Node, Bun, or Deno where a native addon loads, prefer the faster
@everruns/bashkit NAPI package instead.
Install#
npm install @everruns/bashkit-wasm
First script#
Load the .wasm once with initBashkit() before constructing Bash:
import { initBashkit, Bash } from "@everruns/bashkit-wasm";
await initBashkit();
const bash = new Bash();
const result = bash.executeSync('echo "Hello, browser!" | tr a-z A-Z');
console.log(result.stdout); // HELLO, BROWSER!
Try it live#
This is the exact package above, running in your browser — no server, nothing you type leaves this page. Launch it and run some bash:
No bundler#
Straight from a CDN, in a plain <script type="module">:
<script type="module">
import { initBashkit, Bash } from "https://esm.sh/@everruns/bashkit-wasm";
await initBashkit();
const bash = new Bash();
document.body.textContent = bash.executeSync("seq 1 5 | paste -sd+ | bc").stdout;
</script>
Async custom builtins#
Register JS callbacks as bash commands. Async callbacks (e.g. issuing a fetch)
are awaited by the async execute() API:
const bash = new Bash({
customBuiltins: {
graphql: async (ctx) => {
const res = await fetch("/graphql", {
method: "POST",
headers: { "content-type": "application/json" },
body: ctx.stdin ?? "{}",
});
return await res.text();
},
},
});
const out = await bash.execute('echo "{ me { id } }" | graphql | jq .data');
console.log(out.stdout);
Caveats#
- It’s a
wasm-bindgenmodule: it runs in any JavaScript host but not a non-JS/WASI wasm runtime (wasmtime,wasmer). - Reduced feature set relative to the native bindings. Prefer
@everruns/bashkitwhen a native addon can load.
A full interactive terminal built on this package lives in
examples/browser
(single index.html on Vite, no build step, no special headers).
Next steps#
- Get started in Pyodide — for Python running in the browser.
- Sandbox configuration & limits — resource limits and sandbox options.
- Security — sandbox boundaries and what scripts cannot do.