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

@sandflare/sdk

v2.1.20

Published

Sandflare SDK — Firecracker microVM sandboxes for AI agents

Readme

Sandflare JavaScript / TypeScript SDK

The official JS/TS SDK for Sandflare — Firecracker microVM sandboxes for AI agents.

Install

npm install @sandflare/sdk

Quick start

import { Sandbox } from '@sandflare/sdk'

const sb = await Sandbox.create('agent', { templateId: 'codebox' })
const result = await sb.exec('echo hello')
console.log(result.stdout)  // "hello\n"
await sb.delete()

Environment variables

| Variable | Description | |---|---| | SANDFLARE_API_KEY | API key (required) | | SANDFLARE_API_URL | Optional base URL override (default: https://api.sandflare.io) | | PANDAAGENT_API_KEY | Legacy alias for SANDFLARE_API_KEY | | PANDAAGENT_BASE_URL | Legacy alias for SANDFLARE_API_URL |

All requests use X-API-Key header for authentication.


Sandbox

Create

// Basic (base Ubuntu, 512 MB / 1 vCPU)
const sb = await Sandbox.create('agent')

// Pick an environment template
const sb = await Sandbox.create('agent', { templateId: 'codebox' })       // Python data stack
const sb = await Sandbox.create('agent', { templateId: 'ai-agent' })      // LangChain / CrewAI
const sb = await Sandbox.create('agent', { templateId: 'browser-agent' }) // Playwright + Chromium
const sb = await Sandbox.create('agent', { templateId: 'nextjs' })        // Next.js 15
const sb = await Sandbox.create('agent', { templateId: 'vite-react' })    // Vite + React 19

// With options
const sb = await Sandbox.create('agent', {
  templateId: 'codebox',
  ttlHours: 2,
  ephemeral: true,
  metadata: { env: 'prod', version: '1.0' },
  label: 'production-run',
})

// From a snapshot
const sb = await Sandbox.create('restored', { snapshotId: '<snapshot-uuid>' })

Templates and resources:

| templateId | Environment | RAM | vCPU | Rate/s | |---|---|---|---|---| | "" (default) | Base Ubuntu | 512 MB | 1 | ~$0.000014 | | codebox | pandas, numpy, matplotlib, scipy, scikit-learn | 4 GB | 2 | ~$0.000040 | | ai-agent | LangChain, CrewAI, LlamaIndex | 4 GB | 2 | ~$0.000040 | | browser-agent | Playwright + Chromium | 2 GB | 2 | ~$0.000032 | | nextjs | Node 20 + Next.js 15 | 2 GB | 2 | ~$0.000032 | | vite-react | Node 20 + Vite + React 19 | 2 GB | 2 | ~$0.000032 |

sb.info is a SandboxInfo object with these fields:

| Field | Type | Description | |---|---|---| | name | string | Unique sandbox ID (e.g. sb-abc123) | | status | string | ready, paused, stopped | | label | string? | Human-readable label | | previewUrl | string? | https://3000-sb-abc123.sandflare.io | | subdomainUrl | string? | https://sb-abc123.sandflare.io (port-less) | | agentUrl | string | Internal agent URL | | metadata | Record<string,unknown>? | Custom key-value metadata | | ephemeral | boolean? | True if auto-deleted on close | | expiresAt | string? | ISO timestamp if TTL set | | memoryMb | number | RAM in MB (e.g. 512, 1024, 2048, 4096) | | vcpus | number | vCPU count |

Get & List

// Get by name
const sb = await Sandbox.get('sb-abc123')

// List all
const sandboxes = await Sandbox.list()

// Filter by label
const sandboxes = await Sandbox.list({ label: 'production-run' })

Exec

// Run a shell command
const result = await sb.exec('echo hello')
console.log(result.stdout)    // "hello\n"
console.log(result.exitCode)  // 0
console.log(result.ok)        // true

// With env vars
const result = await sb.exec('echo $MY_VAR', { env: { MY_VAR: 'hello_world' } })

// With cwd and timeout
const result = await sb.exec('ls', { cwd: '/tmp', timeout: 10 })

// Stream output in real-time
for await (const chunk of sb.execStream('python3 train.py', { timeout: 120 })) {
  if (chunk.event === 'stdout') process.stdout.write(String((chunk.data as any).line ?? ''))
  if (chunk.event === 'done')   console.log('done')
}

// Typed streaming chunks (type: 'stdout' | 'stderr' | 'done')
for await (const chunk of sb.execStreamIter('python3 train.py')) {
  if (chunk.type === 'stdout') process.stdout.write(chunk.data)
  if (chunk.type === 'done')   console.log(`\nexited ${chunk.exitCode}`)
}

File I/O

// Write and read
await sb.writeFile('/tmp/hello.txt', 'hello world')
const content = await sb.readFile('/tmp/hello.txt')  // string

// Binary upload
await sb.uploadFile('/tmp/data.bin', Buffer.from([0x00, 0x01, 0x02]))

// Binary download
const bytes = await sb.downloadFile('/tmp/data.bin')  // Buffer

// List directory
const entries = await sb.ls('/tmp')
for (const e of entries) {
  console.log(e.name, e.size, e.isDir)
}

Run code

// Python
const result = await sb.runPython('print(2 + 2)')
console.log(result.stdout)  // "4\n"

// Node.js
const result = await sb.runNode('console.log(2 + 2)')
console.log(result.stdout)  // "4\n"

// Stateful kernel (variables persist across calls)
await sb.runCode('x = 42')
const r = await sb.runCode('x * 2')
console.log(r.text)  // "84"

Lifecycle

await sb.pause()    // snapshot memory to disk, free compute
await sb.resume()   // restore from snapshot
await sb.delete()   // destroy permanently
await sb.close()    // alias for delete()

Snapshots

// Create snapshot (sandbox continues running)
const snap = await sb.snapshot({
  name: 'after-data-load',
  description: 'Dataset v2 loaded',
  tags: ['prod', 'v2'],
})
console.log(snap.snapshotId)  // UUID

// List snapshots for this sandbox
const snaps = await sb.listSnapshots()
for (const s of snaps) {
  console.log(s.snapshotId, s.name, s.status)
}

// Restore (creates new sandbox from snapshot)
const restored = await Sandbox.create('fork', { snapshotId: snap.snapshotId })

Pause → auto-resume

await sb.pause()
// ... later ...
const sb2 = await Sandbox.get(sb.id)  // auto-resumes, file state preserved

AI Memory (mem0-backed)

Sandbox-scoped and user-scoped AI memory — semantically searchable across sessions.

// Sandbox-scoped memory (via sb.aiMemory)
await sb.aiMemory.add('User prefers async/await and strict TypeScript')
await sb.aiMemory.add('Bug: always flush stream before closing')

const results = await sb.aiMemory.search('TypeScript coding preferences')
for (const r of results) console.log(r.memory)

const all = await sb.aiMemory.list()

// User-level memory (persists across ALL sandboxes)
const userMem = Sandbox.userMemory()  // reads SANDFLARE_API_KEY from env
await userMem.add('User speaks English and prefers concise answers')
const results = await userMem.search('communication preferences')
const all = await userMem.list()

Custom templates

import { Template } from '@sandflare/sdk'

// Build from Dockerfile
const job = await Template.build('my-env',
  'FROM ubuntu:22.04\nRUN apt-get update && apt-get install -y python3'
)

// Poll until ready
const ready = await Template.waitForBuild(job.id, { timeoutMs: 600_000 })

// Use the template
const sb = await Sandbox.create('agent', { templateId: ready.id })

// Manage templates
const jobs = await Template.list()
const status = await Template.getBuildStatus('tmpl-abc123')
await Template.delete('tmpl-abc123')

Auto-snapshots

await sb.enableAutoSnapshot(15)   // every 15 minutes
await sb.disableAutoSnapshot()

Metrics & processes

const m = await sb.metrics()
console.log(`CPU: ${m.cpuUsedPct.toFixed(1)}%  RAM: ${m.memUsed}/${m.memTotal}`)

const procs = await sb.getProcesses()
for (const p of procs) console.log(p.pid, p.command)

await sb.killProcess(1234)

Git clone

const result = await sb.gitClone('https://github.com/org/repo', {
  path: '/home/agent/repo',
  branch: 'main',
  depth: 1,
})
console.log(result.output)

Terminal (WebSocket)

const ws = sb.openTerminal({ cols: 220, rows: 50 })
ws.addEventListener('message', e => process.stdout.write(e.data))

Local development

cd sdk/javascript
npm install
npm run build      # outputs to dist/
npm run typecheck  # tsc --noEmit

Publish

npm run build && npm publish --access public