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

@nimbus-sh/worker

v0.15.0

Published

Nimbus runtime package for Cloudflare Workers, re-exported publicly through @nimbus-sh/sdk/worker.

Readme

@nimbus-sh/worker

Run a Linux-like sandbox on Cloudflare Workers. A session gets a filesystem, a shell, real processes, and ports you can reach from a browser, all inside one Durable Object.

This package is the Cloudflare half: the NimbusSession Durable Object, the router, the static assets, the facet machinery, and the auth internals. The filesystem, shell, and WASI runtime layer live in @nimbus-sh/core, which this package composes on. Core also runs standalone in bun or node.

Import the deploy-time API from @nimbus-sh/sdk/worker. Install this package as well, because it carries the runtime implementation and the static assets that entrypoint serves.

Install

npm install @nimbus-sh/sdk @nimbus-sh/worker @nimbus-sh/config
# or
bun add @nimbus-sh/sdk @nimbus-sh/worker @nimbus-sh/config

Quickstart

src/index.ts:

import {
  NimbusSession,
  SupervisorRPC,
  NimbusAssetsRPC,
  NimbusLoaderRPC,
  NimbusLoadedWorker,
  NimbusLoadedEntrypoint,
  NimbusDurableObjectNamespace,
  NimbusDOStub,
  CirrusHmrRPC,
  createNimbusHandler,
} from '@nimbus-sh/sdk/worker';
import { defineNimbusConfig } from '@nimbus-sh/config';

// Re-export the DO + every RPC class so wrangler's `class_name` lookup +
// `enable_ctx_exports` find them in your Worker's main-module exports.
export {
  NimbusSession,
  SupervisorRPC,
  NimbusAssetsRPC,
  NimbusLoaderRPC,
  NimbusLoadedWorker,
  NimbusLoadedEntrypoint,
  NimbusDurableObjectNamespace,
  NimbusDOStub,
  CirrusHmrRPC,
};

const nimbusConfig = defineNimbusConfig({
  sandboxes: {
    default: {
      root: '/home/user',
      runtimes: { preinstall: ['python'], onDemand: true },
      tools: { namespace: 'sandbox', kind: 'sandbox' },
    },
  },
});

export default createNimbusHandler({
  sdk: {
    remote: true,
    config: nimbusConfig,
  },
});

wrangler.jsonc (use @nimbus-sh/config to generate, or adapt apps/hosted-demo/wrangler.jsonc):

{
  "name": "my-nimbus",
  "main": "src/index.ts",
  "compatibility_date": "2026-09-26",
  "placement": { "mode": "smart" },
  // Shell commands run in the session DO. The 30 s default kills long ones.
  "limits": { "cpu_ms": 300000 },
  "assets": {
    "directory": "node_modules/@nimbus-sh/worker/public",
    "binding": "ASSETS",
    "run_worker_first": ["/api/*", "/s/*", "/new"]
  },
  "alias": {
    "clean-git-ref": "clean-git-ref/lib/index.js",
    "is-git-ref-name-valid": "is-git-ref-name-valid/index.js",
    "crc-32": "crc-32",
    "sha.js": "sha.js",
    "pako": "pako", "pify": "pify", "diff": "diff", "diff3": "diff3",
    "ignore": "ignore", "readable-stream": "readable-stream",
    "simple-get": "simple-get", "minimisted": "minimisted"
  },
  "durable_objects": {
    "bindings": [{ "name": "NIMBUS_SESSION", "class_name": "NimbusSession" }]
  },
  "migrations": [
    { "tag": "nimbus-v1", "new_sqlite_classes": ["NimbusSession"] }
  ],
  "worker_loaders": [{ "binding": "LOADER" }],
  "r2_buckets": [
    { "binding": "NPM_TARBALL_CACHE",    "bucket_name": "my-nimbus-npm-cache" },
    { "binding": "NPM_PACKUMENT_CACHE",  "bucket_name": "my-nimbus-npm-packument-cache" },
    { "binding": "NIMBUS_RUNTIME_CACHE", "bucket_name": "nimbus-runtime-cache-public" }
  ],
  "vars": {
    // What `nimbus runtime sync` printed for the bucket above.
    "NIMBUS_RUNTIME_CATALOG_SHA256": "<64 hex>"
  }
}

