claude-code-templates 1.21.5 → 1.21.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,169 @@
1
+ # Claude Code Sandbox Components
2
+
3
+ Execute Claude Code in isolated cloud environments for secure code generation and development.
4
+
5
+ ## Available Sandbox Providers
6
+
7
+ ### E2B Sandbox (`e2b`)
8
+ Run Claude Code in E2B's secure cloud environment with pre-configured development tools.
9
+
10
+ **Component**: `e2b/claude-code-sandbox.md`
11
+
12
+ **Files Created**:
13
+ - `.claude/sandbox/e2b-launcher.py` - Python launcher script
14
+ - `.claude/sandbox/requirements.txt` - Python dependencies
15
+ - `.claude/sandbox/.env.example` - Environment variables template
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # Simple execution with API keys as parameters (recommended)
21
+ npx claude-code-templates@latest --sandbox e2b \
22
+ --e2b-api-key your_e2b_key \
23
+ --anthropic-api-key your_anthropic_key \
24
+ --prompt "Create a React todo app"
25
+
26
+ # With components installation
27
+ npx claude-code-templates@latest --sandbox e2b \
28
+ --e2b-api-key your_e2b_key \
29
+ --anthropic-api-key your_anthropic_key \
30
+ --agent frontend-developer \
31
+ --command setup-react \
32
+ --prompt "Create a modern todo app with TypeScript"
33
+
34
+ # Or use environment variables (set E2B_API_KEY and ANTHROPIC_API_KEY)
35
+ npx claude-code-templates@latest --sandbox e2b --prompt "Create a React todo app"
36
+ ```
37
+
38
+ ## Environment Setup
39
+
40
+ 1. **Get API Keys**:
41
+ - E2B API Key: https://e2b.dev/dashboard
42
+ - Anthropic API Key: https://console.anthropic.com
43
+
44
+ 2. **Create Environment File**:
45
+ ```bash
46
+ # In your project/.claude/sandbox/.env
47
+ E2B_API_KEY=your_e2b_api_key_here
48
+ ANTHROPIC_API_KEY=your_anthropic_api_key_here
49
+ ```
50
+
51
+ 3. **Install Python Requirements** (handled automatically):
52
+ - Python 3.11+
53
+ - E2B Python SDK
54
+ - python-dotenv
55
+
56
+ ## How It Works
57
+
58
+ 1. **Component Download**: Downloads sandbox launcher and requirements
59
+ 2. **Environment Check**: Validates Python 3.11+ installation
60
+ 3. **Dependencies**: Installs E2B Python SDK automatically
61
+ 4. **Sandbox Creation**: Creates E2B sandbox with Claude Code template
62
+ 5. **Component Installation**: Installs any specified agents/commands/mcps/settings/hooks inside sandbox
63
+ 6. **Prompt Execution**: Runs your prompt through Claude Code in the isolated environment
64
+ 7. **Result Display**: Shows complete output and generated files
65
+ 8. **Cleanup**: Automatically destroys sandbox after execution
66
+
67
+ ## Usage Examples
68
+
69
+ ### Basic Web Development
70
+ ```bash
71
+ npx claude-code-templates@latest --sandbox e2b --prompt "Create an HTML page with modern CSS animations"
72
+ ```
73
+
74
+ ### Full Stack with Components
75
+ ```bash
76
+ npx claude-code-templates@latest --sandbox e2b \
77
+ --agent fullstack-developer \
78
+ --command setup-node \
79
+ --prompt "Create a Node.js API with JWT authentication"
80
+ ```
81
+
82
+ ### Data Analysis
83
+ ```bash
84
+ npx claude-code-templates@latest --sandbox e2b \
85
+ --agent data-scientist \
86
+ --prompt "Analyze this CSV data and create visualizations"
87
+ ```
88
+
89
+ ### Security Audit
90
+ ```bash
91
+ npx claude-code-templates@latest --sandbox e2b \
92
+ --agent security-auditor \
93
+ --command security-audit \
94
+ --prompt "Review this codebase for security vulnerabilities"
95
+ ```
96
+
97
+ ## Security Benefits
98
+
99
+ - ✅ **Complete Isolation**: Code runs in separate cloud environment
100
+ - ✅ **No Local Impact**: Zero risk to your local system or files
101
+ - ✅ **Temporary Environment**: Sandbox destroyed after execution
102
+ - ✅ **Controlled Access**: Only specified components are installed
103
+ - ✅ **API Key Security**: Keys never leave your local environment
104
+
105
+ ## Future Sandbox Providers
106
+
107
+ ## ✅ Production Ready Features (v1.20.3+)
108
+
109
+ ### Enhanced E2B Integration
110
+ - **Automatic File Download**: Generated files are automatically downloaded to local `./e2b-output/` directory
111
+ - **Extended Timeouts**: 15-minute sandbox lifetime with intelligent timeout management
112
+ - **Detailed Logging**: Step-by-step execution monitoring with debugging information
113
+ - **Environment Verification**: Automatic checks for Claude Code installation and permissions
114
+ - **Error Recovery**: Retry logic for connection issues and comprehensive error handling
115
+
116
+ ### Advanced Debugging Tools
117
+ - **Real-time Monitor** (`e2b-monitor.py`): System resource monitoring and performance analysis
118
+ - **Debug Guide** (`SANDBOX_DEBUGGING.md`): Comprehensive troubleshooting documentation
119
+ - **Sandbox State Tracking**: Live monitoring of file system changes and process execution
120
+
121
+ The system is designed to support multiple sandbox providers:
122
+
123
+ - **E2B** (`--sandbox e2b`) - ✅ **Fully Implemented** - Cloud-based isolated execution environment
124
+ - **Docker** (`--sandbox docker`) - 🔄 Future - Local containerized execution
125
+ - **AWS CodeBuild** (`--sandbox aws`) - 🔄 Future - AWS-based sandbox environment
126
+ - **GitHub Codespaces** (`--sandbox github`) - 🔄 Future - GitHub's cloud development environment
127
+ - **Custom** (`--sandbox custom`) - 🔄 Future - User-defined sandbox configurations
128
+
129
+ ## Troubleshooting
130
+
131
+ ### Python Not Found
132
+ ```bash
133
+ # Install Python 3.11+
134
+ brew install python3 # macOS
135
+ # or visit https://python.org/downloads
136
+ ```
137
+
138
+ ### API Keys Not Set
139
+ ```bash
140
+ # Create .env file in .claude/sandbox/
141
+ echo "E2B_API_KEY=your_key_here" >> .claude/sandbox/.env
142
+ echo "ANTHROPIC_API_KEY=your_key_here" >> .claude/sandbox/.env
143
+ ```
144
+
145
+ ### Dependencies Installation Failed
146
+ ```bash
147
+ # Manual installation
148
+ cd .claude/sandbox
149
+ pip3 install -r requirements.txt
150
+ ```
151
+
152
+ ## Component Architecture
153
+
154
+ ```
155
+ claude-code-templates/
156
+ └── cli-tool/
157
+ └── components/
158
+ └── sandbox/
159
+ ├── e2b/ # E2B provider
160
+ │ ├── claude-code-sandbox.md # Component documentation
161
+ │ ├── e2b-launcher.py # Python launcher script
162
+ │ ├── requirements.txt # Python dependencies
163
+ │ └── .env.example # Environment template
164
+ ├── docker/ # Future: Docker provider
165
+ ├── aws/ # Future: AWS provider
166
+ └── README.md # This file
167
+ ```
168
+
169
+ The sandbox system integrates seamlessly with the existing Claude Code Templates component architecture, allowing any combination of agents, commands, MCPs, settings, and hooks to be installed and used within the secure sandbox environment.
@@ -0,0 +1,10 @@
1
+ # E2B API Configuration
2
+ # Get your API key from: https://e2b.dev/dashboard
3
+ E2B_API_KEY=your_e2b_api_key_here
4
+
5
+ # Anthropic API Configuration
6
+ # Get your API key from: https://console.anthropic.com
7
+ ANTHROPIC_API_KEY=your_anthropic_api_key_here
8
+
9
+ # Optional: Sandbox timeout in seconds (default: 300)
10
+ # E2B_TIMEOUT=300
@@ -0,0 +1,203 @@
1
+ # E2B Sandbox Debugging Guide
2
+
3
+ ## 🔍 Herramientas de Monitoreo Disponibles
4
+
5
+ ### 1. Launcher Principal con Logging Mejorado
6
+ **Archivo**: `e2b-launcher.py`
7
+ - Logging detallado de cada paso
8
+ - Verificación de instalación de Claude Code
9
+ - Monitoreo de permisos y ambiente
10
+ - Timeouts extendidos para operaciones largas
11
+ - Descarga automática de archivos generados
12
+
13
+ ### 2. Monitor de Sandbox en Tiempo Real
14
+ **Archivo**: `e2b-monitor.py`
15
+ - Monitoreo de recursos del sistema
16
+ - Tracking de file system en tiempo real
17
+ - Análisis de performance y memory usage
18
+ - Logging con timestamps detallados
19
+
20
+ ### 3. Simulador Demo
21
+ Para testing sin API keys válidos, crea un archivo demo que simule el flujo completo.
22
+
23
+ ## 🚨 Troubleshooting Común
24
+
25
+ ### Problema: "Sandbox timeout"
26
+ **Síntomas**:
27
+ ```
28
+ ❌ Error: The sandbox was not found: This error is likely due to sandbox timeout
29
+ ```
30
+
31
+ **Soluciones**:
32
+ 1. **Aumentar timeout del sandbox**:
33
+ ```python
34
+ sbx = Sandbox.create(timeout=600) # 10 minutos
35
+ sbx.set_timeout(900) # Extender a 15 minutos
36
+ ```
37
+
38
+ 2. **Usar el monitor para ver qué consume tiempo**:
39
+ ```bash
40
+ python e2b-monitor.py "Your prompt here" "" your_e2b_key your_anthropic_key
41
+ ```
42
+
43
+ ### Problema: "Claude not found"
44
+ **Síntomas**:
45
+ ```
46
+ ❌ Claude not found, checking PATH...
47
+ ```
48
+
49
+ **Debugging Steps**:
50
+ 1. **Verificar template correcto**:
51
+ ```python
52
+ template="anthropic-claude-code" # Debe ser exactamente este
53
+ ```
54
+
55
+ 2. **Verificar instalación en sandbox**:
56
+ ```bash
57
+ # El launcher ejecuta automáticamente:
58
+ which claude
59
+ claude --version
60
+ echo $PATH
61
+ ```
62
+
63
+ ### Problema: "Permission denied"
64
+ **Síntomas**:
65
+ ```
66
+ ❌ Write permission issue
67
+ ```
68
+
69
+ **Soluciones**:
70
+ 1. **Verificar directorio de trabajo**:
71
+ ```bash
72
+ pwd
73
+ whoami
74
+ ls -la
75
+ ```
76
+
77
+ 2. **Cambiar a directorio con permisos**:
78
+ ```python
79
+ sbx.commands.run("cd /home/user && mkdir workspace && cd workspace")
80
+ ```
81
+
82
+ ### Problema: API Key Issues
83
+ **Síntomas**:
84
+ ```
85
+ ❌ Error: 401: Invalid API key
86
+ ```
87
+
88
+ **Debugging**:
89
+ 1. **Verificar formato de API key**:
90
+ - E2B keys: formato específico de E2B
91
+ - Anthropic keys: empiezan con "sk-ant-"
92
+
93
+ 2. **Verificar permisos**:
94
+ - Verificar que la key tenga permisos de sandbox
95
+ - Verificar quota/límites de la cuenta
96
+
97
+ ## 📊 Usando el Monitor para Debugging
98
+
99
+ ### Comando Básico:
100
+ ```bash
101
+ python e2b-monitor.py "Create a React app" "" your_e2b_key your_anthropic_key
102
+ ```
103
+
104
+ ### Output del Monitor:
105
+ ```
106
+ [14:32:15] INFO: 🚀 Starting enhanced E2B sandbox with monitoring
107
+ [14:32:16] INFO: ✅ Sandbox created: abc123xyz
108
+ [14:32:17] INFO: 🔍 System resources check
109
+ [14:32:17] INFO: Memory usage:
110
+ [14:32:17] INFO: total used free
111
+ [14:32:17] INFO: Mem: 2.0Gi 512Mi 1.5Gi
112
+ [14:32:18] INFO: 📁 Initial file system state
113
+ [14:32:18] INFO: Current directory: /home/user
114
+ [14:32:19] INFO: 🤖 Executing Claude Code with monitoring
115
+ [14:32:19] INFO: Starting monitored execution: echo 'Create a React app'...
116
+ [14:32:22] INFO: Command completed in 3.45 seconds
117
+ [14:32:22] INFO: Exit code: 0
118
+ [14:32:22] INFO: STDOUT length: 2847 characters
119
+ ```
120
+
121
+ ## 🎯 Casos de Uso Específicos
122
+
123
+ ### 1. **Debugging Timeouts**
124
+ ```bash
125
+ # Usar el monitor para ver exactamente dónde se cuelga
126
+ python e2b-monitor.py "Complex prompt that times out"
127
+ ```
128
+
129
+ ### 2. **Verificar Generación de Archivos**
130
+ El launcher automáticamente descarga archivos generados:
131
+ ```
132
+ 💾 DOWNLOADING FILES TO LOCAL MACHINE:
133
+ ✅ Downloaded: ./index.html → ./e2b-output/index.html
134
+ ✅ Downloaded: ./styles.css → ./e2b-output/styles.css
135
+
136
+ 📁 All files downloaded to: /path/to/project/e2b-output
137
+ ```
138
+
139
+ ### 3. **Monitoreo de Performance**
140
+ ```
141
+ [14:33:20] INFO: Top processes:
142
+ [14:33:20] INFO: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
143
+ [14:33:20] INFO: user 1234 5.2 2.1 98765 43210 pts/0 S+ 14:32 0:01 claude
144
+ ```
145
+
146
+ ## 🛠 Configuración Avanzada
147
+
148
+ ### Variables de Ambiente Útiles:
149
+ ```bash
150
+ export E2B_DEBUG=1 # Debug mode
151
+ export ANTHROPIC_API_KEY=your_key # Claude API key
152
+ export E2B_API_KEY=your_key # E2B API key
153
+ ```
154
+
155
+ ### Configuración de Timeout Personalizada:
156
+ ```python
157
+ # Para operaciones muy largas (ej: compilación completa)
158
+ sbx = Sandbox.create(timeout=1800) # 30 minutos
159
+ sbx.set_timeout(3600) # 1 hora máximo
160
+ ```
161
+
162
+ ## 📋 Checklist de Debugging
163
+
164
+ ### Antes de Reportar un Issue:
165
+ - [ ] API keys válidos y con permisos correctos
166
+ - [ ] Template correcto: "anthropic-claude-code"
167
+ - [ ] Timeout suficiente para la operación
168
+ - [ ] Ejecutar con el monitor para logs detallados
169
+ - [ ] Verificar que Claude Code esté instalado en sandbox
170
+ - [ ] Revisar permisos de escritura en directorio
171
+ - [ ] Comprobar memoria/recursos disponibles
172
+
173
+ ### Información a Incluir en Reports:
174
+ - Output completo del launcher o monitor
175
+ - Sandbox ID si está disponible
176
+ - Prompt exacto que causa el problema
177
+ - Componentes instalados (si aplica)
178
+ - Tiempo de ejecución antes del fallo
179
+
180
+ ## 🚀 Funcionalidades del Sistema
181
+
182
+ ### Descarga Automática de Archivos
183
+ El launcher descarga automáticamente todos los archivos generados:
184
+ - HTML, CSS, JS, TS, TSX, Python, JSON, Markdown
185
+ - Se guardan en directorio local `./e2b-output/`
186
+ - Excluye archivos internos de Claude Code
187
+ - Preserva nombres de archivo originales
188
+
189
+ ### Logging Detallado
190
+ - Verificación de instalación de Claude Code
191
+ - Monitoreo de permisos y ambiente del sandbox
192
+ - Tracking de exit codes y output length
193
+ - Timestamps para análisis de performance
194
+
195
+ ### Timeouts Inteligentes
196
+ - 10 minutos timeout inicial para creación
197
+ - 15 minutos total extendido automáticamente
198
+ - 5 minutos timeout para ejecución de Claude Code
199
+ - Timeouts cortos para verificaciones (5-10 segundos)
200
+
201
+ ---
202
+
203
+ **Con estas herramientas puedes monitorear exactamente qué está pasando dentro del sandbox E2B y debuggear cualquier problema que surja.**
@@ -0,0 +1,110 @@
1
+ # E2B Claude Code Sandbox
2
+
3
+ Execute Claude Code in an isolated E2B cloud sandbox environment.
4
+
5
+ ## Description
6
+
7
+ This component sets up E2B (E2B.dev) integration to run Claude Code in a secure, isolated cloud environment. Perfect for executing code safely without affecting your local system.
8
+
9
+ ## Features
10
+
11
+ - **Isolated Execution**: Run Claude Code in a secure cloud sandbox
12
+ - **Pre-configured Environment**: Ships with Claude Code already installed
13
+ - **API Integration**: Seamless connection to Anthropic's Claude API
14
+ - **Safe Code Execution**: Execute prompts without local system risks
15
+ - **Component Installation**: Automatically installs any components specified with CLI flags
16
+
17
+ ## Requirements
18
+
19
+ - E2B API Key (get from https://e2b.dev/dashboard)
20
+ - Anthropic API Key
21
+ - Python 3.11+ (for E2B SDK)
22
+
23
+ ## Usage
24
+
25
+ ```bash
26
+ # Execute a prompt in E2B sandbox (requires API keys as environment variables or CLI parameters)
27
+ npx claude-code-templates@latest --sandbox e2b --prompt "Create a React todo app"
28
+
29
+ # Pass API keys directly as parameters
30
+ npx claude-code-templates@latest --sandbox e2b \
31
+ --e2b-api-key your_e2b_key \
32
+ --anthropic-api-key your_anthropic_key \
33
+ --prompt "Create a React todo app"
34
+
35
+ # Install components and execute in sandbox
36
+ npx claude-code-templates@latest --sandbox e2b \
37
+ --agent frontend-developer \
38
+ --command setup-react \
39
+ --e2b-api-key your_e2b_key \
40
+ --anthropic-api-key your_anthropic_key \
41
+ --prompt "Create a modern todo app with TypeScript"
42
+ ```
43
+
44
+ ## Environment Setup
45
+
46
+ The component will create:
47
+ - `.claude/sandbox/e2b-launcher.py` - Python script to launch E2B sandbox
48
+ - `.claude/sandbox/requirements.txt` - Python dependencies
49
+ - `.claude/sandbox/.env.example` - Environment variables template
50
+
51
+ ## API Key Configuration
52
+
53
+ You can provide API keys in two ways:
54
+
55
+ ### Option 1: CLI Parameters (Recommended)
56
+ ```bash
57
+ # Pass keys directly as command parameters
58
+ npx claude-code-templates@latest --sandbox e2b \
59
+ --e2b-api-key your_e2b_api_key \
60
+ --anthropic-api-key your_anthropic_api_key \
61
+ --prompt "Your prompt here"
62
+ ```
63
+
64
+ ### Option 2: Environment Variables
65
+ Set these environment variables in your shell or `.env` file:
66
+ ```bash
67
+ export E2B_API_KEY=your_e2b_api_key_here
68
+ export ANTHROPIC_API_KEY=your_anthropic_api_key_here
69
+
70
+ # Or create .claude/sandbox/.env file:
71
+ E2B_API_KEY=your_e2b_api_key_here
72
+ ANTHROPIC_API_KEY=your_anthropic_api_key_here
73
+ ```
74
+
75
+ **Note**: CLI parameters take precedence over environment variables.
76
+
77
+ ## How it Works
78
+
79
+ 1. Creates E2B sandbox with `anthropic-claude-code` template
80
+ 2. Installs any specified components (agents, commands, etc.)
81
+ 3. Executes your prompt using Claude Code inside the sandbox
82
+ 4. Returns the complete output and any generated files
83
+ 5. Automatically cleans up the sandbox after execution
84
+
85
+ ## Security Benefits
86
+
87
+ - **Isolation**: Code runs in a separate cloud environment
88
+ - **No Local Impact**: No risk to your local system or files
89
+ - **Temporary**: Sandbox is destroyed after execution
90
+ - **Controlled**: Only specified components and prompts are executed
91
+
92
+ ## Examples
93
+
94
+ ```bash
95
+ # Simple web app creation
96
+ npx claude-code-templates@latest --sandbox e2b --prompt "Create an HTML page with CSS animations"
97
+
98
+ # Full stack development
99
+ npx claude-code-templates@latest --sandbox e2b --agent fullstack-developer --prompt "Create a Node.js API with authentication"
100
+
101
+ # Data analysis
102
+ npx claude-code-templates@latest --sandbox e2b --agent data-scientist --prompt "Analyze this CSV data and create visualizations"
103
+ ```
104
+
105
+ ## Template Information
106
+
107
+ - **Provider**: E2B (https://e2b.dev)
108
+ - **Base Template**: anthropic-claude-code
109
+ - **Timeout**: 5 minutes (configurable)
110
+ - **Environment**: Ubuntu with Claude Code pre-installed
@@ -0,0 +1,426 @@
1
+ #!/usr/bin/env python3.11
2
+ """
3
+ E2B Claude Code Sandbox Launcher
4
+ Executes Claude Code prompts in isolated E2B cloud sandbox
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ import datetime
11
+ import re
12
+ import threading
13
+ import time
14
+
15
+ # Debug: Print Python path information
16
+ print(f"Python executable: {sys.executable}")
17
+ print(f"Python version: {sys.version}")
18
+ print(f"Python path: {sys.path[:3]}...") # Show first 3 paths
19
+
20
+ try:
21
+ from e2b import Sandbox
22
+ print("✓ E2B imported successfully")
23
+ except ImportError as e:
24
+ print(f"✗ E2B import failed: {e}")
25
+ print("Trying to install E2B...")
26
+ import subprocess
27
+ # Try different installation methods for different Python environments
28
+ install_commands = [
29
+ [sys.executable, '-m', 'pip', 'install', '--user', 'e2b'], # User install first
30
+ [sys.executable, '-m', 'pip', 'install', '--break-system-packages', 'e2b'], # System packages
31
+ [sys.executable, '-m', 'pip', 'install', 'e2b'] # Default fallback
32
+ ]
33
+
34
+ result = None
35
+ for cmd in install_commands:
36
+ print(f"Trying: {' '.join(cmd)}")
37
+ result = subprocess.run(cmd, capture_output=True, text=True)
38
+ if result.returncode == 0:
39
+ print("✓ Installation successful")
40
+ break
41
+ else:
42
+ print(f"✗ Failed: {result.stderr.strip()[:100]}...")
43
+
44
+ if result is None:
45
+ result = subprocess.run([sys.executable, '-m', 'pip', 'install', 'e2b'],
46
+ capture_output=True, text=True)
47
+ print(f"Install result: {result.returncode}")
48
+ if result.stdout:
49
+ print(f"Install stdout: {result.stdout}")
50
+ if result.stderr:
51
+ print(f"Install stderr: {result.stderr}")
52
+
53
+ # Try importing again
54
+ try:
55
+ from e2b import Sandbox
56
+ print("✓ E2B imported successfully after install")
57
+ except ImportError as e2:
58
+ print(f"✗ E2B still failed after install: {e2}")
59
+ sys.exit(1)
60
+
61
+ # Try to import and use dotenv if available, but don't fail if it's not
62
+ try:
63
+ from dotenv import load_dotenv
64
+ load_dotenv()
65
+ except ImportError:
66
+ # dotenv is optional since we can get keys from command line arguments
67
+ pass
68
+
69
+ def main():
70
+
71
+ # Parse command line arguments
72
+ if len(sys.argv) < 2:
73
+ print("Usage: python e2b-launcher.py <prompt> [components_to_install] [e2b_api_key] [anthropic_api_key]")
74
+ sys.exit(1)
75
+
76
+ prompt = sys.argv[1]
77
+ components_to_install = sys.argv[2] if len(sys.argv) > 2 else ""
78
+
79
+ # Get API keys from command line arguments or environment variables
80
+ e2b_api_key = sys.argv[3] if len(sys.argv) > 3 else os.getenv('E2B_API_KEY')
81
+ anthropic_api_key = sys.argv[4] if len(sys.argv) > 4 else os.getenv('ANTHROPIC_API_KEY')
82
+
83
+ if not e2b_api_key:
84
+ print("Error: E2B API key is required")
85
+ print("Provide via command line argument or E2B_API_KEY environment variable")
86
+ sys.exit(1)
87
+
88
+ if not anthropic_api_key:
89
+ print("Error: Anthropic API key is required")
90
+ print("Provide via command line argument or ANTHROPIC_API_KEY environment variable")
91
+ sys.exit(1)
92
+
93
+ try:
94
+ # Create E2B sandbox with Claude Code template with retry logic
95
+ print("🚀 Creating E2B sandbox with Claude Code...")
96
+
97
+ # Try creating sandbox with retries for WebSocket issues
98
+ max_retries = 3
99
+ retry_count = 0
100
+ sbx = None
101
+
102
+ while retry_count < max_retries and sbx is None:
103
+ try:
104
+ if retry_count > 0:
105
+ print(f"🔄 Retry {retry_count}/{max_retries - 1} - WebSocket connection...")
106
+
107
+ sbx = Sandbox.create(
108
+ template="anthropic-claude-code",
109
+ api_key=e2b_api_key,
110
+ envs={
111
+ 'ANTHROPIC_API_KEY': anthropic_api_key,
112
+ },
113
+ timeout=600, # 10 minutes timeout for longer operations
114
+ )
115
+
116
+ # Keep sandbox alive during operations
117
+ print(f"🔄 Extending sandbox timeout to prevent early termination...")
118
+ sbx.set_timeout(900) # 15 minutes total
119
+ print(f"✅ Sandbox created: {sbx.sandbox_id}")
120
+ break
121
+
122
+ except Exception as e:
123
+ error_msg = str(e).lower()
124
+ if "websocket" in error_msg or "connection" in error_msg or "timeout" in error_msg:
125
+ retry_count += 1
126
+ if retry_count < max_retries:
127
+ print(f"⚠️ WebSocket connection failed (attempt {retry_count}), retrying in 3 seconds...")
128
+ import time
129
+ time.sleep(3)
130
+ continue
131
+ else:
132
+ print(f"❌ WebSocket connection failed after {max_retries} attempts")
133
+ print("💡 This might be due to:")
134
+ print(" • Network/firewall restrictions blocking WebSocket connections")
135
+ print(" • Temporary E2B service issues")
136
+ print(" • Corporate proxy blocking WebSocket traffic")
137
+ print("💡 Try:")
138
+ print(" • Running from a different network")
139
+ print(" • Checking your firewall/proxy settings")
140
+ print(" • Waiting a few minutes and trying again")
141
+ raise e
142
+ else:
143
+ # Non-WebSocket error, don't retry
144
+ raise e
145
+
146
+ if sbx is None:
147
+ raise Exception("Failed to create sandbox after all retry attempts")
148
+
149
+ # Install components if specified
150
+ if components_to_install:
151
+ print("📦 Installing specified components...")
152
+ install_result = sbx.commands.run(
153
+ f"npx claude-code-templates@latest {components_to_install}",
154
+ timeout=120, # 2 minutes for component installation
155
+ )
156
+
157
+ if install_result.exit_code != 0:
158
+ print(f"⚠️ Component installation warnings:")
159
+ print(install_result.stderr)
160
+ else:
161
+ print("✅ Components installed successfully")
162
+
163
+ # Build enhanced prompt with instructions
164
+ # Parse components to extract agents
165
+ agents = []
166
+ if components_to_install:
167
+ # Split by '--' to get individual component types
168
+ parts = components_to_install.split('--')
169
+ for part in parts:
170
+ part = part.strip()
171
+ if part.startswith('agent '):
172
+ # Extract agent names after 'agent ' prefix
173
+ agent_names = part[6:].strip() # Remove 'agent ' prefix
174
+ if agent_names:
175
+ # Split by comma if multiple agents
176
+ agents.extend([a.strip() for a in agent_names.split(',')])
177
+
178
+ # Create enhanced prompt with proper instructions
179
+ if agents:
180
+ agent_list = ', '.join(agents)
181
+ enhanced_prompt = f"""You are Claude Code, an AI assistant specialized in software development.
182
+
183
+ IMPORTANT INSTRUCTIONS:
184
+ 1. Execute the user's request immediately and create the requested code/files
185
+ 2. You have access to the following specialized agents: {agent_list}
186
+ 3. Use these agents in the order you deem most appropriate for completing the task
187
+ 4. Generate all necessary files and code to fulfill the request
188
+ 5. Be proactive and create a complete, working implementation
189
+
190
+ USER REQUEST: {prompt}
191
+
192
+ Now, please execute this request and create all necessary files."""
193
+ else:
194
+ enhanced_prompt = f"""You are Claude Code, an AI assistant specialized in software development.
195
+
196
+ IMPORTANT INSTRUCTIONS:
197
+ 1. Execute the user's request immediately and create the requested code/files
198
+ 2. Generate all necessary files and code to fulfill the request
199
+ 3. Be proactive and create a complete, working implementation
200
+ 4. Don't just acknowledge the request - actually create the implementation
201
+
202
+ USER REQUEST: {prompt}
203
+
204
+ Now, please execute this request and create all necessary files."""
205
+
206
+ # Execute Claude Code with the enhanced prompt
207
+ print(f"🤖 Executing Claude Code with prompt: '{prompt[:50]}{'...' if len(prompt) > 50 else ''}'")
208
+ if agents:
209
+ print(f"🤝 Using agents: {', '.join(agents)}")
210
+
211
+ # First, check if Claude Code is installed and available
212
+ print("🔍 Checking Claude Code installation...")
213
+ check_result = sbx.commands.run("which claude", timeout=10)
214
+ if check_result.exit_code == 0:
215
+ print(f"✅ Claude found at: {check_result.stdout.strip()}")
216
+ else:
217
+ print("❌ Claude not found, checking PATH...")
218
+ path_result = sbx.commands.run("echo $PATH", timeout=5)
219
+ print(f"PATH: {path_result.stdout}")
220
+ ls_result = sbx.commands.run("ls -la /usr/local/bin/ | grep claude", timeout=5)
221
+ print(f"Claude binaries: {ls_result.stdout}")
222
+
223
+ # Check current directory and permissions
224
+ print("🔍 Checking sandbox environment...")
225
+ pwd_result = sbx.commands.run("pwd", timeout=5)
226
+ print(f"Current directory: {pwd_result.stdout.strip()}")
227
+
228
+ whoami_result = sbx.commands.run("whoami", timeout=5)
229
+ print(f"Current user: {whoami_result.stdout.strip()}")
230
+
231
+ # Check if we can write to current directory
232
+ test_write = sbx.commands.run("touch test_write.tmp && rm test_write.tmp", timeout=5)
233
+ if test_write.exit_code == 0:
234
+ print("✅ Write permissions OK")
235
+ else:
236
+ print("❌ Write permission issue")
237
+
238
+ # Build Claude Code command with enhanced prompt and better error handling
239
+ # Escape single quotes in the enhanced prompt
240
+ escaped_prompt = enhanced_prompt.replace("'", "'\\''")
241
+ claude_command = f"echo '{escaped_prompt}' | claude -p --dangerously-skip-permissions"
242
+
243
+ # Show the original user prompt in the command display (not the enhanced version)
244
+ display_prompt = prompt[:100] + '...' if len(prompt) > 100 else prompt
245
+ print(f"🚀 Running command: echo '{display_prompt}' | claude -p --dangerously-skip-permissions")
246
+
247
+ # Show loading message with visual separation
248
+ print("")
249
+ print("=" * 60)
250
+ print("☁️ EXECUTING CLAUDE CODE IN SECURE CLOUD SANDBOX")
251
+ print("=" * 60)
252
+ print("")
253
+ print(" ⏳ Starting execution...")
254
+ print(" 🔒 Isolated E2B environment active")
255
+ print(" 📡 Streaming real-time output below:")
256
+ print("")
257
+ print("-" * 60)
258
+ print("📝 LIVE OUTPUT:")
259
+ print("-" * 60)
260
+
261
+ # Collect output for later use
262
+ stdout_buffer = []
263
+ stderr_buffer = []
264
+
265
+ # Track if we've received any output and last activity time
266
+ has_output = [False] # Use list to allow modification in nested function
267
+ last_activity = [time.time()]
268
+ execution_complete = [False]
269
+
270
+ # Progress indicator thread
271
+ def show_progress():
272
+ """Show periodic progress updates if no output for a while"""
273
+ progress_messages = [
274
+ "⏳ Still processing...",
275
+ "🔄 Claude Code is working on your request...",
276
+ "⚙️ Analyzing requirements...",
277
+ "🛠️ Building solution...",
278
+ "📝 Generating code...",
279
+ "🔍 Reviewing implementation..."
280
+ ]
281
+ message_index = 0
282
+
283
+ while not execution_complete[0]:
284
+ time.sleep(5) # Check every 5 seconds
285
+
286
+ # If no activity for 10 seconds and no output yet
287
+ if not has_output[0] and (time.time() - last_activity[0]) > 10:
288
+ print(f"\n {progress_messages[message_index % len(progress_messages)]}")
289
+ message_index += 1
290
+ last_activity[0] = time.time()
291
+
292
+ # Start progress thread
293
+ progress_thread = threading.Thread(target=show_progress, daemon=True)
294
+ progress_thread.start()
295
+
296
+ # Define callbacks for streaming output
297
+ def on_stdout(data):
298
+ """Handle stdout output in real-time"""
299
+ if data:
300
+ # Mark that we've received output and update activity time
301
+ if not has_output[0]:
302
+ has_output[0] = True
303
+ print("\n🎯 Claude Code started responding:\n")
304
+
305
+ last_activity[0] = time.time()
306
+
307
+ # Print the data as it comes
308
+ print(data, end='', flush=True)
309
+ stdout_buffer.append(data)
310
+
311
+ def on_stderr(data):
312
+ """Handle stderr output in real-time"""
313
+ if data:
314
+ # Mark that we've received output and update activity time
315
+ if not has_output[0]:
316
+ has_output[0] = True
317
+ print("\n🎯 Claude Code started responding:\n")
318
+
319
+ last_activity[0] = time.time()
320
+
321
+ # Print stderr with warning prefix
322
+ if data.strip():
323
+ print(f"⚠️ {data}", end='', flush=True)
324
+ stderr_buffer.append(data)
325
+
326
+ # Execute with streaming output and extended timeout
327
+ try:
328
+ result = sbx.commands.run(
329
+ claude_command,
330
+ timeout=600, # 10 minutes timeout for complex operations
331
+ on_stdout=on_stdout,
332
+ on_stderr=on_stderr
333
+ )
334
+ finally:
335
+ # Mark execution as complete to stop progress thread
336
+ execution_complete[0] = True
337
+
338
+ # Join collected output
339
+ full_stdout = ''.join(stdout_buffer)
340
+ full_stderr = ''.join(stderr_buffer)
341
+
342
+ # Print execution summary
343
+ print("")
344
+ print("-" * 60)
345
+ print(f"🔍 Command exit code: {result.exit_code}")
346
+
347
+ # Since we already streamed the output, just show summary
348
+ if full_stdout:
349
+ print(f"📤 Total stdout: {len(full_stdout)} characters")
350
+ if full_stderr:
351
+ print(f"⚠️ Total stderr: {len(full_stderr)} characters")
352
+
353
+ # List generated files
354
+ print("=" * 60)
355
+ print("📁 GENERATED FILES:")
356
+ print("=" * 60)
357
+
358
+ files_result = sbx.commands.run("find . -type f \\( -name '*.html' -o -name '*.js' -o -name '*.css' -o -name '*.py' -o -name '*.json' -o -name '*.md' -o -name '*.tsx' -o -name '*.ts' \\) ! -path '*/.claude/*' ! -path '*/node_modules/*' | head -20")
359
+ if files_result.stdout.strip():
360
+ print(files_result.stdout)
361
+
362
+ # Download important files to local machine
363
+ print("\n" + "=" * 60)
364
+ print("💾 DOWNLOADING FILES TO LOCAL MACHINE:")
365
+ print("=" * 60)
366
+
367
+ # Create project directory with sandbox ID in current working directory
368
+ project_dir = f"sandbox-{sbx.sandbox_id[:8]}" # Use first 8 chars of sandbox ID
369
+ local_output_dir = os.path.join(os.getcwd(), project_dir) # Use current working directory
370
+
371
+ # Ensure the project directory exists
372
+ os.makedirs(local_output_dir, exist_ok=True)
373
+
374
+ print(f"📂 Downloading files to project directory: {local_output_dir}")
375
+ print(f"📍 Current working directory: {os.getcwd()}")
376
+
377
+ files_to_download = files_result.stdout.strip().split('\n')
378
+ for file_path in files_to_download:
379
+ file_path = file_path.strip()
380
+ if file_path: # Already filtered out .claude and node_modules in find command
381
+ try:
382
+ # Read file content from sandbox
383
+ file_content = sbx.commands.run(f"cat '{file_path}'", timeout=30)
384
+ if file_content.exit_code == 0:
385
+ # Preserve directory structure by removing leading ./
386
+ relative_path = file_path.lstrip('./')
387
+ local_file = os.path.join(local_output_dir, relative_path)
388
+
389
+ # Create directory structure if needed
390
+ os.makedirs(os.path.dirname(local_file), exist_ok=True)
391
+
392
+ # Write file locally
393
+ with open(local_file, 'w', encoding='utf-8') as f:
394
+ f.write(file_content.stdout)
395
+
396
+ print(f"✅ Downloaded: {file_path} → {local_file}")
397
+ else:
398
+ print(f"❌ Failed to read: {file_path}")
399
+ except Exception as e:
400
+ print(f"❌ Error downloading {file_path}: {e}")
401
+
402
+ print(f"\n📁 All files downloaded to: {os.path.abspath(local_output_dir)}")
403
+
404
+ else:
405
+ print("No common files generated")
406
+
407
+ print("=" * 60)
408
+ print(f"✅ Execution completed successfully")
409
+ print(f"🗂️ Sandbox ID: {sbx.sandbox_id}")
410
+ print("💡 Note: Sandbox will be automatically destroyed")
411
+
412
+ except Exception as e:
413
+ print(f"❌ Error executing Claude Code in sandbox: {str(e)}")
414
+ sys.exit(1)
415
+
416
+ finally:
417
+ # Cleanup sandbox
418
+ try:
419
+ if 'sbx' in locals():
420
+ sbx.kill()
421
+ print("🧹 Sandbox cleaned up")
422
+ except Exception as cleanup_error:
423
+ print(f"⚠️ Cleanup warning: {cleanup_error}")
424
+
425
+ if __name__ == "__main__":
426
+ main()
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env python3.11
2
+ """
3
+ E2B Sandbox Real-time Monitor
4
+ Provides real-time monitoring and debugging of E2B sandbox operations
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import time
10
+ import json
11
+ from datetime import datetime
12
+
13
+ def log_with_timestamp(message, level="INFO"):
14
+ timestamp = datetime.now().strftime("%H:%M:%S")
15
+ print(f"[{timestamp}] {level}: {message}")
16
+
17
+ def monitor_sandbox_execution(sbx, command, timeout=600):
18
+ """
19
+ Monitor sandbox command execution with real-time feedback
20
+ """
21
+ log_with_timestamp(f"Starting monitored execution: {command[:100]}...")
22
+
23
+ # Start command execution
24
+ start_time = time.time()
25
+ result = None
26
+
27
+ try:
28
+ # Execute command with monitoring
29
+ log_with_timestamp("Command started, monitoring execution...")
30
+
31
+ # For real implementation, you would run the command and monitor
32
+ # This is a template for when you have valid API keys
33
+ result = sbx.commands.run(command, timeout=timeout)
34
+
35
+ elapsed = time.time() - start_time
36
+ log_with_timestamp(f"Command completed in {elapsed:.2f} seconds")
37
+
38
+ # Log execution results
39
+ log_with_timestamp(f"Exit code: {result.exit_code}")
40
+ if result.stdout:
41
+ log_with_timestamp(f"STDOUT length: {len(result.stdout)} characters")
42
+ if len(result.stdout) < 500:
43
+ log_with_timestamp(f"STDOUT preview: {result.stdout[:200]}...")
44
+ if result.stderr:
45
+ log_with_timestamp(f"STDERR length: {len(result.stderr)} characters", "WARNING")
46
+ log_with_timestamp(f"STDERR: {result.stderr}", "ERROR")
47
+
48
+ return result
49
+
50
+ except Exception as e:
51
+ elapsed = time.time() - start_time
52
+ log_with_timestamp(f"Command failed after {elapsed:.2f} seconds: {e}", "ERROR")
53
+ raise e
54
+
55
+ def monitor_file_system(sbx, description="Monitoring file system"):
56
+ """
57
+ Monitor sandbox file system state
58
+ """
59
+ log_with_timestamp(f"📁 {description}")
60
+
61
+ try:
62
+ # Check current directory
63
+ pwd_result = sbx.commands.run("pwd", timeout=10)
64
+ log_with_timestamp(f"Current directory: {pwd_result.stdout.strip()}")
65
+
66
+ # List files
67
+ ls_result = sbx.commands.run("ls -la", timeout=10)
68
+ log_with_timestamp("Directory contents:")
69
+ for line in ls_result.stdout.split('\n')[:10]: # Show first 10 files
70
+ if line.strip():
71
+ log_with_timestamp(f" {line}")
72
+
73
+ # Check disk usage
74
+ du_result = sbx.commands.run("du -sh .", timeout=10)
75
+ log_with_timestamp(f"Directory size: {du_result.stdout.strip()}")
76
+
77
+ # Check for specific file types
78
+ find_result = sbx.commands.run("find . -type f -name '*.html' -o -name '*.js' -o -name '*.css' -o -name '*.json' | head -10", timeout=15)
79
+ if find_result.stdout.strip():
80
+ log_with_timestamp("Generated files found:")
81
+ for file in find_result.stdout.split('\n')[:10]:
82
+ if file.strip():
83
+ log_with_timestamp(f" 📄 {file.strip()}")
84
+
85
+ except Exception as e:
86
+ log_with_timestamp(f"File system monitoring error: {e}", "ERROR")
87
+
88
+ def monitor_system_resources(sbx):
89
+ """
90
+ Monitor sandbox system resources
91
+ """
92
+ log_with_timestamp("🔍 System resources check")
93
+
94
+ try:
95
+ # Memory usage
96
+ mem_result = sbx.commands.run("free -h", timeout=10)
97
+ log_with_timestamp("Memory usage:")
98
+ for line in mem_result.stdout.split('\n')[:3]:
99
+ if line.strip():
100
+ log_with_timestamp(f" {line}")
101
+
102
+ # CPU load
103
+ load_result = sbx.commands.run("uptime", timeout=10)
104
+ log_with_timestamp(f"System load: {load_result.stdout.strip()}")
105
+
106
+ # Process list (top 5 processes)
107
+ ps_result = sbx.commands.run("ps aux --sort=-%cpu | head -6", timeout=10)
108
+ log_with_timestamp("Top processes:")
109
+ lines = ps_result.stdout.split('\n')
110
+ for line in lines[:6]: # Header + top 5
111
+ if line.strip():
112
+ log_with_timestamp(f" {line}")
113
+
114
+ except Exception as e:
115
+ log_with_timestamp(f"System monitoring error: {e}", "ERROR")
116
+
117
+ def enhanced_sandbox_execution(prompt, components_to_install="", e2b_api_key=None, anthropic_api_key=None):
118
+ """
119
+ Enhanced sandbox execution with full monitoring
120
+ This would be called instead of the basic launcher when you have valid API keys
121
+ """
122
+
123
+ log_with_timestamp("🚀 Starting enhanced E2B sandbox with monitoring")
124
+ log_with_timestamp("=" * 60)
125
+
126
+ try:
127
+ from e2b import Sandbox
128
+ log_with_timestamp("✅ E2B SDK imported successfully")
129
+ except ImportError as e:
130
+ log_with_timestamp(f"❌ E2B import failed: {e}", "ERROR")
131
+ return False
132
+
133
+ if not e2b_api_key or not anthropic_api_key:
134
+ log_with_timestamp("❌ Missing API keys", "ERROR")
135
+ return False
136
+
137
+ try:
138
+ # Create sandbox with monitoring
139
+ log_with_timestamp("Creating E2B sandbox...")
140
+ sbx = Sandbox.create(
141
+ template="anthropic-claude-code",
142
+ api_key=e2b_api_key,
143
+ envs={'ANTHROPIC_API_KEY': anthropic_api_key},
144
+ timeout=600
145
+ )
146
+
147
+ log_with_timestamp(f"✅ Sandbox created: {sbx.sandbox_id}")
148
+ sbx.set_timeout(900)
149
+ log_with_timestamp("⏱️ Sandbox timeout extended to 15 minutes")
150
+
151
+ # Initial system check
152
+ monitor_system_resources(sbx)
153
+ monitor_file_system(sbx, "Initial file system state")
154
+
155
+ # Install components if specified
156
+ if components_to_install:
157
+ log_with_timestamp(f"📦 Installing components: {components_to_install}")
158
+ install_command = f"npx claude-code-templates@latest {components_to_install}"
159
+ monitor_sandbox_execution(sbx, install_command, timeout=120)
160
+ monitor_file_system(sbx, "After components installation")
161
+
162
+ # Verify Claude Code installation
163
+ log_with_timestamp("🔍 Verifying Claude Code installation")
164
+ claude_check = monitor_sandbox_execution(sbx, "which claude", timeout=10)
165
+ if claude_check.exit_code == 0:
166
+ version_check = monitor_sandbox_execution(sbx, "claude --version", timeout=10)
167
+ log_with_timestamp(f"Claude version: {version_check.stdout.strip()}")
168
+ else:
169
+ log_with_timestamp("❌ Claude Code not found in PATH", "ERROR")
170
+
171
+ # Execute main prompt with monitoring
172
+ log_with_timestamp("🤖 Executing Claude Code with monitoring")
173
+ claude_command = f"echo '{prompt}' | claude -p --dangerously-skip-permissions"
174
+
175
+ result = monitor_sandbox_execution(sbx, claude_command, timeout=600)
176
+
177
+ # Final file system check
178
+ monitor_file_system(sbx, "Final file system state")
179
+
180
+ # Display results
181
+ log_with_timestamp("=" * 60)
182
+ log_with_timestamp("🎯 CLAUDE CODE RESULTS")
183
+ log_with_timestamp("=" * 60)
184
+
185
+ if result.stdout:
186
+ print(result.stdout)
187
+
188
+ if result.stderr:
189
+ log_with_timestamp("⚠️ STDERR OUTPUT", "WARNING")
190
+ print(result.stderr)
191
+
192
+ log_with_timestamp("✅ Execution completed successfully")
193
+
194
+ # Cleanup
195
+ sbx.kill()
196
+ log_with_timestamp("🧹 Sandbox cleaned up")
197
+ return True
198
+
199
+ except Exception as e:
200
+ log_with_timestamp(f"❌ Execution failed: {e}", "ERROR")
201
+ return False
202
+
203
+ def main():
204
+ if len(sys.argv) < 2:
205
+ print("E2B Sandbox Monitor")
206
+ print("Usage: python e2b-monitor.py <prompt> [components] [e2b_key] [anthropic_key]")
207
+ print()
208
+ print("This tool provides enhanced monitoring and debugging for E2B sandbox operations.")
209
+ print("Use this when you have valid API keys and want detailed insight into sandbox execution.")
210
+ sys.exit(1)
211
+
212
+ prompt = sys.argv[1]
213
+ components = sys.argv[2] if len(sys.argv) > 2 else ""
214
+ e2b_key = sys.argv[3] if len(sys.argv) > 3 else os.getenv('E2B_API_KEY')
215
+ anthropic_key = sys.argv[4] if len(sys.argv) > 4 else os.getenv('ANTHROPIC_API_KEY')
216
+
217
+ log_with_timestamp("🎬 E2B Sandbox Monitor Starting")
218
+ log_with_timestamp("=" * 60)
219
+
220
+ success = enhanced_sandbox_execution(prompt, components, e2b_key, anthropic_key)
221
+
222
+ if success:
223
+ log_with_timestamp("🎉 Monitoring session completed successfully")
224
+ else:
225
+ log_with_timestamp("❌ Monitoring session failed")
226
+ sys.exit(1)
227
+
228
+ if __name__ == "__main__":
229
+ main()
@@ -0,0 +1 @@
1
+ e2b>=2.0.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.21.5",
3
+ "version": "1.21.7",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -86,6 +86,7 @@
86
86
  "files": [
87
87
  "bin/",
88
88
  "src/",
89
+ "components/sandbox/e2b/",
89
90
  "README.md"
90
91
  ],
91
92
  "devDependencies": {
package/src/index.js CHANGED
@@ -2392,32 +2392,67 @@ async function executeSandbox(options, targetDir) {
2392
2392
  const sandboxDir = path.join(targetDir, '.claude', 'sandbox');
2393
2393
  await fs.ensureDir(sandboxDir);
2394
2394
 
2395
- // Download E2B component files from new structure
2396
- const baseUrl = 'https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/sandbox/e2b';
2395
+ // Copy E2B component files from the installed package
2396
+ const componentsDir = path.join(__dirname, '..', 'components', 'sandbox', 'e2b');
2397
2397
 
2398
- // Download launcher script
2399
- const launcherResponse = await fetch(`${baseUrl}/e2b-launcher.py`);
2400
- if (!launcherResponse.ok) {
2401
- throw new Error(`Failed to download e2b-launcher.py: ${launcherResponse.status} ${launcherResponse.statusText}`);
2402
- }
2403
- const launcherContent = await launcherResponse.text();
2404
- await fs.writeFile(path.join(sandboxDir, 'e2b-launcher.py'), launcherContent, { mode: 0o755 });
2405
-
2406
- // Download requirements.txt
2407
- const requirementsResponse = await fetch(`${baseUrl}/requirements.txt`);
2408
- if (!requirementsResponse.ok) {
2409
- throw new Error(`Failed to download requirements.txt: ${requirementsResponse.status} ${requirementsResponse.statusText}`);
2410
- }
2411
- const requirementsContent = await requirementsResponse.text();
2412
- await fs.writeFile(path.join(sandboxDir, 'requirements.txt'), requirementsContent);
2413
-
2414
- // Download .env.example
2415
- const envExampleResponse = await fetch(`${baseUrl}/.env.example`);
2416
- if (!envExampleResponse.ok) {
2417
- throw new Error(`Failed to download .env.example: ${envExampleResponse.status} ${envExampleResponse.statusText}`);
2398
+ try {
2399
+ // Check if files exist locally (from npm package)
2400
+ if (await fs.pathExists(componentsDir)) {
2401
+ // Copy files from local package
2402
+ console.log(chalk.gray('📦 Using local E2B component files...'));
2403
+
2404
+ const launcherPath = path.join(componentsDir, 'e2b-launcher.py');
2405
+ const requirementsPath = path.join(componentsDir, 'requirements.txt');
2406
+ const envExamplePath = path.join(componentsDir, '.env.example');
2407
+
2408
+ if (await fs.pathExists(launcherPath)) {
2409
+ await fs.copyFile(launcherPath, path.join(sandboxDir, 'e2b-launcher.py'));
2410
+ await fs.chmod(path.join(sandboxDir, 'e2b-launcher.py'), 0o755);
2411
+ } else {
2412
+ throw new Error('e2b-launcher.py not found in package');
2413
+ }
2414
+
2415
+ if (await fs.pathExists(requirementsPath)) {
2416
+ await fs.copyFile(requirementsPath, path.join(sandboxDir, 'requirements.txt'));
2417
+ }
2418
+
2419
+ if (await fs.pathExists(envExamplePath)) {
2420
+ await fs.copyFile(envExamplePath, path.join(sandboxDir, '.env.example'));
2421
+ }
2422
+ } else {
2423
+ // Fallback to downloading from GitHub if not found locally
2424
+ console.log(chalk.gray('📥 Downloading E2B component files from GitHub...'));
2425
+
2426
+ const baseUrl = 'https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/sandbox/e2b';
2427
+
2428
+ // Download launcher script
2429
+ const launcherResponse = await fetch(`${baseUrl}/e2b-launcher.py`);
2430
+ if (!launcherResponse.ok) {
2431
+ throw new Error(`Failed to download e2b-launcher.py: ${launcherResponse.status} ${launcherResponse.statusText}`);
2432
+ }
2433
+ const launcherContent = await launcherResponse.text();
2434
+ await fs.writeFile(path.join(sandboxDir, 'e2b-launcher.py'), launcherContent, { mode: 0o755 });
2435
+
2436
+ // Download requirements.txt
2437
+ const requirementsResponse = await fetch(`${baseUrl}/requirements.txt`);
2438
+ if (!requirementsResponse.ok) {
2439
+ throw new Error(`Failed to download requirements.txt: ${requirementsResponse.status} ${requirementsResponse.statusText}`);
2440
+ }
2441
+ const requirementsContent = await requirementsResponse.text();
2442
+ await fs.writeFile(path.join(sandboxDir, 'requirements.txt'), requirementsContent);
2443
+
2444
+ // Download .env.example
2445
+ const envExampleResponse = await fetch(`${baseUrl}/.env.example`);
2446
+ if (!envExampleResponse.ok) {
2447
+ throw new Error(`Failed to download .env.example: ${envExampleResponse.status} ${envExampleResponse.statusText}`);
2448
+ }
2449
+ const envExampleContent = await envExampleResponse.text();
2450
+ await fs.writeFile(path.join(sandboxDir, '.env.example'), envExampleContent);
2451
+ }
2452
+ } catch (error) {
2453
+ spinner.fail(`Failed to install E2B component: ${error.message}`);
2454
+ throw error;
2418
2455
  }
2419
- const envExampleContent = await envExampleResponse.text();
2420
- await fs.writeFile(path.join(sandboxDir, '.env.example'), envExampleContent);
2421
2456
 
2422
2457
  spinner.succeed('E2B sandbox component installed successfully');
2423
2458