Ctrl + K

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

ParameterTypeDefaultDescription
ignorePatternsstring[][]Patterns to ignore (e.g., 'node_modules')
onChangefunction-File change callback
onAddfunction-File add callback
onUnlinkfunction-File delete callback
onErrorfunction-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 minute
const 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

EventWhen TriggeredCallback Parameter
changeFile modifiedpath (string)
addFile createdpath (string)
unlinkFile deletedpath (string)
errorWatch errorerror (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

  1. Always ignore common directories:

    ignorePatterns: ['node_modules', '.git', 'dist']
  2. Stop watcher when done: Clean up resources by stopping the watcher

  3. Handle errors: Listen for error events

  4. Debounce rapid changes: If a file changes frequently, debounce your handler

  5. 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