nimbus install reads the runtime catalog in NIMBUS_RUNTIME_CACHE by its SHA-256, the NIMBUS_RUNTIME_CATALOG_SHA256 var, and serves it only if its bytes hash to that value. nimbus runtime sync prints the value after it fills the bucket; every sync that adds a runtime changes it, so update the var and redeploy. Without the var, every nimbus install fails, saying so.

The Worker needs enhanced_error_serialization. A process's filesystem errors reach it across workerd RPC, and only that flag carries their code across. A compatibility date of 2026-04-21 or later enables it; on an older date, add "enhanced_error_serialization" to compatibility_flags, which keeps every other behavior of that date. Without it the Worker fails at startup with that reason, since this package's entry composes the fabric at module scope. From 2026-08-04 the date also enables nodejs_compat, so no flag is listed.

Then:

CLOUDFLARE_ACCOUNT_ID=<account-id> npx @nimbus-sh/cli setup cloudflare --name my-nimbus
npx wrangler secret put JWT_SECRET     # 32+ hex chars
npx wrangler deploy

If setup reports Cloudflare R2 error 10042, enable R2 in the Cloudflare Dashboard once for the account, then rerun the setup command.

JWT_SECRET is required for token-enforced deployments. Legacy-public single-tenant demos can set NIMBUS_LEGACY_PUBLIC=1 and rely on URL possession instead.

createNimbusHandler

The handler owns the router, auth, and the session protocol. Its options:

{
  auth?: { mode?: 'auto' | 'enforce' | 'legacy'; legacyPublic?: boolean };
  hooks?: {
    onSessionStart?: (ctx) => void | Promise<void>;
    onSessionEnd?:   (ctx) => void | Promise<void>;  // reserved v0.2
  };
  routes?: (request, env, ctx) => Response | null | Promise<Response | null>;
  sdk?: {
    remote?: boolean | { enabled?: boolean; basePath?: string; allowLegacy?: boolean };
    config?: NimbusConfig;
  };
}

Custom routes

A route that returns anything but null short-circuits Nimbus's router. Use one for a token-mint endpoint, /healthz, SDK smoke tests, or backend sandbox jobs.

import { issueNimbusToken } from '@nimbus-sh/sdk/token';

export default createNimbusHandler({
  routes: async (req, env) => {
    if (new URL(req.url).pathname === '/api/auth/mint' && req.method === 'POST') {
      const { tenant, sub } = await req.json();
      const token = await issueNimbusToken(env, { tn: tenant, sub });
      return Response.json({ token });
    }
    return null;
  },
});

Programmatic sandbox route:

import { Nimbus } from '@nimbus-sh/sdk';

export default createNimbusHandler({
  routes: async (req, env) => {
    const url = new URL(req.url);
    if (url.pathname === '/api/run-python') {
      const nimbus = Nimbus.fromEnv(env, {
        endpoint: url.origin,
        sandboxes: {
          default: {
            root: '/home/user',
            runtimes: { preinstall: ['python'], onDemand: true },
          },
        },
      });
      const box = nimbus.sandbox('api-job-1', { tenant: 'api', subject: 'python' });
      const result = await box.runCode('print(2 + 2)', {
        language: 'python',
        install: 'ifMissing',
      });
      return Response.json(result);
    }
    return null;
  },
});

Remote SDK API:

export default createNimbusHandler({
  sdk: {
    remote: true,
    config: nimbusConfig,
  },
});

Remote calls use POST /api/nimbus/v1/sandboxes/<id>/rpc internally. Applications normally call it through Nimbus.connect({ endpoint, token, config }). The route requires a valid Nimbus JWT and sandbox:use scope. box.destroy() additionally requires session:destroy or session:admin.

With the remote API enabled, DELETE /s/<id>/ is the same operation under the same authorization as box.destroy(), and answers { ok: true, result: { ok, killed, destroyedAt, reason } }. An X-Nimbus-Cleanup-Reason header supplies the reason. The session root serves the UI only to GET and HEAD; any other method is 405, and so is DELETE when the remote API is off.

For an app server, start the process and expose its virtual port:

