File Watcher
Monitor file system changes in real-time through WebSocket. Get notified when files are added, modified, or deleted.
Start Watching
// Start watching - WebSocket auto-connects
await sandbox.watcher.start({
ignorePatterns: ['node_modules', '.git', 'dist'],
onChange: (path) => {
console.log('📝 File changed:', path);
},
onAdd: (path) => {
console.log('➕ File added:', path);
},
onUnlink: (path) => {
console.log('➖ File deleted:', path);
},
onError: (error) => {
console.error('❌ Watch error:', error);
}
});
console.log('Watching for file changes...');
// Watcher runs in background...const ws = new WebSocket(
`wss://${sandbox.url.replace('https://', '')}/ws?token=${sandbox.token}`
);
ws.onopen = () => {
// Start watching
ws.send(JSON.stringify({
type: 'watch',
ignorePatterns: ['node_modules', '.git', 'dist']
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'watch_add') {
console.log('File added:', message.path);
}
if (message.type === 'watch_change') {
console.log('File changed:', message.path);
}
if (message.type === 'watch_unlink') {
console.log('File deleted:', message.path);
}
if (message.type === 'watch_error') {
console.error('Watch error:', message.error);
}
};WebSocket watcher using websocat:
# Connect to WebSocket
websocat "wss://sandbox.oblien.com/ws?token=YOUR_SANDBOX_TOKEN"
# Start watching (send this JSON):
{"type":"watch","ignorePatterns":["node_modules",".git","dist"]}
# You'll receive events like:
# {"type":"watch_add","path":"/opt/app/newfile.js"}
# {"type":"watch_change","path":"/opt/app/index.js"}
# {"type":"watch_unlink","path":"/opt/app/oldfile.js"}Stop Watching
sandbox.watcher.stop();
console.log('Stopped watching files');ws.send(JSON.stringify({
type: 'stop_watch'
}));# Using websocat
websocat "wss://sandbox.oblien.com/ws?token=YOUR_SANDBOX_TOKEN"
# Stop watching:
{"type":"stop_watch"}Event Handlers
Using Callbacks (SDK)
await sandbox.watcher.start({
onChange: (path) => console.log('Changed:', path),
onAdd: (path) => console.log('Added:', path),
onUnlink: (path) => console.log('Deleted:', path)
});Using Event Listeners (SDK)
// Start watcher
await sandbox.watcher.start({
ignorePatterns: ['node_modules']
});
// Add event listeners
sandbox.watcher.on('change', (path) => {
console.log('File changed:', path);
});
sandbox.watcher.on('add', (path) => {
console.log('File added:', path);
});
sandbox.watcher.on('unlink', (path) => {
console.log('File deleted:', path);
});
// Remove event listener
const handler = (path) => console.log(path);
sandbox.watcher.on('change', handler);
// Later...
sandbox.watcher.off('change', handler);Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
ignorePatterns | string[] | [] | Patterns to ignore (e.g., 'node_modules') |
onChange | function | - | File change callback |
onAdd | function | - | File add callback |
onUnlink | function | - | File delete callback |
onError | function | - | Error callback |
Common Ignore Patterns
const ignorePatterns = [
'node_modules', // Dependencies
'.git', // Git directory
'dist', // Build output
'build', // Build output
'.next', // Next.js
'*.log', // Log files
'.DS_Store', // macOS
'coverage' // Test coverage
];
await sandbox.watcher.start({ ignorePatterns });Complete Example
// Start watching
await sandbox.watcher.start({
ignorePatterns: ['node_modules', '.git', 'dist'],
onChange: async (path) => {
console.log(`📝 ${path} changed`);
// Auto-run tests on file change
if (path.endsWith('.js') || path.endsWith('.ts')) {
console.log('Running tests...');
const result = await sandbox.terminal.execute({
command: 'npm test',
cwd: '/opt/app'
});
if (result.exitCode === 0) {
console.log('✅ Tests passed');
} else {
console.log('❌ Tests failed');
}
}
},
onAdd: (path) => {
console.log(`➕ ${path} added`);
},
onUnlink: (path) => {
console.log(`➖ ${path} deleted`);
}
});
console.log('Watching for changes...');
// Make some changes
await sandbox.files.edit({
filePath: '/opt/app/src/index.js',
content: '// Updated code'
});
// Watcher will notify about the change
// Stop watching when done
setTimeout(() => {
sandbox.watcher.stop();
console.log('Stopped watching');
}, 60000); // Stop after 1 minuteconst ws = new WebSocket(
`wss://${sandbox.url.replace('https://', '')}/ws?token=${sandbox.token}`
);
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'watch',
ignorePatterns: ['node_modules', '.git', 'dist']
}));
console.log('Watching for changes...');
};
ws.onmessage = async (event) => {
const message = JSON.parse(event.data);
if (message.type === 'watch_change') {
console.log(`File changed: ${message.path}`);
// Auto-run tests
if (message.path.endsWith('.js')) {
console.log('Running tests...');
// Trigger test execution
}
}
};
// Stop watching
setTimeout(() => {
ws.send(JSON.stringify({ type: 'stop_watch' }));
}, 60000);# Using websocat for real-time watching
websocat "wss://sandbox.oblien.com/ws?token=YOUR_SANDBOX_TOKEN"
# Start watching:
{"type":"watch","ignorePatterns":["node_modules",".git","dist"]}
# Monitor events in real-time:
# {"type":"watch_change","path":"/opt/app/src/index.js"}
# {"type":"watch_add","path":"/opt/app/newfile.js"}
# {"type":"watch_unlink","path":"/opt/app/oldfile.js"}
# Stop watching:
{"type":"stop_watch"}Use Cases
Auto-Run Tests
await sandbox.watcher.start({
ignorePatterns: ['node_modules', 'dist'],
onChange: async (path) => {
if (path.endsWith('.test.js')) {
await sandbox.terminal.execute({
command: 'npm test',
cwd: '/opt/app'
});
}
}
});Hot Reload Detection
await sandbox.watcher.start({
onChange: (path) => {
console.log(`Hot reload triggered for ${path}`);
// Notify frontend to reload
}
});Build on Change
await sandbox.watcher.start({
ignorePatterns: ['node_modules', 'dist'],
onChange: async (path) => {
if (path.includes('/src/')) {
console.log('Source changed, rebuilding...');
await sandbox.terminal.execute({
command: 'npm run build',
cwd: '/opt/app'
});
}
}
});Sync to Database
await sandbox.watcher.start({
onChange: async (path) => {
const content = await sandbox.files.get({ filePath: path });
// Save to database
await saveToDatabase(path, content.content);
}
});Check Watcher Status
// Check if watching
if (sandbox.watcher.isWatching) {
console.log('Watcher is active');
} else {
console.log('Watcher is stopped');
}
// Or use active property
if (sandbox.watcher.active) {
console.log('Actively watching');
}Events
| Event | When Triggered | Callback Parameter |
|---|---|---|
change | File modified | path (string) |
add | File created | path (string) |
unlink | File deleted | path (string) |
error | Watch error | error (object) |
Integration with File Operations
The withWatcher parameter controls whether file operations trigger events:
// Start watcher
await sandbox.watcher.start({
onChange: (path) => console.log('Changed:', path)
});
// This WILL trigger the watcher
await sandbox.files.edit({
filePath: '/opt/app/file.js',
content: 'new content',
withWatcher: true // default
});
// This WON'T trigger the watcher
await sandbox.files.edit({
filePath: '/opt/app/file.js',
content: 'new content',
withWatcher: false
});Best Practices
-
Always ignore common directories:
ignorePatterns: ['node_modules', '.git', 'dist'] -
Stop watcher when done: Clean up resources by stopping the watcher
-
Handle errors: Listen for error events
-
Debounce rapid changes: If a file changes frequently, debounce your handler
-
Use with terminal: Combine with terminal to auto-run commands
Debouncing Example
let timeout;
await sandbox.watcher.start({
onChange: (path) => {
// Debounce - wait 500ms after last change
clearTimeout(timeout);
timeout = setTimeout(async () => {
console.log('Running build after changes...');
await sandbox.terminal.execute({
command: 'npm run build',
cwd: '/opt/app'
});
}, 500);
}
});Next Steps
- WebSocket - Real-time terminal access
- File Operations - Work with files
- Terminal - Execute commands