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

@torkbot/sandbox

v0.1.1

Published

A TypeScript-first Node.js library for spawning libkrun-backed microVMs.

Readme

Sandbox

Sandbox is a TypeScript-first Node.js library for spawning libkrun-backed microVMs.

The target shape is:

  • boot a guest from a prebuilt read-only rootfs artifact, likely EROFS,
  • mount host-implemented virtual filesystems,
  • intercept guest HTTP request headers through host TypeScript hooks,
  • communicate with guest init over a bidirectional transport,
  • ship as a statically linked host artifact.
import {
  acceptPublicInternet,
  acceptTcp,
  binding,
  linuxOverlayFs,
  mount,
  prebuiltRootfs,
  projectInit,
  projectKernel,
  scratchFs,
  createSandbox,
  type SandboxWritableFileSystem,
} from "@torkbot/sandbox";

declare const workspaceFs: SandboxWritableFileSystem;

await using sandbox = createSandbox({
  kernel: projectKernel(),
  init: projectInit(),
  rootfs: linuxOverlayFs({
    lower: prebuiltRootfs("dist/rootfs/sandbox.erofs", { format: "erofs" }),
    upper: scratchFs(),
  }),

  mounts: [
    mount("/sandbox", {
      async stat(path) {
        if (path === "/") {
          return {
            type: "directory",
            sizeBytes: null,
            mediaType: null,
            modifiedAtMs: null,
          };
        }

        if (path === "/status.json") {
          const body = JSON.stringify({ ready: true });
          return {
            type: "file",
            sizeBytes: Buffer.byteLength(body),
            mediaType: "application/json",
            modifiedAtMs: null,
          };
        }

        throw new Error(`missing path ${path}`);
      },

      async list(path) {
        if (path !== "/") throw new Error(`missing directory ${path}`);
        return [{ name: "status.json", type: "file" }];
      },

      async read(input) {
        if (input.path !== "/status.json") {
          throw new Error(`unknown virtual file: ${input.path}`);
        }

        return Buffer.from(JSON.stringify({ ready: true }));
      },
    }),
  ],

  bindings: [
    binding("/workspace", workspaceFs),
  ],

  network: {
    outbound: {
      policy: "deny",
      rules: [
        acceptTcp({ cidr: "127.0.0.1/32", ports: [8080] }),
        acceptPublicInternet({ ports: [443] }),
      ],
    },
  },
});

sandbox.http.onRequest({ origin: "https://api.github.com" }, (request) => {
  request.headers.set("authorization", `Bearer ${process.env.GITHUB_TOKEN}`);
});

await using vm = await sandbox.run();

Incremental guest operations are explicit:

const result = await vm.control.exec({
  id: "tests",
  argv: ["node", "--test", "test/**/*.test.ts"],
});

if (result.exitCode !== 0) {
  throw new Error(result.stderr);
}

Mounted filesystems expose both the raw callback shape and a host-side tool surface for agent workflows:

const sandboxProc = vm.mounts.virtualFs("/sandbox");
const statusBytes = await sandboxProc.read({
  path: "/status.json",
  signal: AbortSignal.timeout(1_000),
});

console.log(JSON.parse(Buffer.from(statusBytes).toString("utf8")));

const workspace = vm.mounts.host("/workspace");

const notes = await workspace.read({
  path: "notes.md",
  offset: 1,
  limit: 80,
});

await workspace.write({
  path: "plan.md",
  content: "# Plan\n\nStart here.\n",
});

await workspace.patch({
  path: "plan.md",
  edits: [{ oldText: "Start here.", newText: "Ship the narrow slice." }],
});

const grep = await workspace.bash({
  command: "grep \"Ship\" plan.md",
  timeoutMs: 1_000,
});

Root filesystems are immutable by default. A writable root is expressed as an explicit Linux overlayfs composition:

await using sandbox = createSandbox({
  kernel: projectKernel(),
  init: projectInit(),
  rootfs: linuxOverlayFs({
    lower: prebuiltRootfs("dist/rootfs/base.erofs", { format: "erofs" }),
    upper: scratchFs(),
  }),
});

