File Watching
Monitor filesystem changes in real-time using Linux's native inotify system. The watch() method returns a Server-Sent Events (SSE) stream of file change events that you consume with parseSSEStream().
Watch a directory for filesystem changes. Returns an SSE stream of events.
const stream = await sandbox.watch(path: string, options?: WatchOptions): Promise<ReadableStream<Uint8Array>>Parameters:
path- Absolute path or relative to/workspace(for example,/app/srcorsrc)options(optional):recursive- Watch subdirectories recursively (default:true)include- Glob patterns to include (for example,['*.ts', '*.js']). Cannot be used together withexclude.exclude- Glob patterns to exclude (default:['.git', 'node_modules', '.DS_Store']). Cannot be used together withinclude.sessionId- Session to run the watch in (if omitted, the default session is used)
Returns: Promise<ReadableStream<Uint8Array>> — an SSE stream of FileWatchSSEEvent objects
import { parseSSEStream } from "@cloudflare/sandbox";const stream = await sandbox.watch("/workspace/src", { recursive: true, include: ["*.ts", "*.js"],});
const controller = new AbortController();
for await (const event of parseSSEStream(stream, controller.signal)) { switch (event.type) { case "watching": console.log(`Watch established on ${event.path} (id: ${event.watchId})`); break; case "event": console.log(`${event.eventType}: ${event.path}`); break; case "error": console.error(`Watch error: ${event.error}`); break; case "stopped": console.log(`Watch stopped: ${event.reason}`); break; }}
// Cancel the watch by aborting — cleans up the watcher server-sidecontroller.abort();import { parseSSEStream } from "@cloudflare/sandbox";import type { FileWatchSSEEvent } from "@cloudflare/sandbox";
const stream = await sandbox.watch("/workspace/src", { recursive: true, include: ["*.ts", "*.js"],});
const controller = new AbortController();
for await (const event of parseSSEStream<FileWatchSSEEvent>( stream, controller.signal,)) { switch (event.type) { case "watching": console.log(`Watch established on ${event.path} (id: ${event.watchId})`); break; case "event": console.log(`${event.eventType}: ${event.path}`); break; case "error": console.error(`Watch error: ${event.error}`); break; case "stopped": console.log(`Watch stopped: ${event.reason}`); break; }}
// Cancel the watch by aborting — cleans up the watcher server-sidecontroller.abort();Union type of all SSE events emitted by the watch stream.
type FileWatchSSEEvent = | { type: "watching"; path: string; watchId: string } | { type: "event"; eventType: FileWatchEventType; path: string; isDirectory: boolean; timestamp: string; } | { type: "error"; error: string } | { type: "stopped"; reason: string };watching— Emitted once when the watch is established. Contains thewatchIdand thepathbeing watched.event— Emitted for each filesystem change. Contains theeventType, thepaththat changed, and whether itisDirectory.error— Emitted when the watch encounters an error.stopped— Emitted when the watch is stopped, with areason.
Types of filesystem changes that can be detected.
type FileWatchEventType = | "create" | "modify" | "delete" | "move_from" | "move_to" | "attrib";create— File or directory was createdmodify— File content changeddelete— File or directory was deletedmove_from— File or directory was moved away (source of a rename/move)move_to— File or directory was moved here (destination of a rename/move)attrib— File or directory attributes changed (permissions, timestamps)
Configuration options for watching directories.
interface WatchOptions { /** Watch subdirectories recursively (default: true) */ recursive?: boolean; /** Glob patterns to include. Cannot be used together with `exclude`. */ include?: string[]; /** Glob patterns to exclude. Cannot be used together with `include`. Default: ['.git', 'node_modules', '.DS_Store'] */ exclude?: string[]; /** Session to run the watch in. If omitted, the default session is used. */ sessionId?: string;}Converts a ReadableStream<Uint8Array> into a typed AsyncGenerator of events. Accepts an optional AbortSignal to cancel the stream.
function parseSSEStream<T>( stream: ReadableStream<Uint8Array>, signal?: AbortSignal,): AsyncGenerator<T>;Parameters:
stream— The SSE stream returned bywatch()signal(optional) — AnAbortSignalto cancel the stream. When aborted, the reader is cancelled which propagates cleanup to the server.
Aborting the signal is the recommended way to stop a watch from outside the consuming loop:
const controller = new AbortController();
// Cancel after 60 secondssetTimeout(() => controller.abort(), 60_000);
for await (const event of parseSSEStream<FileWatchSSEEvent>( stream, controller.signal,)) { // process events}The include and exclude options accept a limited set of glob tokens for predictable matching:
| Token | Meaning | Example |
|---|---|---|
* | Match any characters within a path segment | *.ts matches index.ts |
** | Match across directory boundaries | **/*.test.ts |
? | Match a single character | ?.js matches a.js |
Character classes ([abc]), brace expansion ({a,b}), and backslash escapes are not supported. Patterns containing these tokens are rejected with a validation error.
- Watch filesystem changes guide — Patterns, best practices, and real-world examples
- Manage files guide — File operations