Skip to content

Commit 6c54d07

Browse files
Add rules & mcp config for claude (#149)
1 parent c1f057e commit 6c54d07

File tree

5 files changed

+358
-132
lines changed

5 files changed

+358
-132
lines changed

.mcp.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"mcpServers": {
3+
"cloudflare-docs": {
4+
"type": "http",
5+
"url": "https://docs.mcp.cloudflare.com/mcp"
6+
},
7+
"exa": {
8+
"type": "http",
9+
"url": "https://mcp.exa.ai/mcp",
10+
"headers": {
11+
"Remove-Me": "Disable web_search_exa tool if you're just coding. To 100% call exa-code, say 'use exa-code'."
12+
}
13+
}
14+
}
15+
}

CLAUDE.md

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Documentation Resources
6+
7+
**Always consult the Cloudflare Docs MCP when working on this repository.** The MCP provides comprehensive documentation about:
8+
- API usage patterns and examples
9+
- Architecture concepts and best practices
10+
- Configuration reference (wrangler, Dockerfile)
11+
- Troubleshooting guides
12+
- Production deployment requirements
13+
14+
Use the MCP tools (e.g., `mcp__cloudflare-docs__search_cloudflare_documentation`) to search for specific topics before making changes.
15+
16+
**Exa MCP is available for code search.** Use the exa-code tool when you need real-world code examples or patterns from GitHub repositories, documentation, or Stack Overflow to inform your implementation decisions and avoid hallucinations.
17+
18+
**Always use the `gh` CLI for GitHub interactions.** When you need to access GitHub issues, PRs, repository information, or any GitHub-related data, use the gh CLI tool (e.g., `gh issue view`, `gh pr view`, `gh repo view`) instead of trying to fetch GitHub URLs directly. The CLI provides structured, reliable output and better access to GitHub data.
19+
20+
## Project Overview
21+
22+
The Cloudflare Sandbox SDK enables secure, isolated code execution in containers running on Cloudflare. The SDK allows Workers to execute arbitrary commands, manage files, run background processes, and expose services.
23+
24+
**Status**: Open Beta - API is stable but may evolve based on feedback. Safe for production use.
25+
26+
## Architecture
27+
28+
### Three-Layer Architecture
29+
30+
1. **`@cloudflare/sandbox` (packages/sandbox/)** - Public SDK exported to npm
31+
- `Sandbox` class: Durable Object that manages the container lifecycle
32+
- Client architecture: Modular HTTP clients for different capabilities (CommandClient, FileClient, ProcessClient, etc.)
33+
- `CodeInterpreter`: High-level API for running Python/JavaScript with structured outputs
34+
- `proxyToSandbox()`: Request handler for preview URL routing
35+
36+
2. **`@repo/shared` (packages/shared/)** - Shared types and error system
37+
- Type definitions shared between SDK and container runtime
38+
- Centralized error handling and logging utilities
39+
- Not published to npm (internal workspace package)
40+
41+
3. **`@repo/sandbox-container` (packages/sandbox-container/)** - Container runtime
42+
- Bun-based HTTP server running inside Docker containers
43+
- Dependency injection container (`core/container.ts`)
44+
- Route handlers for command execution, file operations, process management
45+
- Not published to npm (bundled into Docker image)
46+
47+
### Key Flow
48+
49+
Worker → Sandbox DO → Container HTTP API (port 3000) → Bun runtime → Shell commands/File system
50+
51+
## Development Commands
52+
53+
### Building
54+
55+
```bash
56+
npm run build # Build all packages (uses turbo)
57+
npm run build:clean # Force rebuild without cache
58+
```
59+
60+
### Testing
61+
62+
```bash
63+
# Unit tests (runs in Workers runtime with vitest-pool-workers)
64+
npm test
65+
66+
# E2E tests (requires Docker, runs sequentially due to container provisioning)
67+
npm run test:e2e
68+
69+
# Run a single E2E test file
70+
npm run test:e2e -- -- tests/e2e/process-lifecycle-workflow.test.ts
71+
72+
# Run a specific test within a file
73+
npm run test:e2e -- -- tests/e2e/git-clone-workflow.test.ts -t 'test name'
74+
```
75+
76+
**Important**: E2E tests (`tests/e2e/`) run sequentially (not in parallel) to avoid container resource contention. Each test spawns its own wrangler dev instance.
77+
78+
### Code Quality
79+
80+
```bash
81+
npm run check # Run Biome linter + typecheck
82+
npm run fix # Auto-fix linting issues + typecheck
83+
npm run typecheck # TypeScript type checking only
84+
```
85+
86+
### Docker
87+
88+
Docker builds are typically **automated via CI**, but you can build locally for testing:
89+
90+
```bash
91+
npm run docker:rebuild # Rebuild container image locally (includes clean build + Docker)
92+
```
93+
94+
**Note:** Docker images are automatically built and published by CI (`release.yml`):
95+
- Beta images on every main commit
96+
- Stable images when "Version Packages" PR is merged
97+
- Multi-arch builds (amd64, arm64) handled by CI
98+
99+
**Critical:** Docker image version MUST match npm package version (`@cloudflare/[email protected]``cloudflare/sandbox:0.4.7`). This is enforced via `ARG SANDBOX_VERSION` in Dockerfile.
100+
101+
### Development Server
102+
103+
From an example directory (e.g., `examples/minimal/`):
104+
```bash
105+
npm run dev # Start wrangler dev server (builds Docker on first run)
106+
```
107+
108+
**Local development gotcha**: When testing port exposure with `wrangler dev`, the Dockerfile must include `EXPOSE` directives for those ports. Without `EXPOSE`, you'll see "Connection refused: container port not found". This is only required for local dev - production automatically makes all ports accessible.
109+
110+
## Development Workflow
111+
112+
**Main branch is protected.** All changes must go through pull requests. The CI pipeline runs comprehensive tests on every PR - these MUST pass before merging.
113+
114+
### Pull Request Process
115+
116+
1. Make your changes
117+
118+
2. **Run code quality checks after any meaningful change:**
119+
```bash
120+
npm run check # Runs Biome linter + typecheck
121+
```
122+
This catches type errors that often expose real issues with code changes. Fix any issues before proceeding.
123+
124+
3. **Run unit tests to verify your changes:**
125+
```bash
126+
npm test
127+
```
128+
129+
4. Create a changeset if your change affects published packages:
130+
131+
Create a new file in `.changeset/` directory (e.g., `.changeset/your-feature-name.md`):
132+
```markdown
133+
---
134+
"@cloudflare/sandbox": patch
135+
---
136+
137+
Brief description of your change
138+
```
139+
140+
Use `patch` for bug fixes, `minor` for new features, `major` for breaking changes.
141+
142+
5. Push your branch and create a PR
143+
144+
6. **CI runs automatically:**
145+
- **Unit tests** for `@cloudflare/sandbox` and `@repo/sandbox-container`
146+
- **E2E tests** that deploy a real test worker to Cloudflare and run integration tests
147+
- Both test suites MUST pass
148+
149+
7. After approval and passing tests, merge to main
150+
151+
8. **Automated release** (no manual intervention):
152+
- Changesets action creates a "Version Packages" PR when changesets exist
153+
- Merging that PR triggers automated npm + Docker Hub publishing
154+
- Beta releases published on every main commit
155+
- Stable releases published when changesets are merged
156+
157+
## Testing Architecture
158+
159+
**Tests are critical** - they verify functionality at multiple levels and run on every PR.
160+
161+
**Development practice:** After making any meaningful code change:
162+
1. Run `npm run check` to catch type errors (these often expose real issues)
163+
2. Run `npm test` to verify unit tests pass
164+
3. Run E2E tests if touching core functionality
165+
166+
### Unit Tests
167+
168+
Run these frequently during development:
169+
170+
```bash
171+
# All unit tests
172+
npm test
173+
174+
# Specific package
175+
npm test -w @cloudflare/sandbox # SDK tests (Workers runtime)
176+
npm test -w @repo/sandbox-container # Container runtime tests (Bun)
177+
```
178+
179+
**Architecture:**
180+
- **SDK tests** (`packages/sandbox/tests/`) run in Workers runtime via `@cloudflare/vitest-pool-workers`
181+
- **Container tests** (`packages/sandbox-container/tests/`) run in Bun runtime
182+
- Mock container for isolated testing (SDK), no Docker required
183+
- Fast feedback loop for development
184+
185+
**Known issue:** Sandbox unit tests may hang on exit due to vitest-pool-workers workerd shutdown issue. This is cosmetic - tests still pass/fail correctly.
186+
187+
### E2E Tests
188+
189+
Run before creating PRs to verify end-to-end functionality:
190+
191+
```bash
192+
# All E2E tests (requires Docker)
193+
npm run test:e2e
194+
195+
# Single test file
196+
npm run test:e2e -- -- tests/e2e/process-lifecycle-workflow.test.ts
197+
198+
# Single test within a file
199+
npm run test:e2e -- -- tests/e2e/git-clone-workflow.test.ts -t 'should handle cloning to default directory'
200+
```
201+
202+
**Architecture:**
203+
- Tests in `tests/e2e/` run against real Cloudflare Workers + Docker containers
204+
- **In CI**: Tests deploy to actual Cloudflare infrastructure and run against deployed workers
205+
- **Locally**: Each test file spawns its own `wrangler dev` instance
206+
- Config: `vitest.e2e.config.ts` (root level)
207+
- Sequential execution (`singleFork: true`) to prevent container resource contention
208+
- Longer timeouts (2min per test) for container operations
209+
210+
**CI behavior:** E2E tests in CI (`pullrequest.yml`):
211+
1. Build Docker image locally (`npm run docker:local`)
212+
2. Deploy test worker to Cloudflare with unique name (pr-XXX)
213+
3. Run E2E tests against deployed worker URL
214+
4. Cleanup test deployment after tests complete
215+
216+
## Client Architecture Pattern
217+
218+
The SDK uses a modular client pattern in `packages/sandbox/src/clients/`:
219+
220+
- **BaseClient**: Abstract HTTP client with request/response handling
221+
- **SandboxClient**: Aggregates all specialized clients
222+
- **Specialized clients**: CommandClient, FileClient, ProcessClient, PortClient, GitClient, UtilityClient, InterpreterClient
223+
224+
Each client handles a specific domain and makes HTTP requests to the container's API.
225+
226+
## Container Runtime Architecture
227+
228+
The container runtime (`packages/sandbox-container/src/`) uses:
229+
230+
- **Dependency Injection**: `core/container.ts` manages service lifecycle
231+
- **Router**: Simple HTTP router with middleware support
232+
- **Handlers**: Route handlers in `handlers/` directory
233+
- **Services**: Business logic in `services/` (CommandService, FileService, ProcessService, etc.)
234+
- **Managers**: Stateful managers in `managers/` (ProcessManager, PortManager)
235+
236+
Entry point: `packages/sandbox-container/src/index.ts` starts Bun HTTP server on port 3000.
237+
238+
## Monorepo Structure
239+
240+
Uses npm workspaces + Turbo:
241+
- `packages/sandbox`: Main SDK package
242+
- `packages/shared`: Shared types
243+
- `packages/sandbox-container`: Container runtime
244+
- `examples/`: Working example projects
245+
- `tooling/`: Shared TypeScript configs
246+
247+
Turbo handles task orchestration (`turbo.json`) with dependency-aware builds.
248+
249+
## Coding Standards
250+
251+
### TypeScript
252+
253+
**Never use the `any` type** unless absolutely necessary (which should be a final resort):
254+
- First, look for existing types that can be reused appropriately
255+
- If no suitable type exists, define a proper type in the right location:
256+
- Shared types → `packages/shared/src/types.ts` or relevant subdirectory
257+
- SDK-specific types → `packages/sandbox/src/clients/types.ts` or appropriate client file
258+
- Container-specific types → `packages/sandbox-container/src/` with appropriate naming
259+
- Use the newly defined type everywhere appropriate for consistency
260+
- This ensures type safety and catches errors at compile time rather than runtime
261+
262+
### Git Commits
263+
264+
**Follow the 7 rules for great commit messages** (from https://cbea.ms/git-commit/):
265+
266+
1. **Separate subject from body with a blank line**
267+
2. **Limit the subject line to 50 characters**
268+
3. **Capitalize the subject line**
269+
4. **Do not end the subject line with a period**
270+
5. **Use the imperative mood in the subject line** (e.g., "Add feature" not "Added feature")
271+
6. **Wrap the body at 72 characters**
272+
7. **Use the body to explain what and why vs. how**
273+
274+
**Be concise, not verbose.** Every word should add value. Avoid unnecessary details about implementation mechanics - focus on what changed and why it matters.
275+
276+
Example:
277+
```
278+
Add session isolation for concurrent executions
279+
280+
Previously, multiple concurrent exec() calls would interfere with each
281+
other's working directories and environment variables. This adds proper
282+
session management to isolate execution contexts.
283+
284+
The SessionManager tracks active sessions and ensures cleanup when
285+
processes complete. This is critical for multi-tenant scenarios where
286+
different users share the same sandbox instance.
287+
```
288+
289+
## Important Patterns
290+
291+
### Error Handling
292+
- Custom error classes in `packages/shared/src/errors/`
293+
- Errors flow from container → Sandbox DO → Worker
294+
- Use `ErrorCode` enum for consistent error types
295+
296+
### Logging
297+
- Centralized logger from `@repo/shared`
298+
- Structured logging with component context
299+
- Configurable via `SANDBOX_LOG_LEVEL` and `SANDBOX_LOG_FORMAT` env vars
300+
301+
### Session Management
302+
- Sessions isolate execution contexts (working directory, env vars, etc.)
303+
- Default session created automatically
304+
- Multiple sessions per sandbox supported
305+
306+
### Port Management
307+
- Expose internal services via preview URLs
308+
- Token-based authentication for exposed ports
309+
- Automatic cleanup on sandbox sleep
310+
- **Production requirement**: Preview URLs require custom domain with wildcard DNS (*.yourdomain.com)
311+
- `.workers.dev` domains do NOT support the subdomain patterns needed for preview URLs
312+
- See Cloudflare docs for "Deploy to Production" guide when ready to expose services
313+
314+
## Version Management & Releases
315+
316+
**Releases are fully automated** via GitHub Actions (`.github/workflows/release.yml`) and changesets (`.changeset/`):
317+
318+
- **Changesets**: Create a `.changeset/your-feature-name.md` file to document changes affecting published packages (see PR process above)
319+
- **Beta releases**: Published automatically on every push to main (`@beta` tag on npm)
320+
- **Stable releases**: When changesets exist, the "Version Packages" PR is auto-created. Merging it triggers:
321+
1. Version bump in `package.json`
322+
2. Docker image build and push to Docker Hub (multi-arch: amd64, arm64)
323+
3. npm package publish with updated version
324+
- **Version synchronization**: Docker image version always matches npm package version (enforced via `ARG SANDBOX_VERSION` in Dockerfile)
325+
326+
**SDK version tracked in**: `packages/sandbox/src/version.ts`
327+
328+
## Container Base Image
329+
330+
The container runtime uses Ubuntu 22.04 with:
331+
- Python 3.11 (with matplotlib, numpy, pandas, ipython)
332+
- Node.js 20 LTS
333+
- Bun 1.x runtime (powers the container HTTP server)
334+
- Git, curl, wget, jq, and other common utilities
335+
336+
When modifying the base image (`packages/sandbox/Dockerfile`), remember:
337+
- Keep images lean - every MB affects cold start time
338+
- Pin versions for reproducibility
339+
- Clean up package manager caches to reduce image size

0 commit comments

Comments
 (0)