sandbox-sdk — Engineering Performance
11 engineers all time · Jun 2025 – Aug 2026 · built 2026-09-08 · GitHub
Performance snapshot
Today's rolling 90-day reading for sandbox-sdk, compared with the start of the series. Pick a window to move that comparison point.
Avg. perf / dev / mo
−46.1%
1.54 → 0.83 ETV
Active engineers
+66.7%
3.0 → 5.0
Features
−17.4pp
64.5% → 47.1%
vs. Cloudflare
0.68x
2.9x → 0.68x · −32% below
sandbox-sdk vs. Cloudflare
Per-engineer ETV for sandbox-sdk against Cloudflare as a whole. Both lines are 90-day rolling averages scaled to a 30-day month, so they share one axis and can be read against each other at any point. Pick a window to zoom the chart to it.
Performance Composition
Each month's output split by type of work: Features (new value), Maintenance (sustaining systems), Tests, Docs, and Fixes (rework). The yellow line is output per engineer, so when it rises each engineer is delivering more, whatever the team size did. Unit: Engineering Throughput Value (ETV).
Engineering capacity
Effective engineers behind sandbox-sdk, against its pre-AI baseline. Each subject has its own: sandbox-sdk's is 1.54 ETV / dev / mo, its first reading in September 2025. Per-engineer ETV divided by that gives a capacity multiple, and that multiple applied to the engineers active in the trailing 90 days turns it into engineer-equivalents. The line is the real headcount, so the gap between line and area is what the leverage is worth. Because each baseline is its own, every subject opens at 1.0x on its first day: multiples measure improvement and are not comparable between subjects.
Knowledge concentration
How dependent is this repo on a small number of engineers? Higher top-1 share = higher key-person risk.
Naresh owns 34.1 % of commits.
Behind the numbers
Written summary of the work completed each month.
No monthly reports available yet.
Top engineers
Most impactful commits
Top 10 by ETV in the all-time window.
- 4.2ETVAdd two-stage stable release engine Publish immutable release artifacts from an exact release SHA, then promote public Docker refs on main only after that version is complete.Naresh · e8e9e48f · 2026-07-22
- 3.1ETVImplement sessionless execution mode (#706) * implement sessionless exec path * patch test issues * fix sessionless inconsistencies * fix issues + add e2e tests * fix execStream bug * biome fix * fix e2e test * remove configurable session passing * patch e2e test worker * dont persist in DO + change sentinel value * fix sentinel leaking * rebase * fix exec options merging bugs * fix rpc origin bug * address bonk comments * fixed proxy routing bug * update clunky method name * CI update --------- Co-authored-by: scuffi <aferguson@cloudflare.com>Archie Ferguson · ae5f9a10 · 2026-05-27
- 2.8ETVAdd desktop environment container runtime (#422) * Add desktop environment container runtime Enables running a full Linux desktop inside sandbox containers with programmatic screenshot and input control via native FFI. * Add desktop environment SDK client (#423) * Add desktop environment SDK client Sandboxes need a public API for desktop environments so Workers can manage desktops, capture screenshots, and stream VNC. The Dockerfile gains a desktop build stage with the required system dependencies. * Add desktop environment tests (#424) * Add desktop environment tests Unit tests for the container handler, service, and SDK client, plus an E2E test that exercises the full desktop lifecycle through a real deployed worker. * Add desktop viewer example (#425) React + Vite + Tailwind v4 app that demonstrates the desktop environment API with noVNC streaming and viewport-aware resolution. * Fix lint errors in desktop example and biome config * Add desktop E2E test Dockerfile and config generation * Add desktop image to CI build, push, and cleanup workflows * Fix Go build: pin golang.org/x/net to Go 1.24-compatible version go mod tidy resolved golang.org/x/net@v0.51.0 which requires go >= 1.25, breaking the go-builder stage using golang:1.24-bookworm. Pin to v0.50.0 (last Go 1.24-compatible release) and update go directive to match builder. * Fix FFI type mismatch and clickCount handling The Click FFI binding declared 'bool' (1-byte C _Bool) but the Go function expects C.int (4 bytes), causing undefined ABI behavior. Changed to 'int' and pass clickCount through directly so tripleClick emits three rapid single clicks instead of silently degrading to doubleClick. * Guard desktop stop in destroy() on container state desktop.stop() goes through containerFetch which auto-starts sleeping containers. Check ctx.container.running first so destroy() does not wake a container just to immediately tear it down. * Revert accidental backup and token doc changes The desktop branch commit inadvertently changed backup curl from streaming -T to --data-binary (loads full archive into memory), reduced timeouts from 1800s to 300s, removed the local-dev mismatch diagnostic, and changed token docs to show hyphens which the validation regex rejects. Restore all to match main. * Add error resilience to desktop worker and manager Catch stop() failures during start() error recovery so the original error propagates. Add onerror handler to the worker thread so pending promises reject instead of hanging if the worker crashes. * Fix FFI out-pointer semantics and skip stream-url in CI koffi requires koffi.out() annotation on pointer parameters to copy values back from C to JS after the call. Without it, GetScreenSize and GetMousePos always returned zeros because koffi treated int* as input-only. The stream-url E2E test requires preview URL infrastructure (custom domain with wildcard DNS) that CI workers.dev doesn't provide, so skip it with the same pattern used by other port-exposure tests. * Reset manager state on start failure DesktopManager.start() sets state to 'starting' but the catch block relied solely on stop() to reset it to 'inactive'. When stop() itself fails, state remains 'starting' permanently, blocking all subsequent start attempts. Explicitly set state to 'inactive' after cleanup. * Use pure-Go xgb path for GetScreenSize robotgo.GetScreenSize() delegates to C-based XGetMainDisplay() which holds an unsynchronized static Display pointer. In Go's c-shared build mode CGo dispatches from varying OS threads, causing the singleton to silently return zero dimensions. Switch to robotgo.GetDisplayBounds(0) which uses the github.com/kbinani/screenshot pure-Go xgb implementation, matching the existing workaround for the SaveCapture segfault. * Upgrade robotgo to v1.0.1 with uniform error handling Use dedicated v1.0.1 APIs (MouseDown/Up, KeyDown/Up, Type, MultiClick) instead of Toggle/KeyToggle/TypeStr. All Go FFI exports now return error strings via *C.char, and the koffi bindings use HeapStr with a checkError() helper for uniform error propagation. Rename TypeStr→TypeText and SaveCapture→Screenshot to match v1.0.1 naming. Click now takes a count parameter — single, double, and multi-click are handled in Go. The worker-side triple-click loop is removed since Go handles it natively via robotgo.MultiClick.Naresh · dc706497 · 2026-03-03
- 2.6ETVEnforce preview URL runtime activation (#708) * Enforce preview URL runtime activation * Raise E2E sandbox instance cap The default E2E sandbox app can hit its 50-instance cap when the three transport jobs run file-parallel Vitest suites. Raise the cap modestly to match observed CI demand while keeping capacity bounded. * Clean up preview URL E2E tests Make lifecycle synchronization wait for terminal container states and keep preview URL tests closer to public SDK flows. This avoids relying on transitional stop states or hand-edited preview hostnames. * Configure E2E warm pool in wrangler Declare warm pool sizing in the test worker config instead of mutating every container app after deploy. This keeps variant images from reserving unused warm capacity during stacked PR CI. * Reconcile tunnel lifecycle with runtime stops * Restore R2 egress handler registration ContainerProxy resolves outbound handlers through the containers registry populated by the static setter. Keep the test mock aligned with that lookup path so R2 egress mounts fail if the handler is not registered for runtime dispatch. * Remove preview containers dependency Replace the temporary containers package dependency with the latest published release and keep preview URL forwarding non-waking through an SDK-owned helper. The Sandbox DO remains responsible for preview auth and runtime activation decisions, while the helper handles TCP response forwarding and lifecycle settling.Naresh · 287ec04b · 2026-05-28
- 2.6ETVAdd process isolation and persistent sessions for all commands (#59) * Add process isolation for sandbox commands Implements PID namespace isolation to protect control plane processes (Jupyter, Bun) from sandboxed code. Commands executed via exec() now run in isolated namespaces. Key changes: - Sandboxed commands can no longer see or kill control plane processes - Platform secrets in /proc/1/environ are inaccessible - Ports 8888 (Jupyter) and 3000 (Bun) are protected from hijacking - Commands within sessions now maintain state (pwd, env vars) - Graceful fallback when CAP_SYS_ADMIN not available (dev environments) BREAKING CHANGE: Commands within the same session now share state. Previously each command was stateless. Use createSession() for isolated command execution. * Stop information exposure through stack trace * Implement secure streaming execution with ExecutionSession support - Fix streaming security hole by routing through SessionManager instead of direct spawn() - Add ExecutionSession.execStream() method for secure real-time command streaming - Maintain backward compatibility by bridging sessionId API to ExecutionSessions - Extend SessionManager with streaming capabilities using isolated control processes * Remove sessionId * Make file ops session-aware too * Remove duplicate code paths * Fix streaming and corresponding abort * Fix log fetch endpoint * Minor fixes * Rename back to sessionId * Fix pending name references * Move control script into separate file * Fix type errors * fix biome lint errors * Prevent shell command injection * Move code around * Reorganise code * Update changesetNaresh · b6757f73 · 2025-08-15
- 2.1ETVfeat: add file watching capabilities with inotify support (#324) * feat: add file watching capabilities with inotify support * Create empty-poets-serve.md * Potential fix for code scanning alert no. 42: Incomplete string escaping or encoding Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fixes for claude review * update tests to verify regex format for default and custom excludes * Fix error handling and type safety in WatchService and FileWatch classes. Update tests to validate new event parsing logic and ensure proper handling of inotifywait output. * Refactor WatchService tests to validate combined regex patterns for default and custom excludes * Added timeouts for event propagation * Refactored and cleaned * Small ws transport related fixes * Timing changes help account for the additional buffering * Fix WebSocket blocking issue for SSE streaming responses Streaming responses (like file watch events) were blocking the WebSocket message handler because handleStreamingResponse was awaited. This prevented other messages from being processed while a stream was active. Run streaming response handlers in the background with error logging, allowing the message handler to return immediately and process subsequent messages. * Add debug logging and stream tracking for WebSocket streaming Add detailed logging to trace streaming response handling and track active streams to prevent potential garbage collection of Response objects. * Acquire stream reader synchronously before async execution The WebSocket message handler needs to capture the Response body reader before any await points. When getReader() was called inside the async handleStreamingResponse method, Bun's WebSocket handler would return before the reader was acquired, potentially invalidating the Response body stream. By getting the reader synchronously in handleRequest before the promise starts executing, we ensure the stream remains valid throughout the async streaming loop. * Wait for inotifywait watches to be established before signaling ready The watching SSE event was sent immediately when the stream started, before inotifywait finished setting up watches. This caused flaky tests because file operations could occur before the watch was truly ready. Now we read stderr and wait for the 'Watches established' message from inotifywait before sending the watching event to clients. * Add timeout to waitForWatchesEstablished to prevent hanging If inotifywait fails to output 'Watches established' within 10 seconds, the function will return and allow the stream to proceed. This prevents indefinite hangs if inotifywait behaves unexpectedly. * Wait for first message before returning WebSocket stream For WebSocket streaming, errors were deferred until stream consumption. This caused issues where watchStream() would return successfully even when the server returned an error response. Now requestStream() waits for the first message before returning: - If it's a stream chunk, return the stream (success case) - If it's an error response, throw immediately (error case) This makes WebSocket streaming behavior match HTTP streaming, where errors are thrown immediately rather than deferred. * Address code review issues in file watching Replace empty catch blocks with debug/warn logging throughout WatchService and FileWatch to make failures visible. Fix FileWatch.established() to reject on AbortSignal during establishment, preventing indefinite hangs. Strengthen the SSE event type guard to validate required fields per event type. Add WATCH_STOP_ERROR code, integrate watch cleanup into server shutdown, and rewrite changeset for end users. * Fix file watch E2E test timeout race condition The watchWithActions timeout started at stream creation but blocked for ~6.5s inside the event handler (pre-action delay + file ops + post-action delay), leaving insufficient time to read events in CI. Reset the timeout after actions complete so the full window is available for event collection. * Fix exclude test timeout in file watch E2E The combined wait time (~18s) approached the 30s Vitest timeout. With excludes filtering most events, only 2-4 arrive, so the high stopAfterEvents threshold was never reached and the test always fell through to the full 12s reader timeout. * Remove low-level watch API to simplify public interface Remove watchStream(), stopWatch(), and listWatches() methods from Sandbox class. The handle-based API via watch() is sufficient for all use cases and prevents resource management confusion. Keep the internal WatchService methods for container use but don't expose them through the SDK public API. * Harden file watch stream lifecycle * Stabilize explicit watch stop e2e test * Isolate file-watch e2e sessions per test * Stabilize file-watch error and stop e2e cases * Stabilize websocket e2e flake handling Treat watch stop as idempotent when a watcher is already gone and make OpenCode proxy health checks resilient to transient startup failures. Relax the foreground timing threshold to reduce transport-related CI jitter without masking blocking behavior. * Treat ESRCH as success when stopping already-gone watch process Handle the race where a watch process exits before stopWatch() is called. When process.kill() throws ESRCH (no such process), clean up the watch entry and return success instead of an error. * Isolate file watch e2e sandbox * Route watch E2E through SDK surface * Use SDK watch bridge without new public API * Remove unused watch stop endpoint and reduce stream logging verbosity Remove /api/watch/stop endpoint and WatchClient.stop() method as watch lifecycle is now managed through handle-based API. Clean up verbose debug logging in WebSocket stream handler, keeping only completion summary. Clear setup timeout in watch service to prevent leak. * Scope stream cancellation to owning WebSocket connection Track connectionId for each active stream and only allow cancellation from the connection that initiated it. Prevent cross-connection cancel messages and ensure onClose only cancels streams owned by the closing connection. * Address review: parseSSEStream abort, watch readiness, include/exclude validation - Fix parseSSEStream to register abort listener that calls reader.cancel(), unblocking idle streams instead of polling signal.aborted between reads - Make watch() block until the watching event is received so callers can immediately perform actions that depend on the watcher being active - Reject requests that specify both include and exclude with a clear validation error since inotifywait does not support both simultaneously - Add timeout-race tests for WebSocket transport stream requests - Simplify E2E watch helper: use parseSSEStream + AbortSignal.timeout, remove all hardcoded delays - Remove test worker workaround that silently dropped exclude when include was present * Simplify non-existent path error test watch() now throws on establishment failure, so the test worker returns a clear error response. The 3-path defensive logic is no longer necessary. * Simplify stop-watch test: remove manual watching detection watch() now blocks until established, so the manual loop scanning for the watching event is redundant. Read one chunk to confirm the stream is live, then cancel. * chore: retrigger CI * Update .changeset/empty-poets-serve.md Co-authored-by: Naresh <ghostwriternr@gmail.com> * FIxed small review comments --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Naresh <ghostwriternr@gmail.com>whoiskatrin · 2af3c283 · 2026-03-03
- 2.0ETVImplement no credential R2 binding mount support (#691) * Support credential-less R2 mounting * fix dynamic outbound intercept handlers * remove inline egress handler * fix various egress bugs * fix regex issues * address bonk comments * address PR comments * export containerproxy from e2e worker * address PR comments * change r2 upload path to fixedlengthstream * export from containers * update e2e worker wrangler * remove arrayBuffer from multipart upload * fix 0 len uploads + dual mount bug * set durable_object_offset_instances in wrangler * set durable_object_offset_instances in wrangler --------- Co-authored-by: scuffi <aferguson@cloudflare.com>Archie Ferguson · 3ca24fc3 · 2026-05-20
- 2.0ETVAdd WebSocket transport (#253) * add ws transport + e2e * remove unused * fix types * chore: remove ws-transport e2e test (will use existing e2e with WS header) * fix: WebSocket transport for DO environment + dual transport tests - WSTransport: Add fetch-based WebSocket connection for Workers/DO context - Uses containerFetch with upgrade headers instead of raw new WebSocket() - Required because DOs cannot use direct WebSocket() connections to containers - Transport: Pass stub and port to WSTransport for proper routing - CommandClient: Use doStreamFetch for streaming (supports both HTTP and WS) - comprehensive-workflow.test.ts: Run all tests with both HTTP and WebSocket transport * feat: add dual transport (HTTP + WebSocket) testing to e2e tests Updated test files to run with both HTTP and WebSocket transport modes: - comprehensive-workflow.test.ts - file-operations-workflow.test.ts - streaming-operations-workflow.test.ts - environment-workflow.test.ts - git-clone-workflow.test.ts - process-lifecycle-workflow.test.ts - process-readiness-workflow.test.ts - keepalive-workflow.test.ts - code-interpreter-workflow.test.ts - build-test-workflow.test.ts Each test suite now runs twice - once with HTTP transport (default) and once with WebSocket transport (X-Use-WebSocket header). This validates that the WebSocket transport works identically to HTTP for all SDK operations. * fix: use doStreamFetch for WebSocket streaming in ProcessClient and FileClient - ProcessClient.streamProcessLogs: use doStreamFetch instead of doFetch - FileClient.readFileStream: use doStreamFetch instead of doFetch This ensures proper streaming over WebSocket transport. * fix: complete WebSocket transport support for all streaming operations - base-client.ts: Add method parameter to doStreamFetch for GET/POST support - transport.ts: Update requestStream and httpRequestStream for GET/POST - process-client.ts: Use doStreamFetch with GET for process log streaming - file-client.ts: Use doStreamFetch for file streaming - interpreter-client.ts: Use doStreamFetch for code execution streaming - interpreter.ts: Use doStreamFetch for runCodeStream - process-lifecycle-workflow.test.ts: Accept 'already exposed' in port test All 105 e2e tests now pass with both HTTP and WebSocket transport! * Fix incorrect merge * Fix WebSocket transport issues Resolve SSE parsing data loss, connection race conditions, send failure handling, stream cleanup on close, module-level state, and type safety. * Add changeset for WebSocket transport * Integrate WebSocket handler into server module The WebSocket handler was in a separate index.ts that wasn't included in the build. This moves the handler integration into server.ts where the actual server is started, and removes the unused index.ts. * Refactor transport configuration and add CI matrix Replace useWebSocket boolean with transport string union type for future extensibility. Add SANDBOX_TRANSPORT env var support following the existing pattern of SANDBOX_LOG_LEVEL. Configure CI to run E2E tests with both HTTP and WebSocket transports in parallel via matrix. * Fix resource leaks and type safety in WebSocket transport Add client.disconnect() calls before client replacement and in destroy() to prevent WebSocket connection leaks. Add public streamCode() method to InterpreterClient to eliminate unsafe any cast. Add error boundaries in server WebSocket handlers and fix timeout cleanup in ws-transport. * Fix null check for stored transport in constructor * Improve WebSocket transport robustness and documentation Fix race condition in connection promise handling, add 503 retry logic for WebSocket mode to match HTTP behavior, improve error handling for stream operations, and add WSTransport unit tests. Extract client creation to helper method and organize exports. * Unify Transport abstraction and clean up API surface BaseHttpClient now always uses Transport for all requests, eliminating the previous split where HTTP mode bypassed Transport entirely. This ensures both HTTP and WebSocket modes share the same code paths for retry logic and error handling. Removed the legacy TransportResponse-based API (request, requestStream) in favor of the standard Fetch API (fetch, fetchStream). This reduces bundle size by ~2.4 kB and provides a cleaner, more familiar interface. * Refactor transport layer for cleaner separation of concerns Extract HTTP and WebSocket transports into dedicated classes with a shared base class for retry logic. This creates symmetric file structure and clear interfaces for both transport modes. SDK changes: - Create transport/ directory with ITransport interface - Add BaseTransport with shared 503 retry logic - Add HttpTransport and WebSocketTransport implementations - Update consumers to use ITransport interface Container changes: - Rename ws-handler to ws-adapter (reflects protocol adapter role) - Use 'container' log component instead of dedicated entry * Cleanup tests * Remove working documents * Simplify transport config to env var only * Use stub.fetch() for WebSocket transport connection stub.fetch() routes WebSocket upgrade requests through the parent Container class that supports the WebSocket protocol. * Remove redundant plugin config from workflow Plugins are configured via .claude/settings.json. * Revert "Remove redundant plugin config from workflow" This reverts commit 469489e5243c7af5458a7833dada6c861e4f1b9e. * Optimize CI: build Docker once, fix cleanup for transport variants pullrequest.yml: - Extract Docker build into separate job (build-docker) - Both HTTP and WebSocket E2E jobs download pre-built images - Uses docker/build-push-action with GHA layer caching per image variant cleanup.yml: - Clean up all transport variants (-http, -websocket) on PR close cleanup-stale.yml: - Update regex to match transport-suffixed worker names - Fix PR number extraction to handle suffix * Fix WebSocket transport error handling Wrap send() calls in try-catch to properly reject promises and error stream controllers when the WebSocket is disconnected. Also fail early with a clear error when request body JSON parsing fails. * Simplify CI Docker builds Build all images once and share via artifacts to both E2E jobs. * Optimize CI with buildx cache and CF registry Reduces CI runtime by using GHA buildx cache for consistent layer digests and pushing images to Cloudflare registry before deploy. Deploy then references pre-pushed images instead of building and pushing during the slow wrangler deploy step. Cache scopes are shared between e2e-tests and publish-release jobs in the release workflow, so publish-release benefits from cache warmed by e2e-tests. * Parallelize Docker image builds in CI Build base, python, and opencode images concurrently using bash background processes. Standalone builds after base is pushed since it references base from the registry. Pushes to Cloudflare registry are also parallelized where possible. --------- Co-authored-by: Naresh <naresh@cloudflare.com>deathbyknowledge · 4b4ab483 · 2025-12-18
- 1.9ETVAdd PTY terminal passthrough for browser clients (#310) * Add PTY types to shared package * Add PtyManager for container PTY lifecycle * Add PTY handler and route registration * Add PTY message handling to WebSocket adapter * Add PTY methods to transport interface * Add PtyClient for SDK PTY operations * Add pty namespace to Sandbox class * Add E2E tests for PTY workflow * Add changeset for PTY support * Skip PTY tests when PTY allocation fails * Fix pty manager tests * fix any types, logger * fix silent logging * fix pty tests for resizing * update claude review yml * revert review change * update http tests * more test updates * remove the plugin for review * Add error handling to PTY callbacks and terminal operations * Improve PTY error handling based on code review * add structured exit codes * change fire and forget strategy * add more e2e tests * more fixes and tests * fix ws * update error propagation * update resizing tests * add collab terminal example * Potential fix for code scanning alert no. 40: Insecure randomness Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 41: Insecure randomness Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Update dependency in examples * Add PTY listeners cleanup * minor nits * update tests setup * Add logging for PTY listener registration errors and improve error handling * Enhance error handling and logging in WebSocketTransport and PtyHandler; add tests for PTY listener registration and cleanup behavior * Add connection-specific PTY listener cleanup on WebSocket close * Remove outdated comment regarding connection cleanup functions in WebSocketAdapter * Fix error handling in PTY management by updating kill method to return success status and error messages * implement signal handling for Ctrl+C, Ctrl+Z, and Ctrl+\ in the PTY manager * Potential fix for code scanning alert no. 43: Insecure randomness Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Changes based on review comments * Update dependencies and improve PTY handling in collaborative terminal example * Update PTY workflow tests to expect correct HTTP status codes for error responses * extractPtyId method to retrieve PTY IDs from responses, and update handleRegularResponse to return parsed body for further processing * Update PTY workflow tests to expect 'message' field in error responses instead of 'error' * Fixed handlers for tests * Use PR-specific Docker build cache scope to avoid cross-PR cache pollution * Add debug logging to router for route registration and matching * Add INFO-level route logging to debug container caching issues * Add retry logic for WebSocket server readiness in e2e tests The WebSocket connect tests were flaky because they didn't wait for the echo server to be ready after /api/init. Added a helper function that retries WebSocket connection with backoff before running tests. * Remove debug logging added during PTY route investigation The 404 issues were caused by stale container instances, not route registration problems. Reverting the debug logging changes: - Remove INFO-level route logging from router - Remove logRegisteredRoutes() method - Revert PR-specific Docker cache scope (not needed) * Fix sync-docs workflow to handle PR bodies with special characters Use quoted heredoc and printf to safely handle PR description content that may contain backticks, code blocks, or other shell-sensitive characters. Pass PR body via environment variable to prevent shell interpretation during prompt construction. * Fix sync-docs workflow shell escaping for opencode run Use environment variable to pass prompt to opencode run, avoiding shell interpretation of special characters like parentheses, backticks, and dollar signs that appear in PR descriptions with code examples. The prompt is stored in OPENCODE_PROMPT env var which GitHub Actions sets safely, then referenced with double quotes in the shell command. * Fix lint errors and align env type signatures The recent env var changes in 7da85c0 introduced Record<string, string | undefined> but missed updating getInitialEnv return type and getSessionInfo. Also aligns vite-plugin versions across examples. * send heartbeat events to keep container alive * Add PTY terminal passthrough for browser clients Enables browser-based terminal UIs to connect to sandbox shells via WebSocket. The terminal() method proxies connections to the container's PTY endpoint with output buffering for replay on reconnect. * Add tests and infrastructure for PTY terminal (#375) * Add tests and infrastructure for PTY terminal Unit tests for ring buffer, PTY spawning, and WebSocket handler. E2E tests for PTY workflow and browser terminal addon integration. Updates CI workflows and documentation for new test patterns. * Add collaborative terminal example and refine xterm addon (#376) * Refactor SandboxAddon to use connect(target) * Add collaborative terminal example Demonstrates the SandboxAddon connect() API with real-time room switching, presence tracking, and session isolation across multiple terminal rooms. Co-authored-by: Naresh <naresh@cloudflare.com> * Clear bash startup warning in container PTY Bash emits 'cannot set terminal process group' warnings in containers where the shell isn't a session leader. This clutters the first lines of terminal output for users. * Add build/** to turbo output cache React Router outputs to build/ instead of dist/, causing turbo to warn about missing outputs for the collaborative-terminal example. * Update collaborative-terminal README for new API The previous README documented the old PTY API (sandbox.pty.create() with JSON WebSocket protocol) that no longer exists. Updated to reflect the current implementation using session.terminal(request) with direct WebSocket passthrough and SandboxAddon for terminal integration. --------- Co-authored-by: katereznykova <kreznykova@cloudflare.com> --------- Co-authored-by: katereznykova <kreznykova@cloudflare.com> --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Naresh <naresh@cloudflare.com> Co-authored-by: Steve James <sjames@cloudflare.com> Co-authored-by: Naresh <ghostwriternr@gmail.com>whoiskatrin · 3c035872 · 2026-02-06
- 1.7ETVImplement egress interception for S3 mounts (#727) * Implement egress interception for S3 mounts * Implement missing egress handler * Fix proxy handler errors * patch zero len bugs * patch gcs writes * address PR comments * fix password file issue * fix stale proxy issue --------- Co-authored-by: scuffi <aferguson@cloudflare.com>Archie Ferguson · 2acbd243 · 2026-06-05