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

@claxedo/sandbox-manager

v0.7.0

Published

Sandbox lifecycle manager with epoch-based leases and pluggable drivers for Daytona, Modal, Vercel Sandbox, Cloudflare, Box, and Docker

Readme

@claxedo/sandbox-manager

Open-sourceable sandbox placement and lease management for running @claxedo/workspace-runtime inside provider sandboxes.

The package owns the generic pieces:

  • SandboxManager
  • SandboxLease
  • SandboxTarget
  • SandboxLeaseStore
  • SandboxDriver
  • provider drivers for Cloudflare, Daytona, Docker, fetch bridge, Modal, and Vercel

It deliberately does not own Claxedo product auth, billing, Convex schema, SQLite app storage, routes, or relay tokens. Applications provide those through adapters and call createSandboxManager.

Install

npm install @claxedo/sandbox-manager

Quickstart

A SandboxManager is three parts wired together: a SandboxLeaseStore (where lease state lives), a SandboxDriver (how a sandbox is actually placed), and createSandboxManager (the epoch/retry orchestration on top of both). This example uses the in-memory lease store and the Docker driver, so it runs end-to-end with only a local Docker daemon — no provider account needed:

import { createSandboxManager } from "@claxedo/sandbox-manager"
import { createMemoryLeaseStore } from "@claxedo/sandbox-manager/stores/memory"
import { createDockerSandboxDriver } from "@claxedo/sandbox-manager/drivers/docker"
import { SANDBOX_IMAGE } from "@claxedo/sandbox-manager/image"

const manager = createSandboxManager({
  leaseStore: createMemoryLeaseStore(),
  driver: createDockerSandboxDriver({ image: SANDBOX_IMAGE }),
})

const result = await manager.ensure("workspace-1", { homeRegion: "local" })

if (result.status === "ready") {
  console.log(`sandbox ready at ${result.url} (sandboxId: ${result.sandboxId})`)
} else if (result.status === "provisioning") {
  console.log(`still provisioning, retry in ${result.retryAfterMs}ms`)
} else {
  console.error(`unavailable: ${result.error}`)
}

// Later, on the same workspace: `ensure` re-resolves the existing lease
// instead of placing a new sandbox.
await manager.stop("workspace-1")

