claude-code-templates 1.26.4 → 1.28.0
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.
- package/bin/create-claude-config.js +1 -0
- package/components/sandbox/docker/Dockerfile +38 -0
- package/components/sandbox/docker/README.md +453 -0
- package/components/sandbox/docker/docker-launcher.js +184 -0
- package/components/sandbox/docker/execute.js +251 -0
- package/components/sandbox/docker/package.json +26 -0
- package/package.json +2 -1
- package/src/index.js +294 -24
- package/src/skill-dashboard-web/index.html +326 -0
- package/src/skill-dashboard-web/script.js +445 -0
- package/src/skill-dashboard-web/styles.css +3469 -0
- package/src/skill-dashboard.js +441 -0
|
@@ -59,6 +59,7 @@ program
|
|
|
59
59
|
.option('--agents', 'launch Claude Code agents dashboard (opens directly to conversations)')
|
|
60
60
|
.option('--chats-mobile', 'launch mobile-first chats interface (AI-optimized for mobile devices)')
|
|
61
61
|
.option('--plugins', 'launch Plugin Dashboard to view marketplaces, installed plugins, and permissions')
|
|
62
|
+
.option('--skills', 'launch Skills Dashboard to view and explore installed Claude Code Skills')
|
|
62
63
|
.option('--tunnel', 'enable Cloudflare Tunnel for remote access (use with --analytics or --chats)')
|
|
63
64
|
.option('--verbose', 'enable verbose logging for debugging and development')
|
|
64
65
|
.option('--health-check, --health, --check, --verify', 'run comprehensive health check to verify Claude Code setup')
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
FROM node:22-alpine
|
|
3
|
+
|
|
4
|
+
# Install runtime dependencies
|
|
5
|
+
RUN apk --no-cache add \
|
|
6
|
+
git \
|
|
7
|
+
bash \
|
|
8
|
+
python3 \
|
|
9
|
+
py3-pip \
|
|
10
|
+
curl \
|
|
11
|
+
&& npm install -g @anthropic-ai/claude-agent-sdk
|
|
12
|
+
|
|
13
|
+
# Create non-root user for security
|
|
14
|
+
RUN adduser -u 10001 -D -s /bin/bash sandboxuser
|
|
15
|
+
|
|
16
|
+
# Set working directory
|
|
17
|
+
WORKDIR /app
|
|
18
|
+
|
|
19
|
+
# Create output directory
|
|
20
|
+
RUN mkdir -p /output && chown sandboxuser:sandboxuser /output
|
|
21
|
+
|
|
22
|
+
# Copy execution script
|
|
23
|
+
COPY execute.js /app/execute.js
|
|
24
|
+
COPY package.json /app/package.json
|
|
25
|
+
|
|
26
|
+
# Install dependencies
|
|
27
|
+
RUN npm install --production && \
|
|
28
|
+
chown -R sandboxuser:sandboxuser /app
|
|
29
|
+
|
|
30
|
+
# Switch to non-root user
|
|
31
|
+
USER sandboxuser
|
|
32
|
+
|
|
33
|
+
# Set environment
|
|
34
|
+
ENV HOME=/home/sandboxuser
|
|
35
|
+
ENV NODE_ENV=production
|
|
36
|
+
|
|
37
|
+
# Default command (overridden by launcher)
|
|
38
|
+
CMD ["node", "/app/execute.js"]
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# Docker Claude Code Sandbox
|
|
2
|
+
|
|
3
|
+
Execute Claude Code in isolated Docker containers with AI-powered code generation using the Claude Agent SDK.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Install Docker
|
|
8
|
+
|
|
9
|
+
Ensure Docker is installed and running on your system:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Check Docker installation
|
|
13
|
+
docker --version
|
|
14
|
+
|
|
15
|
+
# Verify Docker daemon is running
|
|
16
|
+
docker ps
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If Docker is not installed, visit: https://docs.docker.com/get-docker/
|
|
20
|
+
|
|
21
|
+
### 2. Configure API Key
|
|
22
|
+
|
|
23
|
+
Set your Anthropic API key:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Set as environment variable
|
|
27
|
+
export ANTHROPIC_API_KEY=sk-ant-your-api-key-here
|
|
28
|
+
|
|
29
|
+
# Or pass directly when using the CLI
|
|
30
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
31
|
+
--agent development/frontend-developer \
|
|
32
|
+
--prompt "Create a React component" \
|
|
33
|
+
--anthropic-api-key sk-ant-your-key
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. Run Your First Sandbox
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Basic execution
|
|
40
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
41
|
+
--prompt "Write a function to calculate factorial"
|
|
42
|
+
|
|
43
|
+
# With specific agent
|
|
44
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
45
|
+
--agent development/python-developer \
|
|
46
|
+
--prompt "Create a data validation script"
|
|
47
|
+
|
|
48
|
+
# With multiple components
|
|
49
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
50
|
+
--agent development/fullstack-developer \
|
|
51
|
+
--command development/setup-testing \
|
|
52
|
+
--prompt "Set up a complete testing environment"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
This sandbox combines two powerful technologies:
|
|
58
|
+
|
|
59
|
+
1. **Claude Agent SDK** - Provides programmatic access to Claude Code
|
|
60
|
+
2. **Docker** - Provides isolated container execution
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
User Prompt → Docker Launcher → Container Build → Execute Script → Claude Agent SDK → Output Files
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Components
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
docker/
|
|
70
|
+
├── docker-launcher.js # Node.js launcher that orchestrates Docker
|
|
71
|
+
├── Dockerfile # Container definition with Claude Agent SDK
|
|
72
|
+
├── execute.js # Script that runs inside container
|
|
73
|
+
├── package.json # Dependencies (Claude Agent SDK)
|
|
74
|
+
└── README.md # This file
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## How It Works
|
|
78
|
+
|
|
79
|
+
### 1. Launcher Phase (docker-launcher.js)
|
|
80
|
+
- Checks Docker installation and daemon status
|
|
81
|
+
- Builds container image if it doesn't exist
|
|
82
|
+
- Prepares environment variables and volume mounts
|
|
83
|
+
- Launches container with user prompt
|
|
84
|
+
|
|
85
|
+
### 2. Container Phase (execute.js)
|
|
86
|
+
- Installs requested components (agents, commands, MCPs, etc.)
|
|
87
|
+
- Executes Claude Agent SDK with the user's prompt
|
|
88
|
+
- Auto-allows all tool uses (no permission prompts)
|
|
89
|
+
- Captures output and generated files
|
|
90
|
+
- Copies results to mounted output directory
|
|
91
|
+
|
|
92
|
+
### 3. Output Phase
|
|
93
|
+
- Generated files are saved to `output/` directory
|
|
94
|
+
- Files preserve directory structure
|
|
95
|
+
- Accessible on host machine for inspection
|
|
96
|
+
|
|
97
|
+
## Usage Examples
|
|
98
|
+
|
|
99
|
+
### Simple Code Generation
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
103
|
+
--prompt "Create a REST API server with Express.js"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### With Specific Agent
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
110
|
+
--agent security/security-auditor \
|
|
111
|
+
--prompt "Audit this codebase for security vulnerabilities"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Multiple Components
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
118
|
+
--agent development/frontend-developer \
|
|
119
|
+
--command testing/setup-testing \
|
|
120
|
+
--setting performance/performance-optimization \
|
|
121
|
+
--prompt "Create a React app with testing setup"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Development Workflow
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# 1. Generate initial code
|
|
128
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
129
|
+
--agent development/fullstack-developer \
|
|
130
|
+
--prompt "Create a blog API with authentication"
|
|
131
|
+
|
|
132
|
+
# 2. Check output
|
|
133
|
+
ls -la output/
|
|
134
|
+
|
|
135
|
+
# 3. Iterate on generated code
|
|
136
|
+
npx claude-code-templates@latest --sandbox docker \
|
|
137
|
+
--prompt "Add pagination to the blog API"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
### Environment Variables
|
|
143
|
+
|
|
144
|
+
**Required:**
|
|
145
|
+
- `ANTHROPIC_API_KEY` - Your Anthropic API key
|
|
146
|
+
|
|
147
|
+
**Optional:**
|
|
148
|
+
- `DOCKER_BUILDKIT=1` - Enable BuildKit for faster builds
|
|
149
|
+
|
|
150
|
+
### Docker Image Details
|
|
151
|
+
|
|
152
|
+
The Docker image (`claude-sandbox`) includes:
|
|
153
|
+
|
|
154
|
+
- **Base**: Node.js 22 Alpine Linux (minimal, secure)
|
|
155
|
+
- **Runtime**: Git, Bash, Python3, Pip, Curl
|
|
156
|
+
- **Claude SDK**: `@anthropic-ai/claude-agent-sdk` installed globally
|
|
157
|
+
- **Security**: Runs as non-root user (UID 10001)
|
|
158
|
+
- **Working Directory**: `/app`
|
|
159
|
+
- **Output Directory**: `/output` (mounted as volume)
|
|
160
|
+
|
|
161
|
+
### Build Configuration
|
|
162
|
+
|
|
163
|
+
Edit `Dockerfile` to customize:
|
|
164
|
+
|
|
165
|
+
```dockerfile
|
|
166
|
+
# Add additional system dependencies
|
|
167
|
+
RUN apk --no-cache add postgresql-client redis
|
|
168
|
+
|
|
169
|
+
# Install additional global npm packages
|
|
170
|
+
RUN npm install -g typescript tsx
|
|
171
|
+
|
|
172
|
+
# Set custom environment variables
|
|
173
|
+
ENV CUSTOM_VAR=value
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Command Reference
|
|
177
|
+
|
|
178
|
+
### Build Image Manually
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
cd .claude/sandbox/docker
|
|
182
|
+
docker build -t claude-sandbox .
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Run Container Directly
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
docker run --rm \
|
|
189
|
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
|
190
|
+
-v $(pwd)/output:/output \
|
|
191
|
+
claude-sandbox \
|
|
192
|
+
node /app/execute.js "Your prompt here" ""
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Clean Up
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Remove built image
|
|
199
|
+
docker rmi claude-sandbox
|
|
200
|
+
|
|
201
|
+
# Remove all stopped containers
|
|
202
|
+
docker container prune
|
|
203
|
+
|
|
204
|
+
# Remove dangling images
|
|
205
|
+
docker image prune
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Troubleshooting
|
|
209
|
+
|
|
210
|
+
### Docker Not Found
|
|
211
|
+
|
|
212
|
+
**Error:** `Docker is not installed`
|
|
213
|
+
|
|
214
|
+
**Solution:**
|
|
215
|
+
```bash
|
|
216
|
+
# Install Docker from official site
|
|
217
|
+
# macOS: https://docs.docker.com/desktop/install/mac-install/
|
|
218
|
+
# Linux: https://docs.docker.com/engine/install/
|
|
219
|
+
# Windows: https://docs.docker.com/desktop/install/windows-install/
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Docker Daemon Not Running
|
|
223
|
+
|
|
224
|
+
**Error:** `Docker daemon is not running`
|
|
225
|
+
|
|
226
|
+
**Solution:**
|
|
227
|
+
```bash
|
|
228
|
+
# macOS/Windows: Start Docker Desktop application
|
|
229
|
+
# Linux: sudo systemctl start docker
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### API Key Not Set
|
|
233
|
+
|
|
234
|
+
**Error:** `ANTHROPIC_API_KEY environment variable is required`
|
|
235
|
+
|
|
236
|
+
**Solution:**
|
|
237
|
+
```bash
|
|
238
|
+
export ANTHROPIC_API_KEY=sk-ant-your-key-here
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Build Failures
|
|
242
|
+
|
|
243
|
+
**Error:** Failed to build Docker image
|
|
244
|
+
|
|
245
|
+
**Solution:**
|
|
246
|
+
```bash
|
|
247
|
+
# Check Docker logs
|
|
248
|
+
docker logs <container-id>
|
|
249
|
+
|
|
250
|
+
# Rebuild from scratch
|
|
251
|
+
docker build --no-cache -t claude-sandbox .
|
|
252
|
+
|
|
253
|
+
# Check disk space
|
|
254
|
+
docker system df
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Permission Issues
|
|
258
|
+
|
|
259
|
+
**Error:** Permission denied when accessing output files
|
|
260
|
+
|
|
261
|
+
**Solution:**
|
|
262
|
+
```bash
|
|
263
|
+
# Check output directory permissions
|
|
264
|
+
ls -la output/
|
|
265
|
+
|
|
266
|
+
# Fix permissions (if needed)
|
|
267
|
+
sudo chown -R $USER:$USER output/
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Container Execution Failures
|
|
271
|
+
|
|
272
|
+
**Error:** Container failed with code 1
|
|
273
|
+
|
|
274
|
+
**Solution:**
|
|
275
|
+
```bash
|
|
276
|
+
# Run container interactively for debugging
|
|
277
|
+
docker run -it --rm \
|
|
278
|
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
|
279
|
+
claude-sandbox \
|
|
280
|
+
/bin/bash
|
|
281
|
+
|
|
282
|
+
# Check container logs
|
|
283
|
+
docker logs <container-id>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Performance Tips
|
|
287
|
+
|
|
288
|
+
1. **Image Caching**: First build takes longer, subsequent builds are fast
|
|
289
|
+
2. **Volume Mounts**: Use volumes instead of COPY for faster iteration
|
|
290
|
+
3. **Layer Optimization**: Group RUN commands to reduce image layers
|
|
291
|
+
4. **BuildKit**: Enable for parallel builds (`DOCKER_BUILDKIT=1`)
|
|
292
|
+
5. **Prune Regularly**: Clean up unused images and containers
|
|
293
|
+
|
|
294
|
+
## Security
|
|
295
|
+
|
|
296
|
+
- **Isolation**: Containers are isolated from host system
|
|
297
|
+
- **Non-root User**: Execution runs as `sandboxuser` (UID 10001)
|
|
298
|
+
- **No Network**: Container has no internet access (except during build)
|
|
299
|
+
- **Read-only**: Host filesystem is mounted read-only
|
|
300
|
+
- **Resource Limits**: Docker enforces CPU and memory limits
|
|
301
|
+
- **Secret Management**: API keys are passed as environment variables (not stored in image)
|
|
302
|
+
|
|
303
|
+
## Cost Estimation
|
|
304
|
+
|
|
305
|
+
**Docker:**
|
|
306
|
+
- Free and open-source
|
|
307
|
+
- No cloud costs (runs locally)
|
|
308
|
+
- Resource usage: ~500MB disk space, ~512MB RAM during execution
|
|
309
|
+
|
|
310
|
+
**Anthropic API:**
|
|
311
|
+
- Claude Sonnet 4.5: ~$3 per million input tokens
|
|
312
|
+
- Average request: ~200 tokens = $0.0006 per request
|
|
313
|
+
|
|
314
|
+
**Example costs for 100 executions:**
|
|
315
|
+
- Docker: $0 (local execution)
|
|
316
|
+
- Anthropic: ~$0.06 (avg 200 tokens/request)
|
|
317
|
+
- **Total: ~$0.06**
|
|
318
|
+
|
|
319
|
+
## Comparison with Other Providers
|
|
320
|
+
|
|
321
|
+
| Feature | Docker | E2B | Cloudflare |
|
|
322
|
+
|---------|--------|-----|------------|
|
|
323
|
+
| Execution Location | 🏠 Local | ☁️ Cloud | 🌍 Edge |
|
|
324
|
+
| Setup Complexity | Medium | Easy | Easy |
|
|
325
|
+
| Internet Required | Setup only | Yes | Yes |
|
|
326
|
+
| Cost | Free | Paid | Paid |
|
|
327
|
+
| Privacy | Full control | Third-party | Third-party |
|
|
328
|
+
| Offline Support | Yes | No | No |
|
|
329
|
+
| Best For | Local dev, privacy, offline | Full stack projects | Serverless, global APIs |
|
|
330
|
+
|
|
331
|
+
## Development
|
|
332
|
+
|
|
333
|
+
### Project Structure
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
docker/
|
|
337
|
+
├── docker-launcher.js # Orchestrates container lifecycle
|
|
338
|
+
│ ├── checkDockerInstalled()
|
|
339
|
+
│ ├── checkDockerRunning()
|
|
340
|
+
│ ├── buildDockerImage()
|
|
341
|
+
│ └── runDockerContainer()
|
|
342
|
+
├── Dockerfile # Container definition
|
|
343
|
+
│ ├── Base image (Node 22 Alpine)
|
|
344
|
+
│ ├── System dependencies
|
|
345
|
+
│ ├── Claude Agent SDK
|
|
346
|
+
│ └── Security (non-root user)
|
|
347
|
+
├── execute.js # Execution script (runs in container)
|
|
348
|
+
│ ├── installComponents()
|
|
349
|
+
│ ├── executeQuery()
|
|
350
|
+
│ └── copyGeneratedFiles()
|
|
351
|
+
├── package.json # NPM dependencies
|
|
352
|
+
└── README.md # Documentation
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Scripts
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# Build image
|
|
359
|
+
npm run build
|
|
360
|
+
|
|
361
|
+
# Clean image
|
|
362
|
+
npm run clean
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Extending the Image
|
|
366
|
+
|
|
367
|
+
Add custom tools to the Dockerfile:
|
|
368
|
+
|
|
369
|
+
```dockerfile
|
|
370
|
+
# Install Python packages
|
|
371
|
+
RUN pip install --no-cache-dir pandas numpy matplotlib
|
|
372
|
+
|
|
373
|
+
# Install Node.js packages globally
|
|
374
|
+
RUN npm install -g typescript eslint prettier
|
|
375
|
+
|
|
376
|
+
# Add custom scripts
|
|
377
|
+
COPY scripts/ /app/scripts/
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Advanced Usage
|
|
381
|
+
|
|
382
|
+
### Custom Dockerfile
|
|
383
|
+
|
|
384
|
+
Create a custom Dockerfile for specialized environments:
|
|
385
|
+
|
|
386
|
+
```dockerfile
|
|
387
|
+
FROM node:22-alpine
|
|
388
|
+
|
|
389
|
+
# Install database clients
|
|
390
|
+
RUN apk add --no-cache postgresql-client mysql-client
|
|
391
|
+
|
|
392
|
+
# Install development tools
|
|
393
|
+
RUN apk add --no-cache vim nano tmux
|
|
394
|
+
|
|
395
|
+
# Install Claude Agent SDK
|
|
396
|
+
RUN npm install -g @anthropic-ai/claude-agent-sdk
|
|
397
|
+
|
|
398
|
+
# ... rest of configuration
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Multi-stage Builds
|
|
402
|
+
|
|
403
|
+
Optimize image size with multi-stage builds:
|
|
404
|
+
|
|
405
|
+
```dockerfile
|
|
406
|
+
# Build stage
|
|
407
|
+
FROM node:22-alpine AS builder
|
|
408
|
+
WORKDIR /build
|
|
409
|
+
COPY package*.json ./
|
|
410
|
+
RUN npm ci --only=production
|
|
411
|
+
|
|
412
|
+
# Runtime stage
|
|
413
|
+
FROM node:22-alpine
|
|
414
|
+
COPY --from=builder /build/node_modules ./node_modules
|
|
415
|
+
# ... rest of configuration
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Persistent Storage
|
|
419
|
+
|
|
420
|
+
Mount additional volumes for persistent data:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
docker run --rm \
|
|
424
|
+
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
|
|
425
|
+
-v $(pwd)/output:/output \
|
|
426
|
+
-v $(pwd)/cache:/cache \
|
|
427
|
+
claude-sandbox
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Resources
|
|
431
|
+
|
|
432
|
+
- [Docker Documentation](https://docs.docker.com/)
|
|
433
|
+
- [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk)
|
|
434
|
+
- [Anthropic API Documentation](https://docs.anthropic.com/)
|
|
435
|
+
- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/)
|
|
436
|
+
- [Container Security](https://docs.docker.com/engine/security/)
|
|
437
|
+
|
|
438
|
+
## License
|
|
439
|
+
|
|
440
|
+
MIT License - See LICENSE file for details
|
|
441
|
+
|
|
442
|
+
## Support
|
|
443
|
+
|
|
444
|
+
For issues and questions:
|
|
445
|
+
1. Check Docker installation: `docker --version && docker ps`
|
|
446
|
+
2. Verify API key: `echo $ANTHROPIC_API_KEY`
|
|
447
|
+
3. Check container logs: `docker logs <container-id>`
|
|
448
|
+
4. Review output directory: `ls -la output/`
|
|
449
|
+
5. Open an issue on GitHub
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
Built with ❤️ using Docker, Node.js, and Claude Agent SDK
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Docker Sandbox Launcher
|
|
5
|
+
* Orchestrates Docker container execution for Claude Code
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { spawn, execSync } from 'child_process';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Parse command line arguments
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const prompt = args[0] || 'Hello, Claude!';
|
|
19
|
+
const componentsToInstall = args[1] || '';
|
|
20
|
+
const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
|
|
21
|
+
|
|
22
|
+
// Validate API key
|
|
23
|
+
if (!anthropicApiKey) {
|
|
24
|
+
console.error('❌ Error: ANTHROPIC_API_KEY environment variable is required');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log('🐳 Docker Sandbox Launcher');
|
|
29
|
+
console.log('═══════════════════════════════════════\n');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if Docker is installed
|
|
33
|
+
*/
|
|
34
|
+
function checkDockerInstalled() {
|
|
35
|
+
try {
|
|
36
|
+
execSync('docker --version', { stdio: 'pipe' });
|
|
37
|
+
return true;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('❌ Error: Docker is not installed');
|
|
40
|
+
console.error(' Please install Docker: https://docs.docker.com/get-docker/\n');
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if Docker daemon is running
|
|
47
|
+
*/
|
|
48
|
+
function checkDockerRunning() {
|
|
49
|
+
try {
|
|
50
|
+
execSync('docker ps', { stdio: 'pipe' });
|
|
51
|
+
return true;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('❌ Error: Docker daemon is not running');
|
|
54
|
+
console.error(' Please start Docker and try again\n');
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Build Docker image if it doesn't exist
|
|
61
|
+
*/
|
|
62
|
+
async function buildDockerImage() {
|
|
63
|
+
console.log('🔨 Checking Docker image...');
|
|
64
|
+
|
|
65
|
+
// Check if image exists
|
|
66
|
+
try {
|
|
67
|
+
execSync('docker image inspect claude-sandbox', { stdio: 'pipe' });
|
|
68
|
+
console.log(' ✅ Image already exists\n');
|
|
69
|
+
return true;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// Image doesn't exist, build it
|
|
72
|
+
console.log(' 📦 Building Docker image (this may take a few minutes)...\n');
|
|
73
|
+
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
const build = spawn('docker', [
|
|
76
|
+
'build',
|
|
77
|
+
'-t', 'claude-sandbox',
|
|
78
|
+
'.'
|
|
79
|
+
], {
|
|
80
|
+
cwd: __dirname,
|
|
81
|
+
stdio: 'inherit'
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
build.on('close', (code) => {
|
|
85
|
+
if (code === 0) {
|
|
86
|
+
console.log('\n✅ Docker image built successfully\n');
|
|
87
|
+
resolve(true);
|
|
88
|
+
} else {
|
|
89
|
+
console.error('\n❌ Failed to build Docker image');
|
|
90
|
+
resolve(false);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
build.on('error', (error) => {
|
|
95
|
+
console.error('❌ Build error:', error.message);
|
|
96
|
+
resolve(false);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Run Docker container
|
|
104
|
+
*/
|
|
105
|
+
async function runDockerContainer() {
|
|
106
|
+
console.log('🚀 Starting Docker container...\n');
|
|
107
|
+
|
|
108
|
+
// Create output directory
|
|
109
|
+
const outputDir = path.join(process.cwd(), 'output');
|
|
110
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
111
|
+
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
const dockerArgs = [
|
|
114
|
+
'run',
|
|
115
|
+
'--rm',
|
|
116
|
+
'-e', `ANTHROPIC_API_KEY=${anthropicApiKey}`,
|
|
117
|
+
'-v', `${outputDir}:/output`,
|
|
118
|
+
'claude-sandbox',
|
|
119
|
+
'node', '/app/execute.js',
|
|
120
|
+
prompt,
|
|
121
|
+
componentsToInstall
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
const container = spawn('docker', dockerArgs, {
|
|
125
|
+
stdio: 'inherit'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
container.on('close', (code) => {
|
|
129
|
+
if (code === 0) {
|
|
130
|
+
console.log('\n✅ Docker container completed successfully');
|
|
131
|
+
|
|
132
|
+
// Show output directory
|
|
133
|
+
console.log(`\n📂 Output files saved to: ${outputDir}`);
|
|
134
|
+
resolve(true);
|
|
135
|
+
} else {
|
|
136
|
+
console.error('\n❌ Docker container failed with code:', code);
|
|
137
|
+
resolve(false);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
container.on('error', (error) => {
|
|
142
|
+
console.error('❌ Container error:', error.message);
|
|
143
|
+
resolve(false);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Main execution flow
|
|
150
|
+
*/
|
|
151
|
+
async function main() {
|
|
152
|
+
try {
|
|
153
|
+
// Step 1: Check Docker installation
|
|
154
|
+
if (!checkDockerInstalled()) {
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Step 2: Check Docker daemon
|
|
159
|
+
if (!checkDockerRunning()) {
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Step 3: Build Docker image
|
|
164
|
+
const buildSuccess = await buildDockerImage();
|
|
165
|
+
if (!buildSuccess) {
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Step 4: Run container
|
|
170
|
+
const runSuccess = await runDockerContainer();
|
|
171
|
+
if (!runSuccess) {
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log('\n🎉 Docker sandbox execution completed!');
|
|
176
|
+
process.exit(0);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error('❌ Fatal error:', error.message);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Run main function
|
|
184
|
+
main();
|