Skip to main content

What is a Sandbox Container?

A sandbox is essentially a temporary virtual computer that exists entirely in the cloud. It allows you to run any code you want inside it, install packages and dependencies, create and modify files, host web servers, and even access it remotely through APIs. Once you’re done, the sandbox is automatically destroyed, freeing all allocated resources. Each sandbox operates in complete isolation, ensuring that it never interferes with other sandboxes or your main system. Under the hood, Fermion Sandboxes run on containerized Linux environments that provide an isolated filesystem, meaning any changes made inside one sandbox do not affect others. Network access is also sandboxed, with only specific ports exposed for secure communication. After disconnection, containers are automatically cleaned up, maintaining a lightweight and efficient system. For users who need persistence, Fermion offers the option to back up the filesystem using the shouldBackupFilesystem flag, allowing you to reconnect later and resume your previous environment seamlessly.

Sandbox Lifecycle

A Fermion coding sandbox has the following lifecycle
Create Sandbox

Container Provisioning (wait ~5-10 seconds)

WebSocket Connection Established

Ready for Commands

Work with files, run commands, host servers

Disconnect

Container Destroyed (unless shouldBackupFilesystem: true)

Code Example

The same coding sandbox lifecycle can be explained with the help of the following code.
// 1. Create
const sandbox = new Sandbox({ apiKey: 'key' })
await sandbox.create({ shouldBackupFilesystem: false })

// 2. Use
await sandbox.runCommand({ cmd: 'ls' })

// 3. Cleanup
await sandbox.disconnect()

File Path System

In Fermion Sandbox, every file you create, read, or modify exists within a controlled and isolated directory structure inside the container. To maintain consistency and security across environments, all file operations must use absolute paths within the sandbox’s workspace. The root working directory is /home/damner/code, and you can reference it using either the full path or the shorthand ~ (tilde) symbol. This ensures that your file interactions always occur inside the permitted workspace. Important: All paths must start with either:
  • ~ (tilde) - Shortcut for /home/damner/code
  • /home/damner/code - Full absolute path
Examples:
You WriteActual Path
~/script.js/home/damner/code/script.js
~/app/index.js/home/damner/code/app/index.js
/home/damner/code/test.py/home/damner/code/test.py
Invalid Paths (will throw error):
//  Wrong
await sandbox.writeFile({ path: '/tmp/file.txt', content: '...' })
await sandbox.writeFile({ path: 'relative/path.js', content: '...' })
await sandbox.writeFile({ path: './file.js', content: '...' })

//  Correct
await sandbox.writeFile({ path: '~/file.txt', content: '...' })
await sandbox.writeFile({ path: '/home/damner/code/file.txt', content: '...' })

Ephemeral vs Persistent Sandboxes

Fermion Sandboxes can operate in two distinct modes: ephemeral and persistent, depending on how you want to manage your container’s lifecycle and filesystem data.

Ephemeral (Default)

By default, every sandbox is ephemeral, meaning it exists only for the duration of your session. Once you disconnect, all files and processes are automatically deleted. This mode is ideal for quick code execution, one-time tests, or temporary tasks where persistence isn’t required. It’s lightweight, fast to initialize, and more cost-efficient since it doesn’t retain any data after termination.
await sandbox.create({ shouldBackupFilesystem: false })
  • Files deleted when you disconnect
  • Cheaper to run (less storage)
  • Use for: One-time code execution, testing, temporary tasks

Persistent

For longer-term workflows, you can enable persistent mode by setting shouldBackupFilesystem: true during creation. In this mode, the sandbox’s filesystem is saved even after disconnecting, and you receive a unique snippetId that can be used to reconnect later using sandbox.fromSnippet(). This makes it perfect for building development environments, maintaining progressive builds, or supporting user projects that evolve over time. Persistent sandboxes allow developers to resume exactly where they left off, with all files, dependencies, and configurations preserved.
const snippetId = await sandbox.create({ shouldBackupFilesystem: true })
// Save the snippetId somewhere
  • Files saved after disconnect
  • Can reconnect later with the same snippet ID
  • Use for: Development environments, progressive builds, user projects
Reconnecting to Persistent Sandbox:
// Later, in a different session
const sandbox = new Sandbox({ apiKey: 'key' })
await sandbox.fromSnippet('saved-snippet-id')
// All your files are still there!

Command Execution Types

Fermion Sandbox supports two primary methods for executing commands inside containers: quick commands and streaming commands, each optimized for different use cases.

Quick Commands (runCommand)

Quick commands, executed via runCommand, are designed for short-lived operations that complete within a few seconds. They run synchronously, meaning the system waits for the command to finish before returning the result. This makes them ideal for lightweight tasks such as listing files (ls), printing the current directory (pwd), reading file contents (cat), or running small scripts. Since quick commands do not stream their output in real time, they return a final response object containing both stdout and stderr once execution is complete.
  • Max duration: 5 seconds
  • No streaming: Wait for completion
  • Use for: ls, pwd, cat, quick scripts
  • Returns: { stdout, stderr }
const result = await sandbox.runCommand({
  cmd: 'ls',
  args: ['-la']
})
console.log(result.stdout)

Streaming Commands (runStreamingCommand)

On the other hand, streaming commands, executed via runStreamingCommand, are built for longer-running or interactive tasks. These commands have no time limit and provide real-time feedback through callback functions that stream output as it’s produced. This approach is particularly useful for operations like installing dependencies (npm install), running builds, launching servers, or any process that benefits from continuous log updates. The method returns a Promise containing stdout, stderr, and the final exitCode, allowing developers to monitor and control complex workflows with precision and responsiveness.
  • No time limit: Can run indefinitely
  • Live output: Callbacks as data arrives
  • Use for: npm install, builds, long scripts, servers
  • Returns: { stdout, stderr, exitCode }
const result = await sandbox.runStreamingCommand({
  cmd: 'npm',
  args: ['install'],
  onStdout: (data) => process.stdout.write(data),
  onStderr: (data) => process.stderr.write(data)
})
console.log('Exit code:', result.exitCode)

Port Exposure

Fermion Sandbox allows you to expose specific network ports from within your container to make running web services and APIs publicly accessible. Each sandbox operates within an isolated network environment but can securely expose ports 3000, 1337, and 1338 through HTTPS tunnels. This makes it easy to host web servers, REST APIs, or real-time applications directly from your sandbox instance without additional configuration. To use this feature, simply start a server inside the sandbox on one of the supported ports and then call the exposePort() method to retrieve a public URL. The URL is instantly accessible from any browser or client over HTTPS, allowing seamless interaction with your running service. This capability is especially useful for testing APIs, previewing frontend applications, or running live demos directly from your sandboxed environment. Available Ports:
  • 3000
  • 1337
  • 1338
How it works:
  1. Start a server inside the sandbox on one of these ports
  2. Get the public URL with exposePort()
  3. Access it from anywhere via HTTPS
// Start a server on port 3000
await sandbox.writeFile({
  path: '~/server.js',
  content: `
    const http = require('http');
    http.createServer((req, res) => {
      res.end('Hello World');
    }).listen(3000);
  `
})

sandbox.runStreamingCommand({
  cmd: 'node',
  args: ['server.js']
})

// Get public URL
const url = await sandbox.exposePort(3000)
console.log('Access at:', url)
// Output: https://abc123-3000.run-code.com