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

@mosaic-sandbox/sdk

v0.14.7

Published

TypeScript SDK for Mosaic Sandbox

Readme

Mosaic Sandbox TypeScript SDK

Install:

npm install @mosaic-sandbox/sdk

Set your endpoint and API token in the agent environment, then use the SDK:

import { Sandbox } from "@mosaic-sandbox/sdk";

const sandbox = await Sandbox.create({
  template: "node-20",
  endpoint: "https://sandbox.mosaicos.com",
  apiToken: process.env.MOSAIC_API_TOKEN,
  enableSsh: false
});
const child = await sandbox.process.start("npm run dev");

for await (const event of child.stream()) {
  console.log(event.stdout);
}

const preview = await sandbox.preview(3000);
console.log(preview.url);

const checkpoint = await sandbox.snapshot("ready-to-test");
const fork = await sandbox.fork(checkpoint);
await fork.destroy();
await sandbox.destroy();

Native SDK credentials use apiToken, not apiKey. Passing apiKey raises a ConfigurationError before any request. If apiToken is omitted, the SDK checks MOSAIC_API_TOKEN, then legacy MAR_API_TOKEN, then E2B_API_KEY only when it contains a Mosaic key (msk_ prefix). Authenticated operations fail locally with ConfigurationError when no credential is available; constructing a handle and using local helpers does not require a token. Other unrecognized option keys remain tolerated at runtime. E2B and Daytona compatibility shims continue to accept their documented apiKey option.

SSH helpers are also available for agent-native setups:

const sandbox = await Sandbox.create({
  template: "node-20",
  endpoint: "https://sandbox.mosaicos.com",
  apiToken: process.env.MOSAIC_API_TOKEN,
  enableSsh: true
});

console.log(
  sandbox.getSshConnectionString({
    identityFile: "~/.ssh/mosaic_id_ed25519",
    knownHostsFile: "~/.ssh/mosaic_known_hosts"
  })
);

console.log(
  sandbox.getCodexSshConfigEntry({
    identityFile: "~/.ssh/mosaic_id_ed25519",
    knownHostsFile: "~/.ssh/mosaic_known_hosts"
  })
);

Pass apiToken from the agent's secret store. Preview URLs are private bearer URLs, expire automatically, and can be revoked with revokePreview().

Functions

A function is a name you keep for a one-shot run: a specification — template, command, secrets, network policy, resources, timeout — that lives in your code. Defining one makes no request and creates nothing to deploy or delete. Each invocation creates one isolated microVM, runs the command, and destroys it, so an idle function costs nothing. It is exported as FunctionSpec, because Function is taken by the language.

import { FunctionSpec } from "@mosaic-sandbox/sdk";

const thumbnail = new FunctionSpec(["python", "-m", "thumbnail"], {
  template: "python-3.11",
  secrets: ["OBJECT_STORE_TOKEN"],
  networkAllow: ["objects.mosaicos.com:443"],
  timeoutMs: 60_000,
  endpoint: "https://sandbox.mosaicos.com",
  apiToken: process.env.MOSAIC_API_TOKEN
});

const result = await thumbnail.invoke({ env: { OBJECT_KEY: "images/input.jpg" } });
console.log(result.stdout, result.sandbox_destroyed);

What the sandbox is stays fixed for every invocation. Only cwd, env, stdin, timeoutMs and idempotencyKey may be passed per call; anything else throws rather than being silently ignored, so one call cannot widen another's secrets or egress. Retrying with the same idempotencyKey replays the first invocation instead of running a second one.

Work that must outlive one synchronous call belongs in a process or job, and work that needs a URL belongs behind a preview.

Long-running attempts

Synchronous exec is capped at 900,000 ms (15 minutes). A durable process is owned by the sandbox rather than by the request that starts it, so persist the sandbox and process IDs and reconnect after a client restart. Its lifetime is bounded by its own timeout, when supplied, and by the sandbox TTL.

let sandbox = await Sandbox.create({ template: "base", ttlSeconds: 86_400 });
try {
  const started = await sandbox.process.start(["python", "-m", "train"]);
  const sandboxId = sandbox.id;
  const processId = started.id;

  sandbox = await Sandbox.connect(sandboxId);
  const handle = (await sandbox.process.list()).find((p) => p.id === processId);
  if (!handle) throw new Error("process not found");
  for await (const chunk of handle.stream()) process.stdout.write(chunk.stdout);
  const info = await handle.info();
  if (info.exit_code !== 0) throw new Error(`attempt exited ${info.exit_code}`);
} finally {
  await sandbox.destroy();
}

A running process prevents hibernation; after it finishes, pause/resume works normally. Call handle.kill() to cancel it. The full Python, TypeScript, Go, CLI, and raw-HTTP recovery patterns are in the public documentation.

Vercel AI SDK tools

Give a model a sandbox without writing tools for it. This needs ai >= 4, which you already have if you are using the AI SDK; the SDK imports it only when you call this, and does not depend on it.

import { streamText } from "ai";
import { mosaicSandboxTools } from "@mosaic-sandbox/sdk/ai";

const sandbox = await mosaicSandboxTools({ template: "node-20" });
try {
  const result = streamText({ model, prompt, tools: sandbox.tools });
} finally {
  await sandbox.close();
}

The tools — mosaic_run_command, mosaic_run_python, mosaic_run_javascript, mosaic_read_file, mosaic_write_file, mosaic_list_files and mosaic_start_server — share one sandbox, created on the first call rather than when the agent is built. mosaic_start_server returns a public HTTPS preview URL, so "run the dev server and show me" is a single tool call.

close() destroys the sandbox the toolset created but leaves a sandbox you passed in alone, and the toolset is spent either way — a later tool call throws rather than quietly starting a second machine.

toolDefinitions() exports the same set as plain JSON Schema, for frameworks that take their tools that way.

Docs: https://sandbox.mosaicos.com/docs/