await using vm = await sandbox.run();

await vm.control.exec({
  id: "install-toolchain",
  argv: ["/bin/sh", "-lc", "apk add --no-cache git nodejs"],
});

mount(...) means a guest-visible mount boundary. binding(...) means a host-side attachment point into the same filesystem abstraction and does not create a guest mount.

The guest contract is intentionally narrow:

  • / is read-only unless the rootfs is a linuxOverlayFs(...) composition.
  • /sandbox is implemented by the host.
  • HTTP request-header hooks are registered in TypeScript and enforced by the Rust host data plane.
  • Network egress starts from deny; outbound rules opt in the exact protocols, ranges, and ports the guest can reach.
  • The HTTP interception CA is generated and injected by Sandbox. Callers provide request-header hooks, not certificate plumbing.

Design Targets

  • no dynamic libkrun or libkrunfw dependency in the final host artifact,
  • a signed sandbox-host process for the Node/Rust host boundary,
  • custom guest init owned by this repo,
  • implicit fd-backed host control sockets owned by Sandbox,
  • avoid host filesystem coordination unless it is intrinsic to the artifact; prefer file descriptors, database handles, bytes, and async iterables over paths,
  • build-time rootfs shaping, with prebuilt rootfs artifacts supplied at VM instantiation,
  • root filesystem composition through small explicit primitives such as linuxOverlayFs(...) and scratchFs(), with lower and upper expressed as filesystem values,
  • mount(...) only for guest-visible mounts; binding(...) only for host-side attachment points,
  • programmable virtual filesystems backed by TypeScript callbacks,
  • transparent HTTP interception with TypeScript request-header hooks,
  • default-deny outbound networking with explicit accept rules for protocols, CIDR ranges, public internet reachability, and ports,
  • Rust-native or statically linkable networking components; sidecar network daemons are references, not default runtime dependencies,
  • macOS HVF entitlement signing verified as part of the integration test flow.

Repository Layout

  • src/: TypeScript API consumed by Node.js callers.
  • crates/sandbox-host: signed VM-host helper used for macOS HVF launch.
  • crates/sandbox: Rust host implementation that owns the libkrun boundary and host services.
  • crates/sandbox-init: custom guest init used to configure the guest before supervising untrusted code.
  • tests/e2e: TypeScript e2e scenarios run directly by Node.js 24+ type stripping.

See docs/architecture.md for the initial design.

Kernel artifacts are built separately from runtime VM creation. See docs/kernel-build.md for the Docker-based deps/libkrunfw build entrypoint. See docs/testing-strategy.md for the integration and e2e verification plan.

Publishing

The npm package is published as @torkbot/sandbox. It does not use post-install scripts. The root package contains the TypeScript API and declares platform artifacts as optional dependencies:

  • @torkbot/sandbox-darwin-arm64
  • @torkbot/sandbox-linux-x64-gnu

Each platform package contains the N-API binding and the sandbox-host helper for that target. Runtime artifact resolution only loads the installed optional dependency for the current platform. Local development uses the same layout by materializing the current platform package under node_modules.

macOS signing setup

For now, the macOS sandbox-host artifact is not Developer ID signed or notarized. This is an explicit, possibly temporary workaround for publishing before this project has an Apple Developer account.

macOS users must sign the installed helper locally before launching a VM:

npx @torkbot/sandbox setup-macos

This performs an ad-hoc local codesign with the com.apple.security.hypervisor entitlement required by Hypervisor.framework. It does not contact Apple and does not require an Apple Developer account. If a macOS user tries to launch a VM before running setup, Sandbox throws a runtime error that points back to this command.

The release workflow verifies the tag, builds platform packages on their native runners, publishes the platform packages first, and then publishes the root package. That keeps the installable root package from pointing at missing optional artifacts while staying as close as npm allows to a single coordinated release operation.

Local release packaging sanity check:

npm run release:pack

After rebuilding local native artifacts, refresh the local optional package layout with:

npm run artifacts:link-current