Oblien Docs

File Writing

Create new files, edit existing ones, and merge changes intelligently.

Create File

// Using SDK
await sandbox.files.create({
  filePath: '/opt/app/new-file.js',
  content: 'export default function hello() {\n  console.log("Hello!");\n}'
});
POST /files/create HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "filePath": "/opt/app/new-file.js",
  "content": "export default function hello() {\n  console.log(\"Hello!\");\n}"
}

Response:

{
  "success": true,
  "message": "File created successfully",
  "path": "/opt/app/new-file.js",
  "size": 62
}

Edit File

Replace entire file content:

// Using SDK
await sandbox.files.edit({
  filePath: '/opt/app/config.json',
  content: JSON.stringify({
    port: 3000,
    env: 'production'
  }, null, 2)
});
POST /files/edit HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "filePath": "/opt/app/config.json",
  "content": "{\n  \"port\": 3000,\n  \"env\": \"production\"\n}"
}

Merge Changes

Intelligently merge content into existing files:

// Using SDK
await sandbox.files.merge({
  filePath: '/opt/app/README.md',
  content: '\n## New Section\n\nAdditional documentation here.',
  options: {
    strategy: 'append'
  }
});
POST /files/merge HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "filePath": "/opt/app/README.md",
  "content": "\n## New Section\n\nAdditional documentation here.",
  "options": {
    "strategy": "append"
  }
}

Merge Strategies:

StrategyDescription
appendAdd content to end of file
prependAdd content to beginning of file
replaceReplace entire file (same as edit)

Create Directory

// Using SDK
await sandbox.files.create({
  filePath: '/opt/app/new-folder',
  isFolder: true
});
POST /files/create HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "filePath": "/opt/app/new-folder",
  "isFolder": true
}

Common Patterns

Create File from Template

const template = `
export default class {{className}} {
  constructor() {
    this.name = '{{className}}';
  }
}
`;

const content = template
  .replace(/{{className}}/g, 'UserController');

await sandbox.files.create({
  filePath: '/opt/app/src/UserController.js',
  content
});

Update JSON File

// Read current JSON
const current = await sandbox.files.get({
  filePath: '/opt/app/package.json'
});

const pkg = JSON.parse(current.content);

// Modify
pkg.version = '1.1.0';
pkg.scripts.dev = 'vite';

// Write back
await sandbox.files.edit({
  filePath: '/opt/app/package.json',
  content: JSON.stringify(pkg, null, 2)
});

Append to Log File

const timestamp = new Date().toISOString();
const logEntry = `[${timestamp}] Operation completed successfully\n`;

await sandbox.files.merge({
  filePath: '/opt/app/logs/app.log',
  content: logEntry,
  options: {
    strategy: 'append'
  }
});

Create Multiple Files

const files = [
  { path: '/opt/app/src/utils.js', content: utilsCode },
  { path: '/opt/app/src/config.js', content: configCode },
  { path: '/opt/app/src/index.js', content: indexCode }
];

// Disable watcher for batch operation
for (const file of files) {
  await sandbox.files.create({
    filePath: file.path,
    content: file.content,
    withWatcher: false
  });
}

// Re-enable watcher
await sandbox.files.create({
  filePath: '/opt/app/.batch-complete',
  content: '',
  withWatcher: true
});

Safe File Updates

// 1. Create backup
const original = await sandbox.files.get({ filePath: '/opt/app/important.js' });

try {
  // 2. Make changes
  await sandbox.files.edit({
    filePath: '/opt/app/important.js',
    content: newContent
  });
  
  // 3. Validate
  const result = await sandbox.terminal.execute({
    command: 'node /opt/app/important.js'
  });
  
  if (result.exitCode !== 0) {
    throw new Error('Validation failed');
  }
} catch (error) {
  // 4. Restore backup on error
  await sandbox.files.edit({
    filePath: '/opt/app/important.js',
    content: original.content
  });
  console.log('Restored original file');
}

File Watcher Control

The withWatcher parameter controls WebSocket notifications:

// Silent write - no WebSocket notification
await sandbox.files.create({
  filePath: '/opt/app/temp.txt',
  content: 'temporary data',
  withWatcher: false
});

// Normal write - triggers WebSocket event
await sandbox.files.create({
  filePath: '/opt/app/important.txt',
  content: 'important data',
  withWatcher: true // default
});

ℹ️ Info: Use withWatcher: false for batch operations or temporary files to avoid flooding WebSocket listeners.

Best Practices

1. Validate Before Writing

// Check if file exists
const exists = await sandbox.files.exists({ filePath: path });

if (exists.exists) {
  // Read current content first
  const current = await sandbox.files.get({ filePath: path });
  // Merge or append instead of replacing
}

2. Use Atomic Operations

// ✅ Good - atomic write
await sandbox.files.edit({
  filePath: '/opt/app/config.json',
  content: newContent
});

// ❌ Bad - partial write
const file = await sandbox.files.get({ filePath: '/opt/app/config.json' });
// ... app crashes here ...
await sandbox.files.edit({ ... }); // Never executed

3. Handle Encoding

// For text files
await sandbox.files.create({
  filePath: '/opt/app/text.txt',
  content: 'Text content'
});

// For binary files, use base64
const imageBase64 = Buffer.from(binaryData).toString('base64');
await sandbox.files.upload({
  filePath: '/opt/app/image.png',
  content: imageBase64
});

4. Create Parent Directories

// Ensure parent directory exists
const filePath = '/opt/app/deep/nested/file.js';

// Create parent directories first
await sandbox.terminal.execute({
  command: `mkdir -p $(dirname ${filePath})`
});

// Then create file
await sandbox.files.create({
  filePath,
  content: 'export default {};'
});

Error Handling

try {
  await sandbox.files.edit({
    filePath: '/opt/app/readonly-file.txt',
    content: 'new content'
  });
} catch (error) {
  if (error.message.includes('Permission denied')) {
    console.log('File is read-only');
  } else if (error.message.includes('No such file')) {
    // Create it instead
    await sandbox.files.create({
      filePath: '/opt/app/readonly-file.txt',
      content: 'new content'
    });
  }
}

Next Steps