mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-06 12:37:37 +00:00
config(git,claude,ssh): templated gitconfig; claude settings/commands/hooks/skills; ssh config
gitconfig: name/email from chezmoi data, gh credential helper by PATH lookup (portable to darwin). claude: no credentials, history, projects, sessions, or plugin caches. ssh config as private_ (0600). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3c691e8dc5
commit
20891f3910
476 files changed
+59086
-7
No files matched your search
@@ -0,0 +1,177 @@
|
||||
---
|
||||
name: sandbox-sdk
|
||||
description: Build sandboxed applications for secure code execution. Load when building AI code execution, code interpreters, CI/CD systems, interactive dev environments, or executing untrusted code. Covers Sandbox SDK lifecycle, commands, files, code interpreter, and preview URLs. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.
|
||||
---
|
||||
|
||||
# Cloudflare Sandbox SDK
|
||||
|
||||
Build secure, isolated code execution environments on Cloudflare Workers.
|
||||
|
||||
## FIRST: Verify Installation
|
||||
|
||||
```bash
|
||||
npm install @cloudflare/sandbox
|
||||
docker info # Must succeed - Docker required for local dev
|
||||
```
|
||||
|
||||
## Retrieval Sources
|
||||
|
||||
Your knowledge of the Sandbox SDK may be outdated. **Prefer retrieval over pre-training** for any Sandbox SDK task.
|
||||
|
||||
| Resource | URL |
|
||||
|----------|-----|
|
||||
| Docs | https://developers.cloudflare.com/sandbox/ |
|
||||
| API Reference | https://developers.cloudflare.com/sandbox/api/ |
|
||||
| Examples | https://github.com/cloudflare/sandbox-sdk/tree/main/examples |
|
||||
| Get Started | https://developers.cloudflare.com/sandbox/get-started/ |
|
||||
|
||||
When implementing features, fetch the relevant doc page or example first.
|
||||
|
||||
## Required Configuration
|
||||
|
||||
**wrangler.jsonc** (exact - do not modify structure):
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"containers": [{
|
||||
"class_name": "Sandbox",
|
||||
"image": "./Dockerfile",
|
||||
"instance_type": "lite",
|
||||
"max_instances": 1
|
||||
}],
|
||||
"durable_objects": {
|
||||
"bindings": [{ "class_name": "Sandbox", "name": "Sandbox" }]
|
||||
},
|
||||
"migrations": [{ "new_sqlite_classes": ["Sandbox"], "tag": "v1" }]
|
||||
}
|
||||
```
|
||||
|
||||
**Worker entry** - must re-export Sandbox class:
|
||||
|
||||
```typescript
|
||||
import { getSandbox } from '@cloudflare/sandbox';
|
||||
export { Sandbox } from '@cloudflare/sandbox'; // Required export
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Method |
|
||||
|------|--------|
|
||||
| Get sandbox | `getSandbox(env.Sandbox, 'user-123')` |
|
||||
| Run command | `await sandbox.exec('python script.py')` |
|
||||
| Run code (interpreter) | `await sandbox.runCode(code, { language: 'python' })` |
|
||||
| Write file | `await sandbox.writeFile('/workspace/app.py', content)` |
|
||||
| Read file | `await sandbox.readFile('/workspace/app.py')` |
|
||||
| Create directory | `await sandbox.mkdir('/workspace/src', { recursive: true })` |
|
||||
| List files | `await sandbox.listFiles('/workspace')` |
|
||||
| Expose port | `await sandbox.exposePort(8080)` |
|
||||
| Destroy | `await sandbox.destroy()` |
|
||||
|
||||
## Core Patterns
|
||||
|
||||
### Execute Commands
|
||||
|
||||
```typescript
|
||||
const sandbox = getSandbox(env.Sandbox, 'user-123');
|
||||
const result = await sandbox.exec('python --version');
|
||||
// result: { stdout, stderr, exitCode, success }
|
||||
```
|
||||
|
||||
### Code Interpreter (Recommended for AI)
|
||||
|
||||
Use `runCode()` for executing LLM-generated code with rich outputs:
|
||||
|
||||
```typescript
|
||||
const ctx = await sandbox.createCodeContext({ language: 'python' });
|
||||
|
||||
await sandbox.runCode('import pandas as pd; data = [1,2,3]', { context: ctx });
|
||||
const result = await sandbox.runCode('sum(data)', { context: ctx });
|
||||
// result.results[0].text = "6"
|
||||
```
|
||||
|
||||
**Languages**: `python`, `javascript`, `typescript`
|
||||
|
||||
State persists within context. Create explicit contexts for production.
|
||||
|
||||
### File Operations
|
||||
|
||||
```typescript
|
||||
await sandbox.mkdir('/workspace/project', { recursive: true });
|
||||
await sandbox.writeFile('/workspace/project/main.py', code);
|
||||
const file = await sandbox.readFile('/workspace/project/main.py');
|
||||
const files = await sandbox.listFiles('/workspace/project');
|
||||
```
|
||||
|
||||
## When to Use What
|
||||
|
||||
| Need | Use | Why |
|
||||
|------|-----|-----|
|
||||
| Shell commands, scripts | `exec()` | Direct control, streaming |
|
||||
| LLM-generated code | `runCode()` | Rich outputs, state persistence |
|
||||
| Build/test pipelines | `exec()` | Exit codes, stderr capture |
|
||||
| Data analysis | `runCode()` | Charts, tables, pandas |
|
||||
|
||||
## Extending the Dockerfile
|
||||
|
||||
Base image (`docker.io/cloudflare/sandbox:0.7.0`) includes Python 3.11, Node.js 20, and common tools.
|
||||
|
||||
Add dependencies by extending the Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
FROM docker.io/cloudflare/sandbox:0.7.0
|
||||
|
||||
# Python packages
|
||||
RUN pip install requests beautifulsoup4
|
||||
|
||||
# Node packages (global)
|
||||
RUN npm install -g typescript
|
||||
|
||||
# System packages
|
||||
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
EXPOSE 8080 # Required for local dev port exposure
|
||||
```
|
||||
|
||||
Keep images lean - affects cold start time.
|
||||
|
||||
## Preview URLs (Port Exposure)
|
||||
|
||||
Expose HTTP services running in sandboxes:
|
||||
|
||||
```typescript
|
||||
const { url } = await sandbox.exposePort(8080);
|
||||
// Returns preview URL for the service
|
||||
```
|
||||
|
||||
**Production requirement**: Preview URLs need a custom domain with wildcard DNS (`*.yourdomain.com`). The `.workers.dev` domain does not support preview URL subdomains.
|
||||
|
||||
See: https://developers.cloudflare.com/sandbox/guides/expose-services/
|
||||
|
||||
## OpenAI Agents SDK Integration
|
||||
|
||||
The SDK provides helpers for OpenAI Agents at `@cloudflare/sandbox/openai`:
|
||||
|
||||
```typescript
|
||||
import { Shell, Editor } from '@cloudflare/sandbox/openai';
|
||||
```
|
||||
|
||||
See `examples/openai-agents` for complete integration pattern.
|
||||
|
||||
## Sandbox Lifecycle
|
||||
|
||||
- `getSandbox()` returns immediately - container starts lazily on first operation
|
||||
- Containers sleep after 10 minutes of inactivity (configurable via `sleepAfter`)
|
||||
- Use `destroy()` to immediately free resources
|
||||
- Same `sandboxId` always returns same sandbox instance
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- **Don't use internal clients** (`CommandClient`, `FileClient`) - use `sandbox.*` methods
|
||||
- **Don't skip the Sandbox export** - Worker won't deploy without `export { Sandbox }`
|
||||
- **Don't hardcode sandbox IDs for multi-user** - use user/session identifiers
|
||||
- **Don't forget cleanup** - call `destroy()` for temporary sandboxes
|
||||
|
||||
## Detailed References
|
||||
|
||||
- **[references/api-quick-ref.md](references/api-quick-ref.md)** - Full API with options and return types
|
||||
- **[references/examples.md](references/examples.md)** - Example index with use cases
|
||||
@@ -0,0 +1,113 @@
|
||||
# Sandbox SDK API Reference
|
||||
|
||||
Detailed API for `@cloudflare/sandbox`. For full docs: https://developers.cloudflare.com/sandbox/api/
|
||||
|
||||
## Lifecycle
|
||||
|
||||
```typescript
|
||||
getSandbox(binding: DurableObjectNamespace<Sandbox>, sandboxId: string, options?: SandboxOptions): Sandbox
|
||||
|
||||
interface SandboxOptions {
|
||||
sleepAfter?: string; // Duration before auto-sleep (default: "10m")
|
||||
keepAlive?: boolean; // Prevent auto-sleep (default: false)
|
||||
normalizeId?: boolean; // Lowercase IDs for preview URLs (default: false)
|
||||
}
|
||||
|
||||
await sandbox.destroy(): Promise<void> // Immediately terminate and delete all state
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
```typescript
|
||||
await sandbox.exec(command: string, options?: ExecOptions): Promise<ExecResult>
|
||||
|
||||
interface ExecOptions {
|
||||
cwd?: string; // Working directory
|
||||
env?: Record<string, string>; // Environment variables
|
||||
timeout?: number; // Timeout in ms (no default; runs without timeout if unset)
|
||||
stdin?: string; // Input to command
|
||||
}
|
||||
|
||||
interface ExecResult {
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number;
|
||||
success: boolean; // exitCode === 0
|
||||
}
|
||||
```
|
||||
|
||||
## Code Interpreter
|
||||
|
||||
```typescript
|
||||
await sandbox.createCodeContext(options?: CreateContextOptions): Promise<CodeContext>
|
||||
|
||||
interface CreateContextOptions {
|
||||
language?: 'python' | 'javascript' | 'typescript'; // default: 'python'
|
||||
cwd?: string; // Working directory (default: '/workspace')
|
||||
envVars?: Record<string, string>;
|
||||
timeout?: number; // Request timeout in ms (default: 30000)
|
||||
}
|
||||
|
||||
await sandbox.runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>
|
||||
|
||||
interface RunCodeOptions {
|
||||
context?: CodeContext; // Reuse context for state persistence
|
||||
language?: 'python' | 'javascript' | 'typescript';
|
||||
timeout?: number; // Execution timeout in ms (default: 60000)
|
||||
}
|
||||
|
||||
interface ExecutionResult {
|
||||
code: string;
|
||||
logs: { stdout: string[]; stderr: string[] };
|
||||
results: RichOutput[]; // text, html, png, json, etc.
|
||||
error?: { name: string; value: string; traceback: string[] };
|
||||
executionCount: number;
|
||||
}
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
```typescript
|
||||
await sandbox.writeFile(path: string, content: string | Uint8Array): Promise<void>
|
||||
await sandbox.readFile(path: string): Promise<{ content: string }>
|
||||
await sandbox.mkdir(path: string, options?: { recursive?: boolean }): Promise<void>
|
||||
await sandbox.listFiles(path: string): Promise<FileMetadata[]>
|
||||
await sandbox.deleteFile(path: string): Promise<void>
|
||||
|
||||
interface FileMetadata {
|
||||
name: string;
|
||||
path: string;
|
||||
isDirectory: boolean;
|
||||
size: number;
|
||||
modifiedAt: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Ports
|
||||
|
||||
```typescript
|
||||
await sandbox.exposePort(port: number): Promise<{ url: string; token: string }>
|
||||
await sandbox.unexposePort(port: number): Promise<void>
|
||||
await sandbox.listPorts(): Promise<PortInfo[]>
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Errors include context about the operation:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await sandbox.exec('invalid-command');
|
||||
} catch (error) {
|
||||
// error.message includes command and sandbox context
|
||||
}
|
||||
```
|
||||
|
||||
For `runCode()`, check `result.error` instead of catching:
|
||||
|
||||
```typescript
|
||||
const result = await sandbox.runCode('1/0', { language: 'python' });
|
||||
if (result.error) {
|
||||
console.error(result.error.name); // "ZeroDivisionError"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# Sandbox SDK Examples
|
||||
|
||||
All examples: https://github.com/cloudflare/sandbox-sdk/tree/main/examples
|
||||
|
||||
## Example Index
|
||||
|
||||
| Example | Use Case | Key File |
|
||||
|---------|----------|----------|
|
||||
| `minimal` | Basic setup, exec, file ops | `src/index.ts` |
|
||||
| `code-interpreter` | AI code execution with Workers AI | `src/index.ts` |
|
||||
| `openai-agents` | OpenAI Agents SDK integration | `src/index.ts` |
|
||||
| `opencode` | OpenCode agent integration | `src/index.ts` |
|
||||
| `claude-code` | Claude Code agent integration | `src/index.ts` |
|
||||
| `typescript-validator` | TypeScript compilation/validation | `src/index.ts` |
|
||||
| `authentication` | Auth patterns for sandboxes | `src/index.ts` |
|
||||
|
||||
## When to Use Which Example
|
||||
|
||||
| Building | Start With |
|
||||
|----------|------------|
|
||||
| AI code execution | `code-interpreter` |
|
||||
| Agent with shell + file editing | `openai-agents` |
|
||||
| Basic command execution | `minimal` |
|
||||
| Code validation service | `typescript-validator` |
|
||||
| Multi-user sandboxes | `authentication` |
|
||||
|
||||
## Common Patterns from Examples
|
||||
|
||||
**Sandbox per user/session** (from `openai-agents`):
|
||||
```typescript
|
||||
const sandbox = getSandbox(env.Sandbox, `session-${sessionId}`);
|
||||
```
|
||||
|
||||
**Code context reuse** (from `code-interpreter`):
|
||||
```typescript
|
||||
const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
|
||||
const result = await sandbox.runCode(code, { context: pythonCtx });
|
||||
```
|
||||
|
||||
**Resource cleanup** (from `code-interpreter`):
|
||||
```typescript
|
||||
try {
|
||||
// ... use sandbox
|
||||
} finally {
|
||||
await sandbox.destroy();
|
||||
}
|
||||
```
|
||||
|
||||
Fetch the full example source when implementing similar patterns.
|
||||
Reference in new issue
Block a user