File Watcher
Watch directories for file system changes in real time. The watcher monitors filesystem events and streams them over the WebSocket connection at /ws.
Requires the internal server to be enabled. Up to 5 concurrent watchers per workspace.
Overview
1. Create a watcher via REST → get watcher ID
2. Open WebSocket at /ws → receive "ready" event
3. File changes in watched dir → receive "change" events
4. Delete watcher when done → cleanupWatcher events arrive as JSON text frames on the "watcher" channel of the same WebSocket used for terminal I/O.
Create watcher
Start watching a directory for changes. The watcher recursively monitors all subdirectories and streams events over the WebSocket.
const watcher = await ws.watcher.create('ws_a1b2c3d4', {
path: '/app/src',
excludes: ['*.log', 'tmp'],
});
console.log(watcher.id); // "1"
console.log(watcher.root); // "/app/src"
console.log(watcher.dirs); // 42POST https://workspace.oblien.com/watchers
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"path": "/app/src",
"excludes": ["*.log", "tmp"]
}curl -X POST "https://workspace.oblien.com/watchers" \
-H "Authorization: Bearer $GATEWAY_JWT" \
-H "Content-Type: application/json" \
-d '{"path": "/app/src", "excludes": ["*.log", "tmp"]}'Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Directory to watch (recursively) |
excludes | string[] | No | Glob patterns to exclude (merged with defaults) |
Response
{
"id": "1",
"root": "/app/src",
"dirs": 42,
"excludes": ["node_modules", ".git", "*.log", "tmp"]
}Default excludes
These patterns are always excluded, even if you don't specify any:
node_modules, .git, .svn, .hg, __pycache__, .pytest_cache,
.mypy_cache, .next, .nuxt, dist, build, .DS_Store, *.swp, *.swo, *~Your custom excludes are merged with these defaults.
List watchers
Get all active watchers.
const watchers = await ws.watcher.list('ws_a1b2c3d4');
for (const w of watchers) {
console.log(`${w.id}: watching ${w.root} (${w.dirs} dirs)`);
}GET https://workspace.oblien.com/watchers
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/watchers" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"watchers": [
{
"id": "1",
"root": "/app/src",
"dirs": 42,
"excludes": ["node_modules", ".git"]
}
]
}Get watcher
Get info for a specific watcher.
GET https://workspace.oblien.com/watchers/1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/watchers/1" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"id": "1",
"root": "/app/src",
"dirs": 42,
"excludes": ["node_modules", ".git"]
}Delete watcher
Stop a watcher and release its resources.
await ws.watcher.delete('ws_a1b2c3d4', '1');DELETE https://workspace.oblien.com/watchers/1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl -X DELETE "https://workspace.oblien.com/watchers/1" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"success": true
}WebSocket events
Watcher events are delivered as JSON text frames on the "watcher" channel of the /ws WebSocket. All events include the watcher_id so you can distinguish events from multiple watchers on the same connection.
ready
Sent immediately after a watcher is created and has finished scanning the directory tree.
{
"channel": "watcher",
"type": "ready",
"watcher_id": "1",
"root": "/app/src",
"dirs": 42
}change
Sent when a file is created, modified, deleted, or renamed within the watched directory.
{
"channel": "watcher",
"type": "change",
"watcher_id": "1",
"path": "/app/src/index.ts",
"op": "write"
}Operations
op value | Trigger |
|---|---|
create | File or directory created, or moved into the watched tree |
write | File content modified or saved |
remove | File or directory deleted |
rename | File or directory moved out of the watched tree |
Events are debounced - rapid changes to the same path within 50ms are collapsed into a single event with the last operation.
overflow
Sent when the event queue overflows. This means some events may have been lost.
{
"channel": "watcher",
"type": "overflow",
"watcher_id": "1",
"message": "Event queue overflow, some events may have been lost"
}If you receive an overflow event, re-sync the file tree by listing the directory to get the current state.
Listening for events
Connect to the same WebSocket used for terminal I/O. Text frames with "channel": "watcher" are file watcher events.
const socket = new WebSocket('wss://workspace.oblien.com/ws', {
headers: { Authorization: `Bearer ${gatewayJwt}` },
});
socket.onmessage = (event) => {
if (typeof event.data === 'string') {
const msg = JSON.parse(event.data);
if (msg.channel === 'watcher') {
switch (msg.type) {
case 'ready':
console.log(`Watcher ${msg.watcher_id} ready: ${msg.root} (${msg.dirs} dirs)`);
break;
case 'change':
console.log(`${msg.op}: ${msg.path}`);
break;
case 'overflow':
console.log('Events may have been lost, re-syncing...');
break;
}
}
}
};Limits
| Limit | Value |
|---|---|
| Max concurrent watchers | 5 per workspace |
| Debounce interval | 50ms per path |
| Auto-watch new subdirectories | Yes |
| Excludes | Merged with defaults, glob matching |
Error responses
| Status | Meaning |
|---|---|
400 | Missing or invalid path |
401 | Missing or invalid token |
404 | Watcher not found |
409 | Already at 5 watchers limit |
500 | Failed to create file watcher |