await box.files.write('/home/user/example-app/server.js', serverSource);
const proc = await box.startProcess('node --watch /home/user/example-app/server.js');
const port = await box.ports.expose(3000);
// proc.pid is live immediately: box.processes.logs(proc.pid) streams output,
// box.processes.kill(proc.pid) stops it

Hooks

export default createNimbusHandler({
  hooks: {
    onSessionStart: ({ sessionId, tenantSegment, request }) => {
      console.log(`[${tenantSegment}] session ${sessionId} attached from ${request.headers.get('cf-connecting-ip')}`);
    },
  },
});

Auth modes

| Mode | Meaning | |---|---| | 'auto' (default) | Verify token when JWT_SECRET is set AND NIMBUS_LEGACY_PUBLIC is unset. Otherwise legacy-public. | | 'enforce' | Always verify token; fail closed if JWT_SECRET is missing. | | 'legacy' | Never verify; all requests route to the single legacy:public:_ tenant. Use only for single-tenant demos. |

Session Agent

The bundled session shell carries an agent surface inside the editor workspace. Its route lives in the session Durable Object under /api/agent/*. The stable Cloudflare OAuth callback is /api/nimbus/oauth/callback.

The agent uses the same session tools as the SDK: shell exec, files, runtime installs, long-running processes, logs, and preview ports. Model calls use the AI SDK with Cloudflare Workers AI's OpenAI-compatible endpoint and an optional AI Gateway name.

For user-owned quota, create a Cloudflare OAuth client. Use response type Code, grant type Authorization Code, token authentication method None, and redirect URL https://<your-nimbus-host>/api/nimbus/oauth/callback. Nimbus uses PKCE and stores user OAuth tokens only in encrypted HttpOnly, Secure, SameSite=Lax browser cookies scoped to the session URL.

Non-secret values can be generated with @nimbus-sh/config or written as vars:

| Var | What | |---|---| | NIMBUS_CF_OAUTH_CLIENT_ID | Cloudflare OAuth client ID. | | NIMBUS_CF_OAUTH_SCOPES | Space-delimited Cloudflare OAuth scope IDs. | | NIMBUS_CF_OAUTH_REDIRECT_URI | Optional callback override; default is <origin>/api/nimbus/oauth/callback. | | NIMBUS_CLOUDFLARE_ACCOUNT_ID | Owner-token fallback account ID. | | NIMBUS_AGENT_MODEL | Workers AI model, default @cf/moonshotai/kimi-k2.6. | | NIMBUS_AGENT_GATEWAY_ID | AI Gateway name, default default. |

Secrets stay in Workers secret storage:

npx wrangler secret put NIMBUS_AGENT_COOKIE_SECRET
npx wrangler secret put NIMBUS_CLOUDFLARE_API_TOKEN

Subpath exports

| Subpath | What | |---|---| | @nimbus-sh/sdk/worker | Public Worker embedder API: NimbusSession, RPC classes, createNimbusHandler, auth helpers. | | @nimbus-sh/worker | Runtime implementation package used by the SDK entrypoint. | | @nimbus-sh/worker/router | Runtime router implementation and hook types. | | @nimbus-sh/worker/auth | Runtime auth implementation re-exported by @nimbus-sh/sdk/token. | | @nimbus-sh/worker/workspace-host | composeHostedRuntime: the runtime over a NimbusWorkspace in your own Durable Object. Its lifecycle.schedule must be backed by an alarm; see Use as a library. |

Required bindings

None of these is optional. See apps/hosted-demo/wrangler.jsonc or @nimbus-sh/config for the canonical set:

  • NIMBUS_SESSION (Durable Object) — per-session SQLite state
  • LOADER (Worker Loader) — dynamic-isolate spawning for npm + vite + facets
  • NPM_TARBALL_CACHE + NPM_PACKUMENT_CACHE + NIMBUS_RUNTIME_CACHE (R2)
  • ASSETS — serves the xterm shell + lazy-loaded WASM/JS blobs
  • JWT_SECRET (secret) — HS256 signing key for token-enforced deployments

Status

v0.1 is the first public release. SemVer is not stable yet, so expect breaking changes through v0.x. Issues + PRs welcome.

MIT. © Ashish Kumar Singh + contributors.