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

# Watching

> Watch filesystem for real-time changes via WebSocket in HopX sandboxes. Monitor file and directory changes in real-time, receive notifications for file modifications, and react to filesystem events. Perfect for build systems, file processing pipelines, and real-time monitoring. Includes Python and JavaScript SDK examples and WebSocket API endpoints.

Watch filesystem for real-time changes. Get notified immediately when files are created, modified, deleted, or renamed in your sandbox.

## Overview

File watching is perfect for:

* Real-time monitoring of file changes
* Building reactive applications
* Detecting when outputs are generated
* Implementing file-based workflows

<Note>
  File watching uses WebSocket connections for real-time communication. It requires async/await support and the websockets library (Python).
</Note>

## Basic File Watching

Watch a directory for changes:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from hopx_ai import Sandbox
    import asyncio

    async def watch_files():
        sandbox = Sandbox.create(template="code-interpreter")
        
        # Start watching
        print("👀 Watching /workspace for changes...")
        event_count = 0
        
        async for event in sandbox.files.watch("/workspace"):
            event_type = event.get('event', 'unknown')
            path = event.get('path', '')
            
            print(f"{event_type}: {path}")
            
            event_count += 1
            if event_count >= 10:
                print("Stopping after 10 events")
                break
        
        sandbox.kill()

    asyncio.run(watch_files())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    import { Sandbox } from '@hopx-ai/sdk';

    async function watchFiles() {
      const sandbox = await Sandbox.create({ template: 'code-interpreter' });
      
      // Start watching
      console.log('👀 Watching /workspace for changes...');
      let eventCount = 0;
      
      for await (const event of sandbox.files.watch('/workspace')) {
        const eventType = event.event || 'unknown';
        const path = event.path || '';
        
        console.log(`${eventType}: ${path}`);
        
        eventCount++;
        if (eventCount >= 10) {
          console.log('Stopping after 10 events');
          break;
        }
      }
      
      await sandbox.kill();
    }

    watchFiles();
    ```
  </Tab>
</Tabs>

## Event Types

Handle different file system events:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from hopx_ai import Sandbox
    import asyncio

    async def handle_all_events():
        sandbox = Sandbox.create(template="code-interpreter")
        
        async for event in sandbox.files.watch("/workspace"):
            event_type = event.get('event', 'unknown')
            path = event.get('path', '')
            timestamp = event.get('timestamp', '')
            
            if event_type == 'created':
                print(f"📄 Created: {path}")
            elif event_type == 'modified':
                print(f"✏️  Modified: {path}")
            elif event_type == 'deleted':
                print(f"🗑️  Deleted: {path}")
            elif event_type == 'renamed':
                old_path = event.get('old_path', '')
                print(f"📝 Renamed: {old_path} → {path}")
            else:
                print(f"❓ Unknown event: {event_type} - {path}")

    asyncio.run(handle_all_events())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    import { Sandbox } from '@hopx-ai/sdk';

    async function handleAllEvents() {
      const sandbox = await Sandbox.create({ template: 'code-interpreter' });
      
      for await (const event of sandbox.files.watch('/workspace')) {
        const eventType = event.event || 'unknown';
        const path = event.path || '';
        const timestamp = event.timestamp || '';
        
        if (eventType === 'created') {
          console.log(`📄 Created: ${path}`);
        } else if (eventType === 'modified') {
          console.log(`✏️  Modified: ${path}`);
        } else if (eventType === 'deleted') {
          console.log(`🗑️  Deleted: ${path}`);
        } else if (eventType === 'renamed') {
          const oldPath = event.old_path || '';
          console.log(`📝 Renamed: ${oldPath} → ${path}`);
        } else {
          console.log(`❓ Unknown event: ${eventType} - ${path}`);
        }
      }
      
      await sandbox.kill();
    }

    handleAllEvents();
    ```
  </Tab>
</Tabs>

## Monitoring File Generation

