@brimble/sandbox
v0.1.5
Published
TypeScript SDK for the Brimble Sandbox API
Downloads
868
Readme
@brimble/sandbox
TypeScript SDK for the Brimble Sandbox API.
Install
npm install @brimble/sandboxTesting
# Unit tests (mocked transport, no API key required)
npm run test
# Live integration test (creates a sandbox, runs a command, then destroys it)
BRIMBLE_SANDBOX_KEY=your_key_here npm run test:integration
# Run both
BRIMBLE_SANDBOX_KEY=your_key_here npm run test:allQuickstart
import { CodeLanguage, Sandbox } from '@brimble/sandbox';
const client = new Sandbox();
const sandbox = await client.sandboxes.createReady({
template: 'node-22',
persistent: true,
persistentDiskGB: 20,
mountPath: '/workspace',
});
await sandbox.exec({ cmd: 'node -v', env: { NODE_ENV: 'production' } });
await sandbox.putFile('tmp/notes.txt', Buffer.from('hello sandbox'));
await sandbox.putFiles([
{ path: '/tmp/hello.txt', body: 'hello from batch' },
{ path: '/tmp/config.json', body: JSON.stringify({ mode: 'dev' }) },
]);
const stream = await sandbox.getFile('tmp/notes.txt');
await sandbox.runCode({
language: CodeLanguage.Node,
code: 'console.log(1 + 1)',
env: { FEATURE_FLAG: 'on' },
});
// Handle-first lifecycle on existing sandboxes.
const existingSandbox = await client.sandboxes.get(sandbox.id);
await existingSandbox.destroy();Set BRIMBLE_SANDBOX_KEY in your environment.
If needed, pass apiKey explicitly in the constructor; explicit value wins over env.
Ergonomic helpers
// 1) Create + wait in one call
const created = await client.sandboxes.createReady({ template: 'node-22' });
// 2) Get + wait in one call
const loaded = await client.sandboxes.getReady(created.id);
// 3) Create a volume + attach in one call
const withVolume = await client.sandboxes.withVolume({
sandbox: { template: 'node-22', mountPath: '/var/www/html' },
volume: { name: 'workspace-disk', sizeGB: 20 },
});
// 4) Auto-wait at runtime call sites
await withVolume.exec({ cmd: 'npm -v' }, { waitUntilReady: true });
// Streaming SSE output (stream: true returns ReadableStream<Uint8Array>)
const sse = await withVolume.exec({ cmd: 'for i in 1 2 3; do echo $i; done', stream: true });
// 5) List templates/regions
const templates = await client.sandboxes.listTemplates();
const nodeTemplate = await client.sandboxes.getTemplate('node-22');
const { regions } = await client.sandboxes.listRegions();
// 6) Async iterators for pagination
for await (const sandbox of client.sandboxes.iterate({ teamId: '<team>' })) {
console.log(sandbox.id, sandbox.status);
}Handle composition
const sandbox = await client.sandboxes.get('<sandbox-id>');
await sandbox.snapshots.create({ name: 'before-migration' });Volume attachment is create-time only.
Use client.sandboxes.create({ ..., volumeId }) or client.sandboxes.withVolume(...).
Retry, timeouts, and idempotency
const client = new Sandbox({
timeoutMs: 30_000,
retry: {
maxAttempts: 3,
baseDelayMs: 250,
maxDelayMs: 2_000,
},
});
await client.sandboxes.create(
{ template: 'node-22' },
{ idempotencyKey: 'create-sandbox-123' },
);If region is omitted, the SDK resolves the first available sandbox region automatically.
Resources
client.sandboxescreate,createReady,withVolume,list,iterate,get,getReady,listRegions,listTemplates,getTemplate,destroy,pause,resume,quickstartNode,quickstartPython,use
sandboxhandle (returned fromcreate/get/list)waitUntilReady,refresh,destroy,pause,resume,exec,runCode,putFile,putFiles,getFile,stats,createSnapshot,listSnapshots,snapshots.create,snapshots.list
client.sandboxes.use(id)destroy,exec,runCode,putFile,putFiles,getFile,stats,createSnapshot,listSnapshots
client.snapshotslistAll,iterateAll,delete
client.volumeslist,iterate,create,get,delete
Errors
HTTP errors throw typed errors:
AuthErrorValidationErrorNotFoundErrorRateLimitErrorSandboxApiError
All include:
statusmessageendpointresponseBodyrequestId
