> ## Documentation Index
> Fetch the complete documentation index at: https://docs.novita.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Watch Events

You can watch a directory in the sandbox for filesystem events (file created, written, removed, renamed, or permission changed). The JS/TS SDK and the Python async SDK use a **callback** model, while the Python sync SDK uses a **polling** model - both return a `WatchHandle` that you stop with `stop()`.

***

## Event object & event types

Each filesystem event is a `FilesystemEvent` with two fields:

| Field  | Type                | Description                            |
| ------ | ------------------- | -------------------------------------- |
| `name` | string              | Relative path to the filesystem object |
| `type` | FilesystemEventType | The kind of filesystem operation       |

The `type` is one of the `FilesystemEventType` values:

| Constant                     | Value      | Description                     |
| ---------------------------- | ---------- | ------------------------------- |
| `FilesystemEventType.CHMOD`  | `'chmod'`  | Object permissions were changed |
| `FilesystemEventType.CREATE` | `'create'` | Object was created              |
| `FilesystemEventType.REMOVE` | `'remove'` | Object was removed              |
| `FilesystemEventType.RENAME` | `'rename'` | Object was renamed              |
| `FilesystemEventType.WRITE`  | `'write'`  | Object was written to           |

***

## Watch a directory (JavaScript / TypeScript)

`watchDir(path, onEvent, opts?)` starts watching and invokes `onEvent` for each event. It returns a `WatchHandle`; call `stop()` to stop watching.

| Parameter        | Type                             | Description                          |
| ---------------- | -------------------------------- | ------------------------------------ |
| `path`           | string                           | Directory to watch                   |
| `onEvent`        | (event: FilesystemEvent) => void | Called for each event                |
| `opts.recursive` | boolean (default false)          | Watch subdirectories too             |
| `opts.timeoutMs` | number (default 60000)           | Watch timeout in ms; `0` disables it |
| `opts.onExit`    | (err?: Error) => void            | Called when watching stops           |
| `opts.user`      | string                           | Run the operation as this user       |

```js JavaScript & TypeScript icon="js" theme={"system"}
import { Novita } from 'novita-sandbox'

const novita = new Novita()
const sandbox = await novita.codeInterpreter.create()

const handle = await sandbox.files.watchDir(
  '/tmp',
  (event) => {
    console.log(`[${event.type}] ${event.name}`)
  },
  { recursive: true }
)

// ... trigger some file changes ...

await handle.stop()
await sandbox.kill()
```

***

## Watch a directory (Python)

The Python sync SDK uses a polling model: `watch_dir(path, recursive=False)` returns a `WatchHandle`, and you call `get_new_events()` to pull the events that occurred since the last call. Stop with `stop()`.

| Parameter         | Type                 | Description                    |
| ----------------- | -------------------- | ------------------------------ |
| `path`            | str                  | Directory to watch             |
| `user`            | str (optional)       | Run the operation as this user |
| `request_timeout` | float (optional)     | Request timeout in seconds     |
| `recursive`       | bool (default False) | Watch subdirectories too       |

```python Python icon="python" theme={"system"}
import time
from novita_sandbox import Novita

novita = Novita()
sandbox = novita.code_interpreter.create()

watcher = sandbox.files.watch_dir('/tmp', recursive=True)

try:
    while True:
        events = watcher.get_new_events()
        for e in events:
            print(f'[{e.type.value}] {e.name}')
        time.sleep(1)
except KeyboardInterrupt:
    watcher.stop()
    sandbox.kill()
```

The Python **async** SDK uses a callback model instead: pass an `on_event` callback to `watch_dir`, which returns an `AsyncWatchHandle`. Stop with `await handle.stop()`.

```python Python icon="python" theme={"system"}
import asyncio
from novita_sandbox import AsyncCodeInterpreterSandbox

async def main():
    sandbox = await AsyncCodeInterpreterSandbox.create()

    def on_event(e):
        print(f'[{e.type.value}] {e.name}')

    handle = await sandbox.files.watch_dir('/tmp', on_event=on_event, recursive=True)

    # ... trigger some file changes ...

    await handle.stop()
    await sandbox.kill()

asyncio.run(main())
```

<Note>
  **Note:** Recursive watching (`recursive=True`) requires an up-to-date template. If the template is too old, the SDK raises a template error asking you to rebuild it with `novita-sandbox-cli template build`.
</Note>