Watch for generated output files:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from hopx_ai import Sandbox
    import asyncio

    async def monitor_outputs():
        sandbox = Sandbox.create(template="code-interpreter")
        
        # Start background task that generates files
        sandbox.run_code_background('''
    import time
    import json

    for i in range(5):
        data = {"step": i, "value": i * 2}
        with open(f'/workspace/output_{i}.json', 'w') as f:
            json.dump(data, f)
        time.sleep(2)
    ''', name='file-generator')
        
        # Watch for new files
        print("👀 Watching for output files...")
        output_files = []
        
        async for event in sandbox.files.watch("/workspace"):
            if event.get('event') == 'created':
                path = event.get('path', '')
                if path.startswith('/workspace/output_'):
                    output_files.append(path)
                    print(f"✅ New output: {path}")
                    
                    if len(output_files) >= 5:
                        print("All outputs generated!")
                        break
        
        print(f"\nGenerated {len(output_files)} files")
        sandbox.kill()

    asyncio.run(monitor_outputs())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    import { Sandbox } from '@hopx-ai/sdk';

    async function monitorOutputs() {
      const sandbox = await Sandbox.create({ template: 'code-interpreter' });
      
      // Start background task that generates files
      await sandbox.runCodeBackground(`
    import time
    import json

    for i in range(5):
        data = {"step": i, "value": i * 2}
        with open(f'/workspace/output_{i}.json', 'w') as f:
            json.dump(data, f)
        time.sleep(2)
    `, { name: 'file-generator' });
      
      // Watch for new files
      console.log('👀 Watching for output files...');
      const outputFiles = [];
      
      for await (const event of sandbox.files.watch('/workspace')) {
        if (event.event === 'created') {
          const path = event.path || '';
          if (path.startsWith('/workspace/output_')) {
            outputFiles.push(path);
            console.log(`✅ New output: ${path}`);
            
            if (outputFiles.length >= 5) {
              console.log('All outputs generated!');
              break;
            }
          }
        }
      }
      
      console.log(`\nGenerated ${outputFiles.length} files`);
      await sandbox.kill();
    }

    monitorOutputs();
    ```
  </Tab>
</Tabs>

## Filtering Events

Filter events by type or path:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from hopx_ai import Sandbox
    import asyncio

    async def filter_events():
        sandbox = Sandbox.create(template="code-interpreter")
        
        # Only watch for Python files
        async for event in sandbox.files.watch("/workspace"):
            event_type = event.get('event', '')
            path = event.get('path', '')
            
            # Only process Python files
            if path.endswith('.py'):
                if event_type == 'created':
                    print(f"📄 New Python file: {path}")
                elif event_type == 'modified':
                    print(f"✏️  Python file modified: {path}")
                elif event_type == 'deleted':
                    print(f"🗑️  Python file deleted: {path}")

    asyncio.run(filter_events())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    import { Sandbox } from '@hopx-ai/sdk';

    async function filterEvents() {
      const sandbox = await Sandbox.create({ template: 'code-interpreter' });
      
      // Only watch for Python files
      for await (const event of sandbox.files.watch('/workspace')) {
        const eventType = event.event || '';
        const path = event.path || '';
        
        // Only process Python files
        if (path.endsWith('.py')) {
          if (eventType === 'created') {
            console.log(`📄 New Python file: ${path}`);
          } else if (eventType === 'modified') {
            console.log(`✏️  Python file modified: ${path}`);
          } else if (eventType === 'deleted') {
            console.log(`🗑️  Python file deleted: ${path}`);
          }
        }
      }
      
      await sandbox.kill();
    }

    filterEvents();
    ```
  </Tab>
</Tabs>

## Complete Example

