Skip to main content
The Sandbox class is the main entry point for working with Lifo. It orchestrates all boot steps including the kernel, VFS, command registry, and shell.

Basic Usage

1

Create a headless sandbox

The simplest way to create a sandbox is with no options:
import { Sandbox } from '@lifo-sh/core';

const sandbox = await Sandbox.create();

// Default working directory is /home/user
console.log(sandbox.cwd); // "/home/user"
This creates a headless sandbox suitable for programmatic use.
2

Configure sandbox options

You can customize the sandbox with various options:
const sandbox = await Sandbox.create({
  // Enable IndexedDB persistence (default: false)
  persist: true,

  // Set initial working directory
  cwd: '/tmp',

  // Add custom environment variables
  env: {
    EDITOR: 'vim',
    MY_VAR: 'custom-value'
  },

  // Pre-populate files
  files: {
    '/home/user/config.json': JSON.stringify({ key: 'value' }),
    '/home/user/script.sh': '#!/bin/sh\necho "Hello"'
  }
});
3

Access sandbox properties

The sandbox provides several key properties:
// Programmatic command execution
const result = await sandbox.commands.run('ls -la');

// Filesystem operations
await sandbox.fs.writeFile('/tmp/test.txt', 'content');

// Environment variables (merged with defaults)
console.log(sandbox.env.HOME); // "/home/user"

// Current working directory (read/write)
sandbox.cwd = '/etc';
console.log(sandbox.cwd); // "/etc"
4

Clean up resources

When you’re done, destroy the sandbox to release resources:
sandbox.destroy();

Visual Mode with Terminal

For interactive terminal use, pass an ITerminal instance:
import { Sandbox } from '@lifo-sh/core';
import { Terminal } from '@xterm/xterm';

const term = new Terminal({
  cols: 80,
  rows: 24,
  theme: {
    background: '#1e1e1e',
    foreground: '#d4d4d4'
  }
});

term.open(document.getElementById('terminal'));

const sandbox = await Sandbox.create({
  terminal: term // Enables visual/interactive mode
});
In visual mode:
  • The MOTD (message of the day) is displayed automatically
  • The shell starts and accepts interactive input
  • Users can type commands directly

Pre-populating Files

You can pre-populate files with nested paths. Parent directories are created automatically:
const sandbox = await Sandbox.create({
  files: {
    '/home/user/project/package.json': JSON.stringify({
      name: 'my-app',
      version: '1.0.0'
    }),
    '/home/user/project/src/index.js': 'console.log("Hello");',
    '/home/user/deep/nested/file.txt': 'nested content'
  }
});

// Files are ready to use immediately
const content = await sandbox.fs.readFile('/home/user/project/package.json');

Native Filesystem Mounts

In Node.js environments, you can mount native filesystem directories into the virtual filesystem:
const sandbox = await Sandbox.create({
  mounts: [
    {
      virtualPath: '/mnt/project',
      hostPath: '/home/user/my-project',
      readOnly: false
    },
    {
      virtualPath: '/mnt/readonly',
      hostPath: '/usr/share/data',
      readOnly: true
    }
  ]
});

// Now you can access host files through the VFS
const hostFile = await sandbox.fs.readFile('/mnt/project/README.md');
Native mounts only work in Node.js environments. In browsers, all filesystem operations use the in-memory VFS.
You can also mount/unmount at runtime:
// Mount at runtime (Node.js only)
sandbox.mountNative('/mnt/data', '/path/on/host');

// Unmount when done
sandbox.unmountNative('/mnt/data');

Power-user APIs

For advanced use cases, the sandbox exposes lower-level APIs:
// Direct access to kernel and VFS
sandbox.kernel.vfs.readFile('/etc/hostname');

// Direct shell access
await sandbox.shell.execute('echo $PATH');

// Port registry for virtual networking
sandbox.kernel.portRegistry.set(8080, (req, res) => {
  res.statusCode = 200;
  res.body = 'Hello from virtual server';
});
These APIs are escape hatches for advanced scenarios. Most applications should use sandbox.fs and sandbox.commands instead.

Complete Example

Here’s a complete example that demonstrates common patterns:
import { Sandbox } from '@lifo-sh/core';

async function main() {
  // Create configured sandbox
  const sandbox = await Sandbox.create({
    cwd: '/home/user/project',
    env: { NODE_ENV: 'production' },
    files: {
      '/home/user/project/app.js': `
        const fs = require('fs');
        console.log('Running from:', process.cwd());
        console.log('NODE_ENV:', process.env.NODE_ENV);
      `
    }
  });

  try {
    // Run commands
    const { stdout, exitCode } = await sandbox.commands.run('node app.js');
    console.log('Output:', stdout);
    console.log('Exit code:', exitCode);

    // Manipulate files
    await sandbox.fs.writeFile('output.txt', stdout);

    // Check results
    const exists = await sandbox.fs.exists('output.txt');
    console.log('Output saved:', exists);
  } finally {
    // Always clean up
    sandbox.destroy();
  }
}

main().catch(console.error);

API Reference

See the Sandbox API reference for complete details on all options and methods.

Build docs developers (and LLMs) love