Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/cloudflare-os/llms.txt

Use this file to discover all available pages before exploring further.

Cloudflare OS is a monorepo of Cloudflare Workers packages that together form a coherent “operating system” for AI-driven productivity. At its core, a public-facing router dispatches requests to a stateful backend Durable Object (the “kernel”), which manages user sessions, workspaces, Gadget lifecycles, and security policy. Gatekeepers run as separate Workers and act as sandboxed bridges to external services. The frontend is a pure SPA that communicates with the backend exclusively over a Cap’n Web RPC session on a persistent WebSocket.
workerd — the Cloudflare Workers runtime that powers this stack — is fully open source. Cloudflare OS can run entirely on a self-hosted workerd instance on your own servers. The pnpm run-local command already uses workerd under the hood via wrangler.

The OS Analogy

Cloudflare OS is genuinely analogous to a traditional operating system at the technical level, not just in marketing language.
Traditional OSCloudflare OSNotes
Kernelpackages/workshop-backendManages users, workspaces, Gadgets, Gatekeepers, and enforces capability-based security
Device driverspackages/gatekeeper-*Each Gatekeeper bridges one external service (GitHub, Google, Slack, etc.)
Shellpackages/workshop-frontendPure SPA; communicates with the kernel only via the RPC API
ProcessesGadgetsUser-specific app instances, each sandboxed in a Dynamic Worker Facet
ExecutablesBlueprintsReusable code templates that any user can instantiate into their own Gadget
UsersUsersAuthenticated humans with their own Durable Object storing sessions and connected accounts
ACLsShared permissionsCapability-based access; each Gadget is introduced to resources explicitly
???AgentsFirst-class concept distinct from users; accountable to a human, with restricted permissions
AI agents are an additional concept that traditional operating systems do not model. Cloudflare OS treats agents as distinct from users: they are accountable to a specific human, carry narrower permissions, and execute code inside the same sandboxed Gadget environment.

Package Structure

The monorepo is organized into focused packages, each with a clearly bounded role.
packages/workshop-backend — The kernel. Runs on Cloudflare Workers with multiple Durable Object classes (UserDurableObject, OverseerDurableObject, AdminSettings, PendingLogin). Responsible for authentication, workspace lifecycle, Gadget sandboxing, Gatekeeper capability management, and the AI agent loop. Every line of this package is held to a high review bar — keep diffs small and changes elegant.packages/workshop-frontend — The shell. A pure client-side SPA built with React, Kumo UI, Phosphor icons, and Vite. Connects to the backend over a persistent WebSocket and speaks the Cap’n Web RPC API defined in workshop-shared. Contains no server-side rendering — all Gadget sandboxing happens in the browser.packages/workshop-shared — Shared API definitions used by both the frontend and backend. Defines every RPC interface (PublicApi, AuthenticatedApi, Overseer, GadgetClient, AdminApi, and more) using Cap’n Web’s RpcTarget / RpcStub types. Changing this package changes the contract between client and server — treat it with the same care as the backend.packages/router — The public-facing origin Worker. Routes incoming requests by path prefix: /api/* and /blueprint-screenshot/* go to the workshop-backend service binding, and /gatekeeper/<name>/* goes to the matching GATEKEEPER_* service binding. Gatekeeper bindings are discovered at runtime by scanning the router’s own environment for GATEKEEPER_ prefixed bindings — installing a new Gatekeeper is purely a binding change, not a code change. In development mode (no ASSETS binding), the router proxies frontend requests to the Vite dev server instead.

Request Flow

A request from the browser travels through several layers before reaching its destination.
Browser

  │  WebSocket (Cap'n Web RPC) / HTTP

packages/router  (public origin Worker)

  ├─ /api/*  ──────────────────────────────►  workshop-backend (WORKSHOP_BACKEND binding)
  │                                               │
  │                                               │  Durable Object stub
  │                                               ▼
  │                                           OverseerDurableObject  (one per workspace)
  │                                               │
  │                                               │  Service binding
  │                                               ▼
  │                                           Gatekeeper Worker  (one per connected resource)

  ├─ /gatekeeper/<name>/*  ────────────────►  GATEKEEPER_<NAME> service binding

  └─ /*  ──────────────────────────────────►  ASSETS (frontend SPA) / Vite dev server
The router is stateless and acts purely as a dispatcher. All persistent state lives in Durable Objects inside workshop-backend. Each workspace has its own OverseerDurableObject instance, which manages the Gadgets, chat threads, code history, and Gatekeeper bindings for that workspace.

Service Binding Structure

The root wrangler.jsonc (used for local development via pnpm run-local) defines the router as the entry point with a single static service binding to the backend. Gatekeeper bindings are added dynamically at dev and deploy time:
// wrangler.jsonc (root — dev-router)
{
  "name": "dev-router",
  "main": "packages/router/src/index.ts",
  "compatibility_date": "2025-11-01",
  "compatibility_flags": ["enable_ctx_exports"],

  // Gatekeeper service bindings are dynamically added by run-dev-server.js
  "services": [
    {
      "binding": "WORKSHOP_BACKEND",
      "service": "workshop-backend"
    }
  ]
}
In a deployed customer instance, the router’s wrangler.jsonc is augmented with one GATEKEEPER_<NAME> service binding per installed Gatekeeper — for example, GATEKEEPER_GITHUB, GATEKEEPER_GOOGLE, GATEKEEPER_SLACK. The router discovers them at runtime by scanning its own environment, so no router code changes are needed to add or remove a Gatekeeper.

RPC Protocol: Cap’n Web

All communication between the frontend and backend — and between the backend and Gatekeeper Workers — uses Cap’n Web, a JavaScript/TypeScript RPC system with semantics similar to Cloudflare’s Worker-to-Worker RPC, adapted to run in a browser over WebSocket. Cap’n Web is the right choice here for two reasons:
  1. Promise pipelining — If an RPC call returns a stub, you can immediately call methods on that stub without waiting for the first round trip to complete. The server resolves the pipeline server-side before delivering the downstream call. This eliminates unnecessary round trips and makes the API feel like local function calls. The api.ts file is built entirely around this pattern — for example, openGadget() returns an Overseer stub, and you can pipeline getMetadata(), listChats(), and subscribeToCode() on it before the first call even resolves.
  2. Low boilerplate — You define a TypeScript interface extending RpcTarget, implement it on the server, and call it from the client as if it were local. There is no schema file, no code generation step, and no manual serialization. This also means Gadget APIs are automatically agent-accessible: because every Gadget’s client and server communicate through Cap’n Web, an AI agent using Code Mode can call any Gadget method directly.
The RPC session is established over a persistent WebSocket that the frontend opens at startup and keeps alive for the duration of the session, reconnecting automatically if needed. Gadgets communicate with their server-side Durable Object through the same mechanism — the frontend passes the Gadget a Cap’n Web stub via postMessage() into its sandboxed iframe.

Sandbox Model

Cloudflare OS enforces two layers of sandboxing for every Gadget. Server-side sandbox (Dynamic Worker Facets): Each Gadget’s server code runs in a Dynamic Worker instantiated as a Facet of the workspace’s OverseerDurableObject. The Dynamic Worker has all outbound network access disabled by default. It can only communicate with external resources that have been explicitly bound into its environment via Workers Bindings — meaning a Gatekeeper that the user has explicitly introduced to that workspace. Client-side sandbox (sandboxed iframes): Each Gadget’s UI code runs inside a sandboxed <iframe> with Content-Security-Policy and iframe sandbox attributes that block it from accessing the internet directly. The only channel available to the Gadget’s client code is a Cap’n Web RPC session provided over postMessage() by the parent Workshop frame. Through this session, the Gadget can call its own server-side Durable Object and interact with the Workshop shell — and nothing else. This two-layer model means that even if an agent writes buggy or malicious Gadget code, the sandbox prevents it from leaking data or calling arbitrary services. Security is structural, not policy-based.

Quickstart

Run the full stack locally in minutes or deploy to your Cloudflare account.

Gatekeeper Overview

Learn how to connect external services to agents and Gadgets through the Gatekeeper security layer.

Build docs developers (and LLMs) love