sandbox.fs API provides an async interface for filesystem operations. All paths are resolved relative to the current working directory unless they start with /.
Reading Files
Read Text Files
// Read as UTF-8 string (default)
const content = await sandbox.fs.readFile('/home/user/config.txt');
console.log(content); // string
Read Binary Files
// Read as Uint8Array by passing null as encoding
const binary = await sandbox.fs.readFile('/home/user/image.png', null);
console.log(binary); // Uint8Array
Writing Files
Write files with either string or binary content:// Write string content
await sandbox.fs.writeFile('/tmp/output.txt', 'Hello, world!');
// Write binary content
const data = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
await sandbox.fs.writeFile('/tmp/binary.dat', data);
// Write JSON
const config = { port: 8080, host: 'localhost' };
await sandbox.fs.writeFile('/tmp/config.json', JSON.stringify(config, null, 2));
Parent directories must exist before writing files, or use
mkdir with recursive: true first.Batch Writing
Write multiple files efficiently in one call:await sandbox.fs.writeFiles([
{ path: '/tmp/file1.txt', content: 'First file' },
{ path: '/tmp/file2.txt', content: 'Second file' },
{ path: '/tmp/data.bin', content: new Uint8Array([1, 2, 3]) }
]);
Directory Operations
Creating Directories
// Create single directory
await sandbox.fs.mkdir('/tmp/mydir');
// Create nested directories recursively
await sandbox.fs.mkdir('/home/user/deep/nested/path', { recursive: true });
Listing Directories
// Read directory contents
const entries = await sandbox.fs.readdir('/home/user');
for (const entry of entries) {
console.log(entry.name, entry.type); // 'file' | 'directory'
}
// Filter by type
const files = entries.filter(e => e.type === 'file');
const dirs = entries.filter(e => e.type === 'directory');
Removing Directories
// Remove empty directory
await sandbox.fs.rm('/tmp/emptydir');
// Remove directory recursively (like rm -rf)
await sandbox.fs.rm('/tmp/mydir', { recursive: true });
File Information
Check Existence
const exists = await sandbox.fs.exists('/home/user/config.json');
if (exists) {
console.log('File exists');
}
Get File Stats
const stats = await sandbox.fs.stat('/home/user/file.txt');
console.log(stats.type); // 'file' | 'directory'
console.log(stats.size); // file size in bytes
console.log(stats.mtime); // last modified time (unix timestamp)
File Operations
Copying Files
// Copy file (original remains)
await sandbox.fs.cp('/tmp/source.txt', '/tmp/dest.txt');
// Verify both exist
const srcExists = await sandbox.fs.exists('/tmp/source.txt'); // true
const dstExists = await sandbox.fs.exists('/tmp/dest.txt'); // true
Renaming/Moving Files
// Rename or move file
await sandbox.fs.rename('/tmp/old-name.txt', '/tmp/new-name.txt');
// Move to different directory
await sandbox.fs.rename('/home/user/file.txt', '/tmp/file.txt');
// Original no longer exists after rename
const exists = await sandbox.fs.exists('/tmp/old-name.txt'); // false
Removing Files
// Remove a single file
await sandbox.fs.rm('/tmp/unwanted.txt');
Path Resolution
Paths are resolved relative to the sandbox’s current working directory:// Absolute paths work from anywhere
await sandbox.fs.writeFile('/tmp/file.txt', 'content');
// Relative paths use the sandbox cwd
sandbox.cwd = '/home/user';
await sandbox.fs.writeFile('config.json', '{}'); // writes to /home/user/config.json
// Change working directory
sandbox.cwd = '/tmp';
const content = await sandbox.fs.readFile('file.txt'); // reads /tmp/file.txt
Complete Example: Project Setup
import { Sandbox } from '@lifo-sh/core';
async function setupProject() {
const sandbox = await Sandbox.create();
try {
// Create project structure
await sandbox.fs.mkdir('/home/user/my-app/src', { recursive: true });
await sandbox.fs.mkdir('/home/user/my-app/tests', { recursive: true });
// Write project files
await sandbox.fs.writeFiles([
{
path: '/home/user/my-app/package.json',
content: JSON.stringify({
name: 'my-app',
version: '1.0.0',
main: 'src/index.js'
}, null, 2)
},
{
path: '/home/user/my-app/src/index.js',
content: 'console.log("Hello, Lifo!");'
},
{
path: '/home/user/my-app/README.md',
content: '# My App\n\nA sample project.'
}
]);
// Verify structure
const entries = await sandbox.fs.readdir('/home/user/my-app');
console.log('Created:', entries.map(e => e.name));
// Read back and parse JSON
const pkgJson = await sandbox.fs.readFile('/home/user/my-app/package.json');
const pkg = JSON.parse(pkgJson);
console.log('Project name:', pkg.name);
// Get stats
const stats = await sandbox.fs.stat('/home/user/my-app/src/index.js');
console.log('index.js size:', stats.size, 'bytes');
} finally {
sandbox.destroy();
}
}
setupProject().catch(console.error);
Working with Binary Files
// Create binary data
const pixels = new Uint8Array(256);
for (let i = 0; i < 256; i++) {
pixels[i] = i;
}
// Write binary file
await sandbox.fs.writeFile('/tmp/image.raw', pixels);
// Read it back
const loaded = await sandbox.fs.readFile('/tmp/image.raw', null);
console.log(loaded instanceof Uint8Array); // true
console.log(loaded.length); // 256
// Verify contents match
for (let i = 0; i < pixels.length; i++) {
console.assert(loaded[i] === pixels[i]);
}
Snapshot Export/Import
Export and import the entire filesystem as a compressed snapshot:// Export entire VFS to tar.gz
const snapshot = await sandbox.fs.exportSnapshot();
console.log('Snapshot size:', snapshot.length, 'bytes');
// Save snapshot to host (browser example)
const blob = new Blob([snapshot], { type: 'application/gzip' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'lifo-snapshot.tar.gz';
a.click();
// Later: restore from snapshot
const sandbox2 = await Sandbox.create();
await sandbox2.fs.importSnapshot(snapshot);
// All files are restored
const content = await sandbox2.fs.readFile('/home/user/my-file.txt');
Virtual directories like
/proc and /dev are automatically excluded from snapshots since they’re generated at runtime.Error Handling
try {
await sandbox.fs.readFile('/nonexistent/file.txt');
} catch (error) {
console.error('File not found:', error.message);
}
// Check before accessing
if (await sandbox.fs.exists('/etc/config.json')) {
const config = await sandbox.fs.readFile('/etc/config.json');
// Process config...
}