Select with provider: cloudflare-dynamic-workers (aliases cf-dynamic and
cfdw) to run Cloudflare Workers module source through Cloudflare Dynamic
Workers. This is a delegated-run provider with target=worker-runtime: the
local CLI sends a JavaScript, CommonJS, or Python module to a deployed Crabbox
loader Worker, the loader creates or reuses a Dynamic Worker, invokes its
fetch handler, and returns the result. There is no Linux host and no SSH lease.
Use the separate Cloudflare provider when you need Cloudflare Containers and Linux command execution.
- Target:
worker-runtime. - Supported commands:
run,status,stop,list,doctor, and local-claimcleanup. - Run input:
--script <file>for JavaScript, CommonJS, or Python modules;--script-stdinfor JavaScript module source. - Coordinator: never brokered. The CLI talks directly to the loader Worker.
- Cache modes:
one-shot,stable, andexplicit. - Egress modes:
blockedby default, orinterceptwhen the loader exports the gateway bindings required by the Worker runner. - Not supported: trailing
-- <command>argv,--shell, POSIX shell, SSH, rsync, archive sync, VNC, browser desktop, code-server, port forwarding, Actions hydration, artifact download,--fresh-pr,--checksum,--class, and--type.
- A Cloudflare Workers account with Dynamic Workers enabled for the target account.
- Wrangler authenticated for that account.
- The deployed Crabbox Dynamic Workers loader from
worker/wrangler.cloudflare-dynamic-workers.jsonc. - A Workers KV namespace bound as
RUNSfor retained terminal metadata and upgrade compatibility. - A Durable Object binding named
RUN_COORDINATORusingDynamicWorkerRunCoordinatorfor atomic run lifecycle coordination, authoritative status, and the run index used bylist --refresh. - The Worker secret
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN. - CLI-side
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_URLandCRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN.
The Worker entrypoint is worker/src/cloudflare-dynamic-worker-runner.ts. It is
separate from the Cloudflare Containers runner and uses a worker_loaders
binding named LOADER, a Workers KV namespace binding named RUNS, and a
Durable Object binding named RUN_COORDINATOR. Python modules automatically
enable Cloudflare's required python_workers compatibility flag.
Keep the loader URL and bearer token in trusted user config or environment; the loader URL also has a CLI flag. Repository config can select the provider and blocked runtime settings, but cannot replace the loader connection or enable intercepted network egress:
provider: cloudflare-dynamic-workers
target: worker-runtime
cloudflareDynamicWorkers:
compatibilityDate: "2026-06-12"
compatibilityFlags:
- nodejs_compat
cacheMode: stable
egress: blocked
cpuMs: 50
subrequests: 12
timeoutSecs: 30Config keys map to the typed cloudflareDynamicWorkers section:
loaderUrl, token, compatibilityDate, compatibilityFlags, cacheMode,
egress, cpuMs, subrequests, timeoutSecs, and metadata.
| Setting | Config key | Environment variable | Flag |
|---|---|---|---|
| Loader URL | loaderUrl |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_URL |
--cloudflare-dynamic-workers-url |
| Loader URL alias | loaderUrl |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_LOADER_URL |
--cloudflare-dynamic-workers-url |
| Token | token |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN |
(none, by design) |
| Compatibility date | compatibilityDate |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_COMPATIBILITY_DATE |
--cloudflare-dynamic-workers-compatibility-date |
| Compatibility flags | compatibilityFlags |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_COMPATIBILITY_FLAGS |
--cloudflare-dynamic-workers-compatibility-flags |
| Cache mode | cacheMode |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_CACHE_MODE |
--cloudflare-dynamic-workers-cache |
| Egress mode | egress |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_EGRESS |
--cloudflare-dynamic-workers-egress |
| CPU limit | cpuMs |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_CPU_MS |
--cloudflare-dynamic-workers-cpu-ms |
| Subrequest limit | subrequests |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_SUBREQUESTS |
--cloudflare-dynamic-workers-subrequests |
| Loader timeout | timeoutSecs |
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TIMEOUT_SECS |
--cloudflare-dynamic-workers-timeout-secs |
The token is intentionally not exposed as a command-line flag because command
arguments can appear in shell history and process listings. Repository-local
config cannot override loaderUrl or token, and cannot change egress from
blocked to intercept. Repository-local cpuMs, subrequests, and
timeoutSecs values can tighten trusted limits but cannot loosen them.
Install dependencies and verify the Worker before deploy:
npm ci --prefix worker
npm run check --prefix worker
npm run build:cloudflare-dynamic-workers --prefix workerSet the loader bearer token as a Worker secret through stdin:
printf '%s' "$CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN" \
| npx wrangler secret put CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN \
--config worker/wrangler.cloudflare-dynamic-workers.jsoncCreate a KV namespace for run metadata and replace the placeholder RUNS
namespace IDs in worker/wrangler.cloudflare-dynamic-workers.jsonc before live
deploy:
npx wrangler kv namespace create crabbox-cloudflare-dynamic-workers-runs
npx wrangler kv namespace create crabbox-cloudflare-dynamic-workers-runs-preview --previewDeploy the Dynamic Workers loader:
npm run deploy:cloudflare-dynamic-workers --prefix workerCheck readiness without creating a Dynamic Worker:
crabbox doctor --provider cloudflare-dynamic-workersDynamic Workers run Worker module source, not shell commands:
export default {
async fetch() {
return new Response("hello from dynamic workers");
},
};Run the module from a file:
crabbox run \
--provider cloudflare-dynamic-workers \
--script ./worker-smoke.mjs \
--timing-jsonOr send source on stdin:
printf '%s\n' 'export default { fetch() { return new Response("ok") } }' \
| crabbox run --provider cfdw --script-stdinTrailing command argv is rejected because there is no POSIX shell:
crabbox run --provider cloudflare-dynamic-workers -- echo not-supportedcacheMode controls how the loader identifies Dynamic Workers:
one-shotcreates an uncached one-off run.stableuses a stable ID derived from module source and runtime settings so repeated same-code runs can reuse Cloudflare's Dynamic Worker cache. Each invocation receives a separate run ID for lifecycle metadata.explicitrequires--idand is the mode to use when an operator wants a named Worker cache identity. Each invocation still receives a unique run ID forstatus,list, andstop; Crabbox prints that lifecycle ID alongside the named Worker ID. Reuse the explicit ID only with identical module source and runtime settings.
Cloudflare bills Dynamic Workers according to the platform's current pricing and limits. Stable IDs can improve repeat-run startup behavior, but they should be treated as a cache key, not as durable user data.
The default egress mode is blocked. In blocked mode the loader does not wire
an outbound gateway into the Dynamic Worker. intercept mode routes outbound
fetches through the loader's HttpGateway and LogTailer exports when the live
Cloudflare runtime supports those bindings. Because those bindings contain
run-scoped context, intercept requires cacheMode: one-shot.
Use cpuMs, subrequests, and timeoutSecs to bound execution. These are
runtime limits for a module invocation, not VM sizing knobs; --class and
--type are rejected for this provider.
statusresolves a local claim or explicit run ID and asks the loader for run metadata.listreports local Dynamic Workers claims. Add--refreshto query loader metadata for each claim.stopdeletes terminal loader metadata and removes the local claim. Active runs cannot be stopped because the loader cannot cancel an in-flight Dynamic Worker invocation; wait for completion first. If the loader reports the run is missing, Crabbox removes the stale local claim.cleanupchecks local claims and removes stale claims whose loader metadata is missing or terminal.--dry-runprints the same decisions without removing local state.
Completed non-kept runs remove their loader metadata automatically. Use --keep,
--keep-on-failure, or cacheMode: explicit when lifecycle inspection must
remain available after the invocation.
Cleanup is local-claim cleanup. It is not a global Cloudflare account inventory sweeper.
The live smoke harness is opt-in and non-mutating by default:
scripts/deploy-cloudflare-dynamic-workers-smoke.shWithout explicit gates it exits successfully with:
environment_blocked provider=cloudflare-dynamic-workers mutation=false reason=live_gate_missing
To allow live deploy and smoke, set both gates and the required Cloudflare account:
export CRABBOX_LIVE=1
export CRABBOX_LIVE_PROVIDERS=cloudflare-dynamic-workers
export CLOUDFLARE_ACCOUNT_ID=...
scripts/deploy-cloudflare-dynamic-workers-smoke.shWrangler may authenticate from its existing login or CLOUDFLARE_API_TOKEN.
The harness generates an ephemeral runner token when none is supplied, creates
a uniquely named KV namespace, deploys a uniquely named Worker, derives its
workers.dev URL, and removes both resources on exit. Set
CRABBOX_CFDW_SKIP_DEPLOY=1 plus
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_URL and
CRABBOX_CLOUDFLARE_DYNAMIC_WORKERS_TOKEN to exercise an existing deployment.
The script classifies the result as one of:
environment_blocked— gates, local tools, dependencies, or runtime setup are unavailable, and no live success is claimed.auth_blocked— required credentials are missing or rejected.quota_blocked— Cloudflare plan, quota, limit, or billing capacity prevents deploy or run.live_cloudflare_dynamic_workers_smoke_passed— deploy, doctor, run, status, list, stop, and cleanup completed.
The script never prints token values. It passes the runner token through a mode-0600 temporary secrets file and removes the file during cleanup.
- Dynamic Workers execute Worker-runtime module source only.
- TypeScript must be transpiled to JavaScript before upload.
warmupis unsupported because a Dynamic Worker cannot be loaded or cached without module source; userun --script.- There is no Linux shell, SSH target, filesystem sync, archive upload, VNC, browser desktop, code-server, port forwarding, or Actions hydration.
--download,--fresh-pr,--artifact-glob,--require-artifact,--checksum,--class, and--typeare unsupported.interceptegress requires loader exports and Cloudflare runtime support.- Local
listandcleanupare claim-based; they do not enumerate every Dynamic Worker in the Cloudflare account.