One Workspace, Three Ways to Execute

For Cloudflare Computer, runtime choice is a question about what an agent must be allowed and equipped to do around one durable Workspace. This chapter compares the common workspace.runtime doorway with the three execution contracts behind it: a full container shell, a fast just-bash Worker shell, and a bounded Worker JavaScript module. The useful outcome is conditional selection—choosing the smallest environment that can perform the work without mistaking a backend name for an authorization decision.

The preceding model gives the comparison a fixed reference point. The Durable Object’s SQLite-backed Workspace owns the durable filesystem. A container may mirror that filesystem so Linux programs can use it. The Worker backends call the host store more directly. Runtime selection changes the path used for computation, not the identity of the files the application cares about.

A common doorway, different execution contracts

Cloudflare Computer exposes one public execution namespace: workspace.runtime. An application supplies source and options, and the selected backend returns a handle that can produce events or a result. The runtime also has common operations for retrieving, stopping, and disposing of executions. This shared surface is valuable because an agent-facing tool does not need one completely different calling convention for each environment.

The shared doorway ends where source interpretation begins. A command backend treats the source as shell syntax. A module backend treats it as ECMAScript module source. A command result is naturally process-like—standard output, standard error, and an exit code. A callable JavaScript backend can additionally accept structured input and return a structured value. Passing structured input to a backend that does not declare itself callable is rejected rather than silently ignored.

Backend identifiers make that distinction explicit. Cloudflare Computer gives the shipped paths conventional IDs such as container-shell, worker-shell, and worker-javascript; the first configured backend is the default when a caller does not select one. That default is a convenience for application code, not a guarantee about the model’s authority or about the capabilities of the environment.

The same source text can therefore mean different things depending on the selected backend. A command like grep is a shell operation in the two command runtimes. A module that imports node:fs/promises is code for the Worker JavaScript runtime. The runtime surface can normalize handles and result shapes, but it should not hide this semantic difference from the caller or from an agent deciding where to run a task.

flowchart TD E["workspace.runtime.exec(source)"] --> L{"Need full Linux, native binaries, or package managers?"} L -- "Yes" --> C["container-shell\nreal userland and mirrored VFS"] L -- "No" --> M{"Need structured module input/results?"} M -- "Yes" --> J["worker-javascript\nfresh bounded Dynamic Worker"] M -- "No" --> S["worker-shell\nfast just-bash text tooling"] C --> P["Host policy allowlist\nand egress decision"] J --> P S --> P P --> W["Same durable Workspace\nwith backend-specific guarantees"]

A good comparison must therefore ask four questions in order: what source language is needed, what environment does the operation depend on, what authority should it receive, and what lifecycle or recovery behavior does the application require? Startup speed alone is not enough, and a long feature list can obscure the fact that each backend solves a different problem.

Worker shell: the fast path for textual work

The Worker shell runs the just-bash interpreter in a Dynamic Worker. A Dynamic Worker is an isolate loaded through the Worker Loader rather than a full container.