Quickstart
Run your own Apps on Cloudflare Workers or celld: installable App Releases, each with its own Durable Object, SQLite database and declared bindings
Deciding what to run? Is Oyster for you? compares agent Computers and App builds with Cloudflare Workers Builds.
You need:
- a Cloudflare account on Workers Paid, with Containers, Artifacts, Workers AI, Workflows and Browser Rendering (now called Browser Run) enabled;
- Docker, which Wrangler uses to build the Computer’s container image;
- Node 24, pnpm 11 or newer and Git.
The first install takes about 15 to 20 minutes, mostly building the seven Apps on the Computer. By default, Oyster builds two Apps at a time. Start a project, add Oyster, its Computer and Wrangler, and copy the example Worker out of the package. The local pnpm policy allows esbuild and workerd to install their native binaries and disables unneeded optional dependency scripts, so a fresh install exits successfully:
mkdir my-oyster && cd my-oystercat > pnpm-workspace.yaml <<'YAML'allowBuilds: "@google/genai": false "@mongodb-js/zstd": false esbuild: true exifreader: false node-liblzma: false protobufjs: false workerd: trueYAMLpnpm add @fungi.computer/oyster @fungi.computer/computer react@^19.2.0 react-dom@^19.2.0pnpm add -D wranglercp node_modules/@fungi.computer/oyster/examples/standalone/{worker.ts,wrangler.jsonc} .If pnpm add reports ERR_PNPM_IGNORED_BUILDS, check that the policy file
above exists before installing. If it names a new dependency not listed there,
stop and review that package before allowing its scripts. Do not treat exit 1 as
success.
worker.ts re-exports the whole host:
export * from "@fungi.computer/oyster/standalone";export { default } from "@fungi.computer/oyster/standalone";wrangler.jsonc names the Worker oyster, its Release bucket oyster-releases
and its Artifacts namespace oyster, and runs the Computer from
node_modules/@fungi.computer/computer/Dockerfile. Its
"browser": { "binding": "BROWSER" } enables Cloudflare Browser Rendering for
the zero-grant UI boot check and for Agents’ browser tool. Without the binding
the UI of a Release is reported not_checked with
code: "boot_browser_binding_missing"; the install still proceeds.
Create the bucket and deploy. Your Worker’s address is
https://oyster.<your-subdomain>.workers.dev; your workers.dev subdomain is on
the Workers & Pages overview in the Cloudflare dashboard.
npx wrangler loginnpx wrangler r2 bucket create oyster-releasesexport OYSTER_URL=https://oyster.<your-subdomain>.workers.devnpx wrangler deploy --var OYSTER_ORIGIN:$OYSTER_URLSet OYSTER_ORIGIN in wrangler.jsonc instead if you deploy again later; every
deploy replaces the Worker’s variables. If you rename the Worker’s name in
wrangler.jsonc, update OYSTER_ORIGIN to that Worker’s URL at the same time.
API-token permissions and teardown
Section titled “API-token permissions and teardown”For an API token instead of wrangler login, load CLOUDFLARE_API_TOKEN into
your shell without committing it. Set CLOUDFLARE_ACCOUNT_ID (or account_id
in wrangler.jsonc) explicitly, and skip the login command. Use Wrangler
4.135.0 or newer; record npx wrangler --version for deployment and teardown.
The Cloudflare API specification names these account-scoped permission groups for the deployment and resource deletion operations:
| Permission group | Used for |
|---|---|
| Workers Scripts Write | Deploy, secrets, Worker deletion and Workflow deletion |
| Workers R2 Storage Write | Release bucket creation, object cleanup and bucket deletion |
| Workers Containers Write | Computer container application management |
| Artifacts Edit | Artifacts namespace and repository management |
Browser Rendering through the Workers BROWSER binding
needs no additional API-token permission.
The separate Browser Rendering Write permission is for its REST API, which this
quick start does not use. Workers Paid entitlement is still required.
For stream-rehearsal diagnostics, include Browser Rendering (Read) in the
account-scoped token checklist: it permits REST session inspection, separate
from the BROWSER binding’s boot operation. Use the documented
/browser-rendering/devtools/session list and devtools/session/{session_id}
details operations; a session’s endTime, not its connection end time, reports
closure. A plain 404 from another route does not establish a missing permission.
If inspection is unavailable, record UNAVAILABLE, not confirmed cleanup. Do
not broaden an existing token automatically.
With an explicit account ID, user/account discovery is unnecessary. Do not add
Workers KV Storage Read, User Details Read or Memberships Read just for that
discovery. Wrangler 4.135.0 treats denied legacy-Sites KV inspection during
wrangler delete as a warning, not a reason to broaden this token. AI Gateway
Read/Edit permissions are not needed for this deploy or a teardown before any
media ran; inspect that additional resource if media has created a gateway.
npx wrangler delete deletes the Worker, not the entire Oyster. For a throwaway
deployment, also empty and delete the Release bucket, delete the Computer’s
container application, delete the Workflow, and delete the Artifacts
repositories and namespace. Use the configured resource names and confirm each
is gone through Cloudflare’s dashboard or API. Capture teardown errors and the
Wrangler version rather than silently adding unrelated token permissions.
Upgrading from Oyster 0.2 or earlier
Section titled “Upgrading from Oyster 0.2 or earlier”Oyster 0.3 does not read data created by Oyster 0.1 or 0.2, and it does not
convert it. An Oyster deployed on 0.2 and redeployed on 0.3 answers every
request with 409 and {"error": "store_from_older_oyster", ...} (a short
explanation page in a browser), and oyster install-apps prints the same
message. Old data is left untouched, so redeploying 0.2.x brings the Oyster back
exactly as it was.
To move to 0.3, start from a fresh store. The smallest way is to deploy under
new names, leaving the old Oyster in place until you no longer need it. In
wrangler.jsonc, rename name, both bucket_name values,
artifacts.namespace and every workflows[].name; create the new release
bucket; then run the quick start again. To reuse the names instead, tear the old
Oyster down as in the teardown steps above (delete the Worker, which deletes its
Durable Object data; empty and delete the release bucket; delete the Computer’s
container application, the Workflow, and the Artifacts repositories and
namespace), then deploy 0.3 and reinstall the Apps. Data in the old Oyster, such
as Apps’ stored data, is not carried over.
Set the Oyster owner key
Section titled “Set the Oyster owner key”Choose an owner key (separate from the Cloudflare API token) and store it as a secret:
export OYSTER_OWNER_KEY=$(openssl rand -hex 24)printf '%s' "$OYSTER_OWNER_KEY" | npx wrangler secret put OYSTER_OWNER_KEYInstall the starter Apps
Section titled “Install the starter Apps”npx oyster install-appsThe installer clones each App’s repository, seeds it on your Oyster with
git push, and builds the Apps on your Computer, Tourtois first, installing
each as its build succeeds. It prints a line per step and then where the time
went:
tourtois source recorded at git:……Building tourtois on the Computer (build_…)Installed tourtois from its build build_…Building bonsai on the Computer (build_…)…Installed grove from its build build_…
App fetch seed queue build clone deps compile upload installtourtois ……Installed 7 Apps in …. Open https://oyster.<your-subdomain>.workers.dev/ to use Tourtois and the installed Apps.Open $OYSTER_URL/login and sign in with the owner key: your Oyster opens on
the Tourtois desktop with all seven Apps, as in the pictures above.
Run install-apps again to update them; a replaced Release keeps each App’s
data. --ref picks a branch or tag of the App repositories, --repositories
another host for them, and --timings <file> writes the timing table as JSON.
Builds run two at a time on the example’s standard-4 Computer (12 GiB).
--concurrency 1 runs them one at a time and --concurrency 3 three at once.
Git, keys and MCP
Section titled “Git, keys and MCP”People and agents clone, fetch and push App repositories with ordinary
git at /git/<installation>/<repo>.git. Give each agent its own key; Oyster
shows each key once:
curl -s -X POST -H "Authorization: Bearer $OYSTER_OWNER_KEY" \ -H 'content-type: application/json' \ -d '{"name":"morel","grants":[{"capability":"apps.use","targets":{"kind":"all"}}]}' \ $OYSTER_URL/api/keysThe answer’s plaintext field, starting oyk_, signs in to git and to
/mcp. That key can read and write every App on this Oyster, including Apps
installed later, without asking each time; anyone holding it can act as the
owner in those Apps, and revoking it stops it immediately.
Any MCP client can call every installed App with a key. For Claude Code:
claude mcp add --transport http oyster "$OYSTER_URL/mcp" \ --header "Authorization: Bearer <the agent's key>"What the live demo runs
Section titled “What the live demo runs”https://oyster.shiit.app/ runs this same host with the same seven Apps. Its
koi-pond repository is a small canvas game three coding agents built together,
each in its own fork with its own key, with Bonsai drawing a lane per agent as
they pushed and merged.
CONTEST.md
tours it.