Here's a complete file watching workflow:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from hopx_ai import Sandbox
    import asyncio

    async def complete_watch_example():
        sandbox = Sandbox.create(template="code-interpreter")
        
        # Start a task that creates/modifies files
        sandbox.run_code_background('''
    import time
    import json

    # Create initial file
    with open('/workspace/status.json', 'w') as f:
        json.dump({"status": "starting"}, f)

    time.sleep(1)

    # Modify file
    with open('/workspace/status.json', 'w') as f:
        json.dump({"status": "processing"}, f)

    time.sleep(1)

    # Create output file
    with open('/workspace/result.txt', 'w') as f:
        f.write("Processing complete")

    time.sleep(1)

    # Delete status file
    import os
    os.remove('/workspace/status.json')
    ''', name='file-operations')
        
        # Watch for all events
        print("👀 Watching filesystem...\n")
        events_received = []
        
        async for event in sandbox.files.watch("/workspace"):
            event_type = event.get('event', 'unknown')
            path = event.get('path', '')
            timestamp = event.get('timestamp', '')
            
            events_received.append({
                'type': event_type,
                'path': path,
                'timestamp': timestamp
            })
            
            # Display event
            icons = {
                'created': '📄',
                'modified': '✏️',
                'deleted': '🗑️',
                'renamed': '📝'
            }
            icon = icons.get(event_type, '❓')
            print(f"{icon} {event_type.upper()}: {path}")
            
            # Stop after receiving all expected events
            if len(events_received) >= 4:
                print("\n✅ All events received")
                break
        
        # Summary
        print(f"\n📊 Summary: Received {len(events_received)} events")
        for e in events_received:
            print(f"  - {e['type']}: {e['path']}")
        
        sandbox.kill()

    asyncio.run(complete_watch_example())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    import { Sandbox } from '@hopx-ai/sdk';

    async function completeWatchExample() {
      const sandbox = await Sandbox.create({ template: 'code-interpreter' });
      
      // Start a task that creates/modifies files
      await sandbox.runCodeBackground(`
    import time
    import json

    # Create initial file
    with open('/workspace/status.json', 'w') as f:
        json.dump({"status": "starting"}, f)

    time.sleep(1)

    # Modify file
    with open('/workspace/status.json', 'w') as f:
        json.dump({"status": "processing"}, f)

    time.sleep(1)

    # Create output file
    with open('/workspace/result.txt', 'w') as f:
        f.write("Processing complete")

    time.sleep(1)

    # Delete status file
    import os
    os.remove('/workspace/status.json')
    `, { name: 'file-operations' });
      
      // Watch for all events
      console.log('👀 Watching filesystem...\n');
      const eventsReceived = [];
      
      for await (const event of sandbox.files.watch('/workspace')) {
        const eventType = event.event || 'unknown';
        const path = event.path || '';
        const timestamp = event.timestamp || '';
        
        eventsReceived.push({
          type: eventType,
          path: path,
          timestamp: timestamp
        });
        
        // Display event
        const icons = {
          'created': '📄',
          'modified': '✏️',
          'deleted': '🗑️',
          'renamed': '📝'
        };
        const icon = icons[eventType] || '❓';
        console.log(`${icon} ${eventType.toUpperCase()}: ${path}`);
        
        // Stop after receiving all expected events
        if (eventsReceived.length >= 4) {
          console.log('\n✅ All events received');
          break;
        }
      }
      
      // Summary
      console.log(`\n📊 Summary: Received ${eventsReceived.length} events`);
      for (const e of eventsReceived) {
        console.log(`  - ${e.type}: ${e.path}`);
      }
      
      await sandbox.kill();
    }

    completeWatchExample();
    ```
  </Tab>
</Tabs>

## Best Practices

<Steps>
  <Step title="1. Use Async/Await">
    File watching requires async/await. Make sure your code uses async functions and `async for` loops.
  </Step>

  <Step title="2. Filter Events">
    Filter events by type or path pattern to process only relevant changes.
  </Step>

  <Step title="3. Handle All Event Types">
    Process created, modified, deleted, and renamed events appropriately for your use case.
  </Step>

  <Step title="4. Set Timeout Limits">
    Consider setting timeouts or event count limits to avoid infinite watching.
  </Step>

  <Step title="5. Clean Up Connections">
    Always break the watch loop and clean up connections when done.
  </Step>
</Steps>

## Related

* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents
* **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes
* **SDK**: [sandbox.files.watch()](/sdk/python/files#watch) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI

## Next Steps

* Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Explore [Writing Files](/core-concepts/filesystem/writing) to create files
* Review [Listing Files](/core-concepts/filesystem/listing) to browse directories
