npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@everruns/bashkit-web

v0.14.2

Published

Sandboxed bash interpreter for the browser (WebAssembly). Single-threaded — no SharedArrayBuffer, no COOP/COEP headers.

Readme

@everruns/bashkit-web

Sandboxed bash interpreter for the browser, compiled to WebAssembly.

Unlike a WASI-threads build, this package is single-threaded: it needs no SharedArrayBuffer and no cross-origin isolation (COOP/COEP) headers. That makes it a drop-in for any web app — including embedded and third-party iframe contexts where those headers can't be set.

For Node.js / Bun / Deno, use the native package @everruns/bashkit instead.

Install

npm install @everruns/bashkit-web

Quick start

import { initBashkit, Bash } from "@everruns/bashkit-web";

// Load the .wasm once before constructing Bash.
await initBashkit();

const bash = new Bash();
const result = bash.executeSync('echo "Hello, browser!" | tr a-z A-Z');
console.log(result.stdout); // HELLO, BROWSER!

Plain <script type="module"> (no bundler)

<script type="module">
  import { initBashkit, Bash } from "https://esm.sh/@everruns/bashkit-web";
  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 / GraphQL request) are awaited by execute() — the async 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);

ctx is { name, argv, stdin, env, cwd, fs }. Return the builtin's stdout as a string (or a Promise<string>); throwing becomes stderr with exit code 1.

ctx.fs is a live handle to the same virtual filesystem the script sees, so a builtin can read inputs and write outputs that later commands pick up:

const bash = new Bash({
  customBuiltins: {
    "uppercase-file": (ctx) => {
      const text = ctx.fs.readFile(ctx.argv[0]);
      ctx.fs.writeFile("/out.txt", text.toUpperCase());
      return "done\n";
    },
  },
});
bash.writeFile("/in.txt", "hello\n");
await bash.execute("uppercase-file /in.txt && cat /out.txt"); // -> HELLO

ctx.fs has readFile, writeFile, appendFile, exists, mkdir, remove, and ls — the same surface as the Bash VFS helpers below.

Sync vs async

  • executeSync(cmd) — for plain bash and jq. Fast, returns an ExecResult directly. Throws if the script suspends (async builtin, sleep, background job).
  • execute(cmd) — returns Promise<ExecResult>. Required whenever an async custom builtin may run.

Options

new Bash({
  username, hostname, cwd,
  env: { KEY: "value" },
  maxCommands, maxLoopIterations, maxMemory,
  files: { "/config.json": '{"debug":true}' },
  customBuiltins: { name: (ctx) => "..." },
});

Virtual filesystem

Files created via the helpers are visible to scripts and vice versa:

bash.mkdir("/data");
bash.writeFile("/data/x.txt", "hi\n");
bash.appendFile("/data/x.txt", "there\n");
bash.readFile("/data/x.txt"); // "hi\nthere\n"
bash.exists("/data/x.txt");   // true
bash.ls("/data");             // ["x.txt"]
bash.executeSync("cat /data/x.txt").stdout; // "hi\nthere\n"
bash.remove("/data/x.txt");

// bash.fs() returns the same live handle passed to builtins as ctx.fs
const fs = bash.fs();

What's included

Plain bash plus the built-in text tooling (grep, sed, awk, jq, find, …) and jq. Not included in the browser build: outbound HTTP (curl/wget), ssh, sqlite, and embedded python — these need sockets, threads, or a host filesystem the browser sandbox doesn't provide. Bridge to the network through a custom builtin (see above) so requests go through your app's own fetch.

Limitations

  • No wall-clock timeout. wasm32-unknown-unknown has no reliable timer driver, so timeoutMs is not enforced. Runaway scripts are instead bounded by maxCommands, maxLoopIterations, and the parser fuel budget — a while true loop throws a resource-limit error rather than hanging.
  • executeSync can't run async builtins. The single-threaded event loop can't settle a Promise without yielding; an async builtin under executeSync fails fast with a clear message. Use execute().

Examples

Runnable browser demos live in example/ — an interactive terminal and an async-builtin/ctx.fs demo, both served by any static file server with no special headers. See example/README.md.

Development

# Build the bundle and run the headless integration tests:
bash scripts/build.sh
node --test __test__/bashkit-web.test.mjs
# or, from the repo root:
just build-web

License

MIT — part of the Bashkit project.