Swap createDockerSandboxDriver for createDaytonaSandboxDriver, createModalSandboxDriver, createVercelSandboxDriver, createCloudflareSandboxDriver, or createBoxSandboxDriver (all under @claxedo/sandbox-manager/drivers/*) to place on a hosted provider instead — see docs/architecture.md for the full driver comparison and each provider's required options. Swap createMemoryLeaseStore for a persisted SandboxLeaseStore implementation (e.g. backed by SQLite or Convex) to survive process restarts.

Credentials & secrets

There are two distinct channels for getting values into a sandbox, chosen by whether the code inside the sandbox is trusted with the raw value.

env — readable, for trusted credentials

SandboxManagerInput.env (and the driver-level env) sets ordinary environment variables, readable inside the sandbox via process.env. Reserve this for credentials the agent is meant to hold — e.g. the user's own model subscription/API key, which the agent needs to call the model directly.

secrets — brokered, never readable inside the sandbox

SandboxManagerInput.secrets: SandboxBrokeredSecret[] is for credentials the sandbox must be able to use on outbound requests but must never be able to read or exfiltrate (connection tokens, deploy tokens). The raw value never enters the sandbox: the provider injects it on egress to an allowlist of hosts only.

await manager.ensure(workspaceId, {
  homeRegion: "us-east",
  secrets: [{
    name: "NOTION_TOKEN",
    value: notionToken,          // never enters the sandbox in plaintext
    hosts: ["api.notion.com"],   // substituted/injected only for these hosts
    header: "Authorization",     // required for Vercel; optional for Daytona
  }],
})

Per-provider mechanism (from each provider's official docs):

| Driver | secretBrokering | Mechanism | | --- | --- | --- | | Daytona | native | daytona.secret.create({name, value, hosts}); the sandbox env holds an opaque dtn_secret_… placeholder and an egress proxy substitutes the real value only for allowlisted hosts (docs). | | Vercel | native | Firewall header-transform (updateNetworkPolicy): the value is spliced onto egress to the allowlisted hosts as header, so the sandbox makes an unauthenticated request (docs). updateNetworkPolicy replaces the whole policy, so the driver sends the union of the create-time allow-list and the brokered hosts — attaching a credential must not revoke egress the caller was already granted (a mid-run npm install would start failing), nor widen it to a brokered host the create-time policy never approved. | | Cloudflare | proxy | Implemented via the official Worker-proxy pattern: the driver sends the value to the sandbox Worker (API-token-gated, never into the container); the Worker stores it in KV, mints a short-lived per-sandbox JWT, and sets CLAXEDO_EGRESS_PROXY_URL/CLAXEDO_EGRESS_TOKEN/CLAXEDO_EGRESS_HOSTS in the container. The sandbox routes brokered-host egress through the Worker, which validates the JWT and injects the credential as header — the raw value never enters the sandbox. The reusable core is @claxedo/sandbox-manager/drivers/cloudflare-egress (mint/verify + handleEgressRequest). | | Modal | none | Modal Secrets are an encrypted by-reference store, but exposed as readable env vars inside the sandbox — they cannot satisfy the never-readable contract. | | Docker, fetch | none | Plaintext env only. |

Fail-closed contract. A brokered secret is never silently downgraded to readable env. native (transparent egress) and proxy (Cloudflare Worker egress proxy) both keep the value out of the sandbox and provision normally; only a none driver makes the manager refuse to provision (status: "unavailable", error: "secret_brokering_unsupported") rather than expose or drop the credential. Brokered secret values are also never written to labels, never logged, and never captured in a driver snapshot.

Consumption note: native brokering is transparent (existing code reaches the real host and the platform injects). Cloudflare proxy is NOT transparent — the sandbox must route brokered-host requests through CLAXEDO_EGRESS_PROXY_URL (with the CLAXEDO_EGRESS_TOKEN bearer and the x-claxedo-egress-target header). Modal stays none; its secret store improves storage hygiene for readable credentials but does not hide them from the sandbox.

Egress containment

SandboxManagerInput.net restricts what the sandbox can reach on the network. It is a separate control from brokered secrets, with a different posture, and the difference matters:

  • Brokered secrets fail closed. A driver that cannot broker refuses to provision (error: "secret_brokering_unsupported").
  • Egress does not. Only daytona (names + CIDRs) and vercel (names) can enforce an allowlist. Every other driver declares metadata.egressControl: "none", and for those the manager withholds the policy and provisions anyway — the sandbox runs with unrestricted egress.

Withholding rather than passing is deliberate: exe, docker, modal and box throw when handed a restricted policy, and cloudflare and the fetch bridge accept one and silently ignore it. Withholding at the manager means the throwing drivers never see a policy (their throws stay as their own last line of defence) and the silently-dropping ones stop pretending.

The gap is never silent. createSandboxManager warns at composition, and again each time a policy is withheld:

[sandbox-manager] SANDBOX EGRESS IS UNRESTRICTED: driver "cloudflare" declares
egressControl: "none", so workspace ws_1 can reach ANY host on the internet …

Pass onEgressUnenforced to route that into telemetry instead of console.warn — it receives a structured SandboxEgressUnenforcedEvent. Overriding the sink replaces the console warning, so only do it if the replacement is as visible.

Reuse and resume reapply the policy. A restricted policy only reaches a provider as creation parameters, so a sandbox handed back rather than created — reuse in ensureHost, resume in resumeHost — would otherwise run on the policy in force when it was first created, possibly a wider one from an earlier caller. Daytona's allow-list is mutable post-create (Sandbox.updateNetworkSettings), so daytona reapplies the requested policy on both paths. A client too old to expose that call makes the driver refuse the reuse: a policy reported as applied but not in force is worse than no sandbox. Requesting no containment leaves the existing policy alone rather than clearing it — "not requested" is not "please unrestrict".

driver.metadata.egressControl is the machine-readable source of truth, and sandboxEgressDisposition(control, net) is the pure predicate the manager uses, so you can ask the same question before composing. One exception stays fail closed: a hosts-only driver handed an address-only policy is refused (sandbox_egress_policy_unenforceable) rather than degraded, because that driver does enforce egress — it just cannot express that encoding.

SDK conformance: the Daytona secret API and Vercel network-policy transform shapes follow the providers' official docs and are validated structurally against the pinned SDK types; like all provider calls in this package they are exercised against mocks in unit tests, with live-SDK integration verified at deploy time.