> ## 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 template build`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.