> ## 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.

# Cloud-Based IDE Backend

> Build a Replit/CodeSandbox-style online IDE with file system management, terminal emulation, and multi-file project execution

Build a production-ready cloud-based IDE backend that provides file system management, terminal access, and code execution. This cookbook demonstrates how to create a backend similar to Replit or CodeSandbox using HopX for secure execution.

## Overview

Cloud-based IDEs allow developers to code, run, and debug applications entirely in the browser. The backend manages file systems, provides terminal access, executes code, and handles real-time updates. HopX provides the secure execution environment needed for this use case.

## Prerequisites

* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of WebSocket connections
* Basic knowledge of IDE architecture

## Architecture

```
┌──────────────┐
│   Browser    │ Editor, Terminal UI
└──────┬───────┘
       │ WebSocket/HTTP
       ▼
┌─────────────────┐
│  IDE Backend    │ File ops, Terminal, Execution
└──────┬──────────┘
       │
       ▼
┌─────────────────┐
│  HopX Sandbox   │ Secure execution environment
└─────────────────┘
```

## Implementation

### Step 1: File System Management

Create a file system manager for the IDE:

<CodeGroup>
  ```python Python theme={null}
  from hopx_ai import Sandbox
  import os
  from typing import Dict, List, Any

  class IDEFileSystem:
      def __init__(self, api_key: str):
          self.api_key = api_key
          self.sandbox = None
      
      def initialize_project(self, project_id: str) -> Dict[str, Any]:
          """Initialize a new project sandbox"""
          try:
              self.sandbox = Sandbox.create(
                  template="code-interpreter",
                  api_key=self.api_key,
                  timeout_seconds=3600  # 1 hour for IDE session
              )
              
              # Create project structure
              self.sandbox.files.mkdir("/workspace/project")
              self.sandbox.files.write("/workspace/project/.gitignore", "__pycache__/\n*.pyc\n")
              
              return {
                  "success": True,
                  "sandbox_id": self.sandbox.sandbox_id,
                  "project_path": "/workspace/project"
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e)
              }
      
      def list_files(self, path: str = "/workspace/project") -> List[Dict[str, Any]]:
          """List files and directories"""
          try:
              files = self.sandbox.files.list(path)
              return [
                  {
                      "name": f.name,
                      "path": f.path,
                      "is_dir": f.is_dir,
                      "size": f.size,
                      "modified": f.modified_time.isoformat() if hasattr(f.modified_time, 'isoformat') else str(f.modified_time)
                  }
                  for f in files
              ]
          except Exception as e:
              return []
      
      def read_file(self, file_path: str) -> Dict[str, Any]:
          """Read file contents"""
          try:
              content = self.sandbox.files.read(file_path)
              return {
                  "success": True,
                  "content": content,
                  "path": file_path
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e),
                  "path": file_path
              }
      
      def write_file(self, file_path: str, content: str) -> Dict[str, Any]:
          """Write file contents"""
          try:
              self.sandbox.files.write(file_path, content)
              return {
                  "success": True,
                  "path": file_path,
                  "size": len(content)
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e),
                  "path": file_path
              }
      
      def create_directory(self, dir_path: str) -> Dict[str, Any]:
          """Create a directory"""
          try:
              self.sandbox.files.mkdir(dir_path)
              return {
                  "success": True,
                  "path": dir_path
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e),
                  "path": dir_path
              }
      
      def delete_file(self, file_path: str) -> Dict[str, Any]:
          """Delete a file or directory"""
          try:
              self.sandbox.files.remove(file_path)
              return {
                  "success": True,
                  "path": file_path
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e),
                  "path": file_path
              }
      
      def cleanup(self):
          """Clean up sandbox"""
          if self.sandbox:
              self.sandbox.kill()
              self.sandbox = None

  # Usage
  fs = IDEFileSystem(api_key=os.getenv("HOPX_API_KEY"))
  result = fs.initialize_project("my-project")
  print(result)

  # List files
  files = fs.list_files()
  print(files)

  # Create a file
  fs.write_file("/workspace/project/main.py", "print('Hello, World!')")

  # Read the file
  content = fs.read_file("/workspace/project/main.py")
  print(content)

  fs.cleanup()
  ```

  ```javascript JavaScript theme={null}
  import { Sandbox } from '@hopx-ai/sdk';

  class IDEFileSystem {
      constructor(apiKey) {
          this.apiKey = apiKey;
          this.sandbox = null;
      }
      
      async initializeProject(projectId) {
          try {
              this.sandbox = await Sandbox.create({
                  template: 'code-interpreter',
                  apiKey: this.apiKey,
                  timeoutSeconds: 3600  // 1 hour for IDE session
              });
              
              // Create project structure
              await this.sandbox.files.mkdir('/workspace/project');
              await this.sandbox.files.write('/workspace/project/.gitignore', '__pycache__/\n*.pyc\n');
              
              return {
                  success: true,
                  sandboxId: this.sandbox.sandboxId,
                  projectPath: '/workspace/project'
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message
              };
          }
      }
      
      async listFiles(path = '/workspace/project') {
          try {
              const files = await this.sandbox.files.list(path);
              return files.map(f => ({
                  name: f.name,
                  path: f.path,
                  isDir: f.isDir,
                  size: f.size,
                  modified: f.modifiedTime
              }));
          } catch (error) {
              return [];
          }
      }
      
      async readFile(filePath) {
          try {
              const content = await this.sandbox.files.read(filePath);
              return {
                  success: true,
                  content,
                  path: filePath
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message,
                  path: filePath
              };
          }
      }
      
      async writeFile(filePath, content) {
          try {
              await this.sandbox.files.write(filePath, content);
              return {
                  success: true,
                  path: filePath,
                  size: content.length
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message,
                  path: filePath
              };
          }
      }
      
      async createDirectory(dirPath) {
          try {
              await this.sandbox.files.mkdir(dirPath);
              return {
                  success: true,
                  path: dirPath
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message,
                  path: dirPath
              };
          }
      }
      
      async deleteFile(filePath) {
          try {
              await this.sandbox.files.remove(filePath);
              return {
                  success: true,
                  path: filePath
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message,
                  path: filePath
              };
          }
      }
      
      async cleanup() {
          if (this.sandbox) {
              await this.sandbox.kill();
              this.sandbox = null;
          }
      }
  }

  // Usage
  const fs = new IDEFileSystem(process.env.HOPX_API_KEY);
  const result = await fs.initializeProject('my-project');
  console.log(result);

  // List files
  const files = await fs.listFiles();
  console.log(files);

  // Create a file
  await fs.writeFile('/workspace/project/main.py', "print('Hello, World!')");

  // Read the file
  const content = await fs.readFile('/workspace/project/main.py');
  console.log(content);

  await fs.cleanup();
  ```
</CodeGroup>

### Step 2: Terminal Emulation

Implement terminal access using WebSocket:

<CodeGroup>
  ```python Python theme={null}
  import asyncio
  from typing import AsyncIterator, Dict, Any

  class IDETerminal:
      def __init__(self, sandbox: Sandbox):
          self.sandbox = sandbox
          self.terminal_session = None
      
      async def connect(self) -> Dict[str, Any]:
          """Connect to terminal"""
          try:
              self.terminal_session = await self.sandbox.terminal.connect()
              return {
                  "success": True,
                  "session_id": str(self.terminal_session)
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e)
              }
      
      async def send_command(self, command: str) -> None:
          """Send command to terminal"""
          if self.terminal_session:
              await self.sandbox.terminal.send_input(
                  self.terminal_session,
                  command + "\n"
              )
      
      async def receive_output(self) -> AsyncIterator[Dict[str, Any]]:
          """Receive terminal output"""
          if not self.terminal_session:
              return
          
          async for message in self.sandbox.terminal.iter_output(self.terminal_session):
              yield {
                  "type": message.get("type", "output"),
                  "data": message.get("data", ""),
                  "timestamp": message.get("timestamp")
              }
      
      async def resize(self, rows: int, cols: int) -> None:
          """Resize terminal"""
          if self.terminal_session:
              await self.sandbox.terminal.resize(
                  self.terminal_session,
                  rows=rows,
                  cols=cols
              )
      
      async def disconnect(self):
          """Disconnect from terminal"""
          self.terminal_session = None

  # Usage
  sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
  terminal = IDETerminal(sandbox)

  await terminal.connect()
  await terminal.send_command("pwd")
  await terminal.send_command("ls -la")

  async for output in terminal.receive_output():
      print(output)
      # Break after some outputs
      break

  await terminal.disconnect()
  sandbox.kill()
  ```

  ```javascript JavaScript theme={null}
  class IDETerminal {
      constructor(sandbox) {
          this.sandbox = sandbox;
          this.terminalSession = null;
      }
      
      async connect() {
          try {
              this.terminalSession = await this.sandbox.terminal.connect();
              return {
                  success: true,
                  sessionId: String(this.terminalSession)
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message
              };
          }
      }
      
      async sendCommand(command) {
          if (this.terminalSession) {
              await this.sandbox.terminal.sendInput(
                  this.terminalSession,
                  command + '\n'
              );
          }
      }
      
      async *receiveOutput() {
          if (!this.terminalSession) {
              return;
          }
          
          for await (const message of this.sandbox.terminal.iterOutput(this.terminalSession)) {
              yield {
                  type: message.type || 'output',
                  data: message.data || '',
                  timestamp: message.timestamp
              };
          }
      }
      
      async resize(rows, cols) {
          if (this.terminalSession) {
              await this.sandbox.terminal.resize(
                  this.terminalSession,
                  rows,
                  cols
              );
          }
      }
      
      async disconnect() {
          this.terminalSession = null;
      }
  }

  // Usage
  const sandbox = await Sandbox.create({
      template: 'code-interpreter',
      apiKey: process.env.HOPX_API_KEY
  });
  const terminal = new IDETerminal(sandbox);

  await terminal.connect();
  await terminal.sendCommand('pwd');
  await terminal.sendCommand('ls -la');

  for await (const output of terminal.receiveOutput()) {
      console.log(output);
      // Break after some outputs
      break;
  }

  await terminal.disconnect();
  await sandbox.kill();
  ```
</CodeGroup>

### Step 3: Multi-File Project Execution

Execute projects with multiple files:

<CodeGroup>
  ```python Python theme={null}
  class IDEProjectExecutor:
      def __init__(self, sandbox: Sandbox):
          self.sandbox = sandbox
      
      def execute_project(self, entry_point: str, working_dir: str = "/workspace/project") -> Dict[str, Any]:
          """Execute a multi-file project"""
          try:
              # Determine language from file extension
              language = self._detect_language(entry_point)
              
              # Execute in project directory
              result = self.sandbox.run_code(
                  self._get_execution_code(entry_point, language),
                  language=language,
                  working_dir=working_dir,
                  timeout=30
              )
              
              return {
                  "success": result.success,
                  "stdout": result.stdout,
                  "stderr": result.stderr,
                  "exit_code": result.exit_code,
                  "execution_time": result.execution_time
              }
          except Exception as e:
              return {
                  "success": False,
                  "error": str(e)
              }
      
      def _detect_language(self, file_path: str) -> str:
          """Detect language from file extension"""
          ext = file_path.split('.')[-1].lower()
          language_map = {
              'py': 'python',
              'js': 'javascript',
              'ts': 'typescript',
              'java': 'java',
              'go': 'go'
          }
          return language_map.get(ext, 'python')
      
      def _get_execution_code(self, entry_point: str, language: str) -> str:
          """Get code to execute based on language"""
          if language == 'python':
              return f"exec(open('{entry_point}').read())"
          elif language == 'javascript':
              return f"require('{entry_point.replace('.js', '')}')"
          else:
              # For other languages, use appropriate execution method
              return f"# Execute {entry_point}"

  # Usage
  sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
  executor = IDEProjectExecutor(sandbox)

  # Create a multi-file project
  sandbox.files.write("/workspace/project/utils.py", """
  def greet(name):
      return f"Hello, {name}!"
  """)

  sandbox.files.write("/workspace/project/main.py", """
  from utils import greet
  print(greet("World"))
  """)

  # Execute
  result = executor.execute_project("main.py")
  print(result)

  sandbox.kill()
  ```

  ```javascript JavaScript theme={null}
  class IDEProjectExecutor {
      constructor(sandbox) {
          this.sandbox = sandbox;
      }
      
      async executeProject(entryPoint, workingDir = '/workspace/project') {
          try {
              // Determine language from file extension
              const language = this.detectLanguage(entryPoint);
              
              // Execute in project directory
              const executionCode = this.getExecutionCode(entryPoint, language);
              const result = await this.sandbox.runCode(executionCode, {
                  language,
                  workingDir,
                  timeout: 30
              });
              
              return {
                  success: result.success,
                  stdout: result.stdout,
                  stderr: result.stderr,
                  exitCode: result.exit_code,
                  executionTime: result.execution_time
              };
          } catch (error) {
              return {
                  success: false,
                  error: error.message
              };
          }
      }
      
      detectLanguage(filePath) {
          const ext = filePath.split('.').pop().toLowerCase();
          const languageMap = {
              'py': 'python',
              'js': 'javascript',
              'ts': 'typescript',
              'java': 'java',
              'go': 'go'
          };
          return languageMap[ext] || 'python';
      }
      
      getExecutionCode(entryPoint, language) {
          if (language === 'python') {
              return `exec(open('${entryPoint}').read())`;
          } else if (language === 'javascript') {
              return `require('${entryPoint.replace('.js', '')}')`;
          } else {
              return `# Execute ${entryPoint}`;
          }
      }
  }

  // Usage
  const sandbox = await Sandbox.create({
      template: 'code-interpreter',
      apiKey: process.env.HOPX_API_KEY
  });
  const executor = new IDEProjectExecutor(sandbox);

  // Create a multi-file project
  await sandbox.files.write('/workspace/project/utils.py', `
  def greet(name):
      return f"Hello, {name}!"
  `);

  await sandbox.files.write('/workspace/project/main.py', `
  from utils import greet
  print(greet("World"))
  `);

  // Execute
  const result = await executor.executeProject('main.py');
  console.log(result);

  await sandbox.kill();
  ```
</CodeGroup>

### Step 4: Complete IDE Backend

Combine all components into a complete IDE backend:

<CodeGroup>
  ```python Python theme={null}
  class CloudIDEBackend:
      def __init__(self, api_key: str):
          self.api_key = api_key
          self.fs = IDEFileSystem(api_key)
          self.sandbox = None
          self.terminal = None
          self.executor = None
      
      def initialize(self, project_id: str) -> Dict[str, Any]:
          """Initialize IDE session"""
          result = self.fs.initialize_project(project_id)
          if result["success"]:
              self.sandbox = self.fs.sandbox
              self.terminal = IDETerminal(self.sandbox)
              self.executor = IDEProjectExecutor(self.sandbox)
          return result
      
      async def handle_file_operation(self, operation: str, **kwargs) -> Dict[str, Any]:
          """Handle file operations"""
          if operation == "list":
              return {"files": self.fs.list_files(kwargs.get("path", "/workspace/project"))}
          elif operation == "read":
              return self.fs.read_file(kwargs["path"])
          elif operation == "write":
              return self.fs.write_file(kwargs["path"], kwargs["content"])
          elif operation == "create_dir":
              return self.fs.create_directory(kwargs["path"])
          elif operation == "delete":
              return self.fs.delete_file(kwargs["path"])
          else:
              return {"success": False, "error": f"Unknown operation: {operation}"}
      
      async def handle_terminal_command(self, command: str) -> Dict[str, Any]:
          """Handle terminal command"""
          if not self.terminal.terminal_session:
              await self.terminal.connect()
          
          await self.terminal.send_command(command)
          
          # Collect output
          outputs = []
          async for output in self.terminal.receive_output():
              outputs.append(output)
              if len(outputs) >= 10:  # Limit output
                  break
          
          return {"outputs": outputs}
      
      def handle_execution(self, entry_point: str) -> Dict[str, Any]:
          """Handle code execution"""
          return self.executor.execute_project(entry_point)
      
      def cleanup(self):
          """Clean up all resources"""
          if self.terminal:
              asyncio.run(self.terminal.disconnect())
          self.fs.cleanup()

  # Usage
  ide = CloudIDEBackend(api_key=os.getenv("HOPX_API_KEY"))
  ide.initialize("my-project")

  # File operations
  result = asyncio.run(ide.handle_file_operation("write", path="/workspace/project/app.py", content="print('Hello')"))
  print(result)

  # Terminal
  result = asyncio.run(ide.handle_terminal_command("ls -la"))
  print(result)

  # Execution
  result = ide.handle_execution("app.py")
  print(result)

  ide.cleanup()
  ```

  ```javascript JavaScript theme={null}
  class CloudIDEBackend {
      constructor(apiKey) {
          this.apiKey = apiKey;
          this.fs = new IDEFileSystem(apiKey);
          this.sandbox = null;
          this.terminal = null;
          this.executor = null;
      }
      
      async initialize(projectId) {
          const result = await this.fs.initializeProject(projectId);
          if (result.success) {
              this.sandbox = this.fs.sandbox;
              this.terminal = new IDETerminal(this.sandbox);
              this.executor = new IDEProjectExecutor(this.sandbox);
          }
          return result;
      }
      
      async handleFileOperation(operation, ...args) {
          const kwargs = args[0] || {};
          
          if (operation === 'list') {
              return { files: await this.fs.listFiles(kwargs.path || '/workspace/project') };
          } else if (operation === 'read') {
              return await this.fs.readFile(kwargs.path);
          } else if (operation === 'write') {
              return await this.fs.writeFile(kwargs.path, kwargs.content);
          } else if (operation === 'createDir') {
              return await this.fs.createDirectory(kwargs.path);
          } else if (operation === 'delete') {
              return await this.fs.deleteFile(kwargs.path);
          } else {
              return { success: false, error: `Unknown operation: ${operation}` };
          }
      }
      
      async handleTerminalCommand(command) {
          if (!this.terminal.terminalSession) {
              await this.terminal.connect();
          }
          
          await this.terminal.sendCommand(command);
          
          // Collect output
          const outputs = [];
          for await (const output of this.terminal.receiveOutput()) {
              outputs.push(output);
              if (outputs.length >= 10) {  // Limit output
                  break;
              }
          }
          
          return { outputs };
      }
      
      async handleExecution(entryPoint) {
          return await this.executor.executeProject(entryPoint);
      }
      
      async cleanup() {
          if (this.terminal) {
              await this.terminal.disconnect();
          }
          await this.fs.cleanup();
      }
  }

  // Usage
  const ide = new CloudIDEBackend(process.env.HOPX_API_KEY);
  await ide.initialize('my-project');

  // File operations
  const result1 = await ide.handleFileOperation('write', {
      path: '/workspace/project/app.py',
      content: "print('Hello')"
  });
  console.log(result1);

  // Terminal
  const result2 = await ide.handleTerminalCommand('ls -la');
  console.log(result2);

  // Execution
  const result3 = await ide.handleExecution('app.py');
  console.log(result3);

  await ide.cleanup();
  ```
</CodeGroup>

## Best Practices

### Security

<Warning>
  Always validate file paths to prevent directory traversal attacks. Never allow access to files outside the project directory.
</Warning>

1. **Path Validation**: Sanitize all file paths
2. **Resource Limits**: Set appropriate timeouts and memory limits
3. **Sandbox Isolation**: One sandbox per user/project
4. **Input Validation**: Validate all user inputs

### Performance

<Tip>
  Use file watching to detect changes and update the UI in real-time, reducing the need for polling.
</Tip>

1. **Sandbox Reuse**: Reuse sandboxes for the duration of an IDE session
2. **Caching**: Cache file listings and metadata
3. **Async Operations**: Use async/await for all I/O operations
4. **Connection Pooling**: Manage WebSocket connections efficiently

### User Experience

1. **Real-Time Updates**: Use file watching for live file updates
2. **Auto-Save**: Implement auto-save functionality
3. **Error Handling**: Provide clear error messages
4. **Progress Indicators**: Show execution progress

## Real-World Examples

This pattern is used by:

* **Replit**: Online IDE and coding platform
* **CodeSandbox**: Online code editor and prototyping tool
* **Gitpod**: Cloud development environments
* **GitHub Codespaces**: Cloud-based VS Code

## Related Cookbooks

* [Browser-Based Code Editor](/cookbooks/development/browser-editor) - Client-side implementation
* [Terminal WebSocket](/core-concepts/terminal/websocket) - Terminal integration
* [Code Execution](/core-concepts/code-execution/synchronous) - Execution concepts

## Next Steps

1. Implement WebSocket server for real-time communication
2. Add file watching for live updates
3. Create a frontend editor interface
4. Implement package management (pip, npm, etc.)
5. Add debugging support
