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:
Strategy | Description |
---|---|
append | Add content to end of file |
prepend | Add content to beginning of file |
replace | Replace 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
- Learn about File Operations overview
- Check File Reading for reading files
- Explore File Watcher for change notifications