Creating Sandboxes
Copy
import { RunTools } from '@runtools/sdk';
const rt = new RunTools({ apiKey: process.env.RUNTOOLS_API_KEY });
// Basic creation (ephemeral, no mounts)
const sandbox = await rt.sandboxes.create({
template: 'nodejs-20',
});
// With persistent mount
const sandbox = await rt.sandboxes.create({
template: 'nodejs-20',
mounts: [
{ workspaceId: 'my-project', path: '/workspace' },
],
});
// Multiple mounts
const sandbox = await rt.sandboxes.create({
template: 'nodejs-20',
mounts: [
{ workspaceId: 'my-code', path: '/workspace' },
{ workspaceId: 'datasets', path: '/data' },
],
});
// With all options
const sandbox = await rt.sandboxes.create({
template: 'python-ml',
idleTimeout: 600,
mounts: [
{ workspaceId: 'ml-experiments', path: '/workspace' },
{ workspaceId: 'training-data', path: '/data' },
],
resources: {
vcpus: 4,
memory: '8GB',
disk: '50GB',
},
env: {
NODE_ENV: 'development',
},
metadata: {
projectId: 'proj-123',
userId: 'user-456',
},
});
Getting Sandboxes
Copy
// Get by ID
const sandbox = await rt.sandboxes.get('sandbox-abc123');
// List all
const sandboxes = await rt.sandboxes.list();
// Filter
const running = await rt.sandboxes.list({
status: 'running'
});
const userSandboxes = await rt.sandboxes.list({
metadata: { userId: 'user-456' }
});
Executing Commands
Copy
// Simple execution
const result = await sandbox.exec('ls -la');
console.log(result.stdout);
console.log(result.stderr);
console.log(result.exitCode);
// With options
const result = await sandbox.exec('npm run build', {
timeout: 120000, // 2 minutes
cwd: '/app', // Working directory
env: { CI: 'true' },
});
// Stream output
for await (const chunk of sandbox.execStream('npm run dev')) {
process.stdout.write(chunk);
}
// Background process
await sandbox.exec('node server.js &');
File Operations
Copy
// Write file
await sandbox.files.write('/app/index.js', `
console.log('Hello World');
`);
// Read file
const content = await sandbox.files.read('/app/index.js');
// List directory
const files = await sandbox.files.list('/app');
// → [{ name: 'index.js', type: 'file', size: 28 }]
// Check if exists
const exists = await sandbox.files.exists('/app/index.js');
// Delete file
await sandbox.files.remove('/app/old.js');
// Create directory
await sandbox.files.mkdir('/app/src');
// Surgical edit
await sandbox.files.replace('/app/index.js', {
old: 'Hello World',
new: 'Hello RunTools',
});
// Upload file
await sandbox.files.upload('/app/data.json', localBuffer);
// Download file
const buffer = await sandbox.files.download('/app/data.json');
Dev Server URLs
Copy
// Get URL for port
const url = await sandbox.getUrl({ port: 3000 });
console.log(url); // https://sandbox-abc123.sandboxes.runtools.ai
// With custom subdomain
const url = await sandbox.getUrl({
port: 3000,
subdomain: 'my-app',
});
// → https://my-app.sandboxes.runtools.ai
// List all URLs
const urls = await sandbox.getUrls();
Pause and Resume
Copy
// Pause (snapshot state)
await sandbox.pause();
// Resume (restore state)
await sandbox.resume();
// Check status
console.log(sandbox.status); // 'running' | 'paused' | 'stopped'
Snapshots
Copy
// Create snapshot
await sandbox.snapshot({ name: 'before-changes' });
// List snapshots
const snapshots = await sandbox.snapshots.list();
// Rollback
await sandbox.rollback({ snapshot: 'before-changes' });
// Branch (create new sandbox from snapshot)
const branched = await sandbox.branch({
snapshot: 'before-changes',
name: 'experiment',
});
SSH Access
SSH access uses your organization’s registered SSH keys:Copy
// Get SSH connection info
const ssh = await sandbox.getSSH();
console.log(ssh.host); // ssh.runtools.ai
console.log(ssh.username); // sandbox-abc123 (sandbox ID)
console.log(ssh.port); // 22
// Connect via: ssh [email protected]
You must register your SSH public key first using
runtools ssh-key add or via the dashboard. The SSH gateway matches your local private key against your org’s registered keys.VNC Access (Desktop Templates)
VNC access is available for desktop-enabled templates. Coming soon.
Lifecycle
Copy
// Destroy sandbox
await sandbox.destroy();
// Wait for status
await sandbox.waitFor('running');
// Refresh status
await sandbox.refresh();
Events
Copy
// Listen for events
sandbox.on('status', (status) => {
console.log('Status changed:', status);
});
sandbox.on('log', (log) => {
console.log(log.message);
});
// Remove listener
sandbox.off('status', handler);
Types
Copy
import type {
Sandbox,
SandboxStatus,
SandboxCreateOptions,
ExecResult,
FileInfo,
} from '@runtools/sdk';
const status: SandboxStatus = 'running';