computer
Frameworkcloudflare/computer
Virtual filesystem and runtime for building agent workspaces on Cloudflare Workers.
Overview
Cloudflare Computer provides a SQLite-backed virtual filesystem inside a Durable Object, with pluggable execution backends such as containers, shell isolates, and JavaScript isolates. It exposes workspace.runtime.exec as a single entry point and supports FUSE mounts, sync over RPC, and durable relative imports.
README Preview
# Cloudflare Computer\n\nCloudflare Computer is a virtual filesystem that lives inside a\nDurable Object. The Durable Object holds the authoritative state in\nSQLite and exposes one pluggable execution surface through\n`workspace.runtime`. Three backends ship today:\n\n- **Container** projects the SQLite state into a sandbox container as\n a real FUSE mount. A sandbox-side daemon (`computerd`) mounts the state\n as a filesystem and syncs changes back over a capnweb RPC channel.\n Full Linux userland, real binaries, real network.\n- **Isolate shell** runs [just-bash](https://github.com/vercel-labs/just-bash)\n in a Dynamic Worker. It reaches the authoritative Workspace over\n Workers RPC, so there is no second store or sync round trip.\n- **Isolate JavaScript** runs an ECMAScript module in a fresh Dynamic\n Worker with structured input/results, durable relative imports,\n configured libraries, Workspace-backed `node:fs/promises`, and trusted `ws:git` and\n `ws:artifacts` modules.\n\nA Workspace may register multiple backends under stable IDs.\n`workspace.runtime.exec(source, { backend })` is the single execution\nentry point; the selected backend defines whether `source` is a shell\ncommand or an ECMAScript module. Backends connect lazily on first use.\n\nWorkspace can also be constructed without a backend at all, giving\ncallers the filesystem on its own.\n\n> [!IMPORTANT]\n> **PREVIEW ONLY** This package is provided as a preview for feedback only.\n> APIs are unstable and the design is subject to change.\n>\n> Suitable for experiments, exploration and prototypes. It is NOT suitable\n> for production use at this time.\n>\n> The specification under [`docs/`](docs/) is forward-looking — read it for\n> intent, not as description of the code today.\n\n## Using it\n\nIf you want to build on Cloudflare Computer, install\n[`@cloudflare/computer`](packages/computer/README.md) and follow that\npackage's README — it has the installation steps, the entrypoint map,\nandFAQ (5)
TroubleshootingHow do I fix "Cannot read properties of undefined (reading 'WorkspaceServiceProxy')" when running worker-shell exec in Cloudflare Computer?
This error has two possible setup causes. Fix both:
1. Add the required enable_ctx_exports compatibility flag to wrangler.toml:
compatibility_flags = ["nodejs_compat", "experimental", "enable_ctx_exports"]
If using `wrangler.json`:json{
"compatibility_flags": ["nodejs_compat", "experimental", "enable_ctx_exports"]
}
2. Re-export `WorkspaceServiceProxy` from your Worker entry point:jsexport { WorkspaceServiceProxy } from "@cloudflare/computer";
Restart or redeploy Wrangler, then retry:bashcurl -X POST localhost:8787/exec \
-H 'content-type: application/json' \
-d '{"cmd":"echo hi"}'
``
Without
enable_ctx_exports, ctx.exports is undefined; without the re-export, WorkspaceServiceProxy itself is missing. Both mistakes produce the same misleading error. This was observed with @cloudflare/computer@0.2.0, wrangler@4.123.0, and workerd@1.20260811.1`.TroubleshootingHow to fix the @cloudflare/computer `edit` tool rewriting the whole file and stripping smart quotes, dashes, or trailing whitespace when `oldText` does not match exactly?
Root cause: when exact matching fails, applyEditsToNormalizedContent in packages/computer/src/tools/fs/edit-diff.ts matches against a fuzzy-normalized copy, but incorrectly uses that normalized copy as baseContent for both the write and diff. Therefore unrelated Unicode punctuation and trailing whitespace are flattened.
Immediate workaround: make oldText byte-for-byte exact. Remove accidental trailing spaces and preserve smart quotes (U+201C/U+201D), em dashes (U+2014), and the file's Unicode normalization. For the reproduction, change:
oldText: "let target = 1; "
to:
oldText: "let target = 1;"
Inspect invisible characters with sed -n l path/to/file or od -c path/to/file.
Permanent fix: keep the normalized content only for matching, maintain a source-offset map from normalized characters back to the original file, splice replacements into the original content, and generate the diff from original versus edited content. Reject ambiguous mappings, such as Unicode normalization merging characters or a match covering only part of an expanded ligature. This is implemented by the PR fix: preserve files during fuzzy edits (#51).
Affected version: @cloudflare/computer 0.1.0-alpha.1 at commit 76d9e75. Validate with:
npm test --workspace @cloudflare/computer -- src/tools/fs/repro.test.tsTroubleshootingWhy does the Worker JavaScript capability size error show a literal ${maxCapabilityBytes} instead of the configured byte limit?
The limit is interpolated in the size comparison, but the error message is generated as a plain double-quoted string, so ${maxCapabilityBytes} is not replaced. Fix capabilitiesModule() in packages/computer/src/backends/worker-javascript/module-graph.ts by inserting the configured value when generating the module, for example: throw new Error(${JSON.stringify(Workspace capability request exceeds ${maxCapabilityBytes} bytes.)});. With maxCapabilityBytes: 256, the generated runtime code must become: throw new Error("Workspace capability request exceeds 256 bytes.");. Rebuild or regenerate the Worker module and redeploy. If available, update to a release containing PR #99 instead of patching manually.
TroubleshootingWhy did the Cap'n Web WebSocket endpoint move from /ws to /api in computerd 0.3.0?
In computerd 0.3.0, the Cap'n Web endpoint was consolidated: use /api for WebSocket connections instead of /ws. The server distinguishes a WebSocket request from an HTTP request by the GET request with Upgrade headers. The old /ws path was removed. Note that HTTP batch support was also removed in 0.3.0 because it could not connect to streams returned from RPC calls after the streams migration.
TroubleshootingWhy does Workspace.fs expose symlink(), readlink(), lstat(), and chmod() when the documentation says symbolic links are internal?
The documentation is outdated. In the shipped API, these methods are intentionally public on WorkspaceFilesystem and are mirrored across the Workers RPC boundary by WorkspaceFilesystemStub.
Use them as the Promise-based filesystem API:
await workspace.fs.symlink(targetPath, linkPath);
const target = await workspace.fs.readlink(linkPath);
const linkStats = await workspace.fs.lstat(linkPath);
await workspace.fs.chmod(filePath, 0o644);
stat() follows a trailing symbolic link and reports the target, while lstat() reports the link itself. Relevant errors include ENOENT for a missing path, EINVAL for an invalid argument or operation, and ELOOP when too many symbolic links are encountered.
The fix is to update docs/04_filesystem_interface.md to document symlink, readlink, lstat, and chmod, and remove the claim that symbolic links are internal only. Removing these methods would be a breaking API change.