Cloudflare workers
Skill Goodsmileduck/claude-registry/plugins/cloud-platform-skills/skills/cloudflare-workers
Community marketplace of Claude Code plugins: DevOps skill packs (Terraform, Kubernetes, CI/CD, cloud platforms, DigitalOcean), CLAUDE.md optimization, and diagramming — gated by a best-practices lint + security-audit CI.
npx -y skills add Goodsmileduck/claude-registry --skill cloudflare-workersAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Authors and reviews Cloudflare Workers projects — wrangler config (toml/jsonc), bindings (KV, R2, D1, Queues, Durable Objects, service bindings, Vectorize, Workers AI), env-scoped vs root config and the non-inheritable bindings trap, Durable Object migrations (renames, SQLite backend), compatibility_date semantics, static assets and Pages migration, secrets vs vars, cron triggers, observability, and deploy/CI patterns with `cloudflare/wrangler-action`. Use when working with Cloudflare Workers, wrangler.toml/wrangler.jsonc, Workers bindings, Durable Objects, Workers KV/R2/D1/Queues, Workers Static Assets, migrating from Pages to Workers, service bindings or WorkerEntrypoint RPC, or deploying Workers from CI.
SKILL.md
9.4 KB, as published. Nobody here has run it
Cloudflare Workers
When to invoke
Symptoms:
- A binding works in
wrangler devbut isundefinedin production. wrangler deployfails withCannot apply new-class migration to class 'X' that is already depended on by existing Durable ObjectsorClass 'X' cannot be used as a Durable Objectafter a code rename.- A secret value is visible in the Cloudflare dashboard under "Variables" — or worse, committed in
wrangler.toml. - Same hostname has both a Custom Domain and a route pattern, and routing is non-deterministic.
- New Pages project — should it actually be a Worker?
- Two Workers in the same account need to talk; engineer is about to wire it through a public URL.
compatibility_datewas bumped and something started 500-ing.wrangler tailshows the deploy succeeded but the new code isn't running.
The trap this prevents: treating wrangler.toml/wrangler.jsonc as docstring-like config. Several keys are non-inheritable across envs, several have implicit ordering, and the Durable Object migrations array is append-only with strict semantics. Most "it broke in prod" Workers incidents trace to one of these.
Inputs to collect first
| Input | Why | Example |
|---|---|---|
| Account ID | All Workers are account-scoped | dashboard sidebar |
| Worker name | Becomes <name>.<subdomain>.workers.dev and route target | checkout-api |
| Routes vs Custom Domain | Decide before deploying — they conflict on the same hostname | api.example.com/* (route) or api.example.com (custom domain) |
| Bindings list | KV / R2 / D1 / Queues / DOs / services / AI / Vectorize | [{type: kv, id: ...}, {type: do, class: Counter}] |
| Environments | staging, production, ephemeral PR envs | dictates env block structure |
compatibility_date | Behavior pin; not metadata | 2025-05-01, recent but not future |
| Static assets | Yes/no; SPA vs MPA; needs Worker handler? | ./dist, SPA, no |
API token scopes for deploy: see references/recipes/ci-deploy.md for the full per-resource list.
Config format
Use wrangler.jsonc for new projects. wrangler init defaults to it, it supports $schema for IDE autocomplete, and Cloudflare's docs lead with it. wrangler.toml is fully supported — no urgency to migrate.
Add "$schema": "node_modules/wrangler/config-schema.json" at the top of any jsonc file; the IDE will underline unknown keys.
Deep dive: references/recipes/wrangler-config.md.
Hard rules
scripts/validate_wrangler.py flags rules 1–5 statically.
-
Bindings are non-inheritable across envs. (Every binding type.) A populated
env.productionblock fully overrides the root config for non-inheritable keys (vars,kv_namespaces,r2_buckets,d1_databases,queues,durable_objects.bindings,services,routes/route). It does NOT merge. If you set KV at root and only routes underenv.production, production deploys with zero KV bindings — silently. Either repeat per env, or move everything into envs and leave root empty. -
migrationsis append-only and class-name driven. (Durable Objects.) Every class referenced by a DO binding must appear in the cumulativemigrationshistory asnew_classes/new_sqlite_classes/ thetoside ofrenamed_classes. Renames need a new entry with a newtag— never edit a past entry. Switching backends (KV → SQLite) is one-way;new_sqlite_classescannot be downgraded. -
Secrets are not
vars. (All projects.)varsships in plaintext with the deploy bundle and is visible in the dashboard. Anything ending in_KEY/_TOKEN/_SECRET/_PASSWORD/_PASSPHRASEbelongs inwrangler secret put NAME(per env if envs are used). Secrets persist acrosswrangler deploy; vars are overwritten. -
compatibility_dateis behavior, not metadata. Bumping it can changefetchredirect handling,nodejs_compatsemantics, error formatting, and more. Read the changelog before bumping; pin to a date in the past, not the future (deploys reject future dates). -
Custom Domain and route patterns can collide. A Custom Domain attached to
api.example.comAND a[[routes]]pattern matchingapi.example.com/*produce undefined precedence. Pick one per hostname. -
Module syntax only. Service Worker syntax (
addEventListener('fetch', ...)) is deprecated. Newcompatibility_datevalues can refuse it. Useexport default { fetch(req, env, ctx) { ... } }. -
Local
wrangler devuses local bindings. Local KV / R2 / D1 / DO state lives in.wrangler/state/. It diverges silently from production. For real-binding behavior usewrangler dev --remote, or set"remote": trueper-binding in newer Wrangler versions.
Bindings
Each binding type has its own block in the config and its own dev-mode behavior. Per-binding shape, gotchas, and the remote flag for local dev: references/recipes/bindings.md.
Durable Objects
Migrations array gotchas and the SQLite-vs-KV backend choice get a dedicated page: references/recipes/durable-objects.md. The five migration verbs (new_classes, new_sqlite_classes, renamed_classes, deleted_classes, transferred_classes) and tag semantics are easy to get subtly wrong.
Static assets and Pages migration
[assets] block in a Worker now covers what Pages used to. references/recipes/static-assets.md covers the conversion, not_found_handling modes (SPA vs 404 page vs none), run_worker_first for auth interceptors, and DNS coordination during the cutover.
Don't migrate a working Pages project just to migrate — wait for a meaningful change. New projects should pick Workers + Static Assets directly.
CI deploy
references/recipes/ci-deploy.md covers the Workers-specific deploy: cloudflare/wrangler-action, API token scopes, multi-env deploys, environment-scoped secrets, and the --env flag. For OIDC, GITHUB_TOKEN permissions, concurrency, and reusable-workflow posture see the github-actions-pipelines skill — that surface is shared with AWS/GCP deploys and not Workers-specific.
Validator
# Validates wrangler.toml or wrangler.jsonc against the hard rules.
python3 scripts/validate_wrangler.py --config wrangler.jsonc
# --format json for CI; non-zero exit on findings.
Checks: env-override (rule 1), DO migrations coverage (rule 2), secret-shape vars (rule 3), future or missing compatibility_date (rule 4), route/custom_domain hostname overlap (rule 5), and an INFO for missing $schema in jsonc.
Proactive triggers
- User pastes a
wrangler.jsoncwith bindings at root AND a populatedenv.production/env.stagingblock → check whether bindings are repeated per env; flag if not. - User renames a Durable Object class in code without touching
migrations→ flag rule 2 before they try to deploy. - User adds
STRIPE_*/_TOKEN/_SECRETetc. tovars→ suggestwrangler secret put. - User attaches both a Custom Domain and a
[[routes]]pattern to the same hostname → pick one. - User has Worker A about to
fetch('https://worker-b...')for an internal call → suggest service binding + RPC. - User starts a new project with
wrangler.tomland thepages_build_output_dirkey → suggest Workers Static Assets ([assets]block) instead. - User uses
wrangler publishin CI → it's deprecated in favor ofwrangler deploy. - User bumps
compatibility_dateto today and 500s appear → ask which flags they changed.
Verification
-
wrangler deploy --dry-run --outdir=./dist-deploysucceeds and theworker.jslooks right. -
python3 scripts/validate_wrangler.py --config wrangler.jsoncreturns 0 findings. - For each env:
wrangler deploy --env <env> --dry-runsucceeds. -
curl -i https://<worker-route>/<health-path>returns the expected response after deploy. -
wrangler tail --env <env>shows request logs for the production hostname. - If DOs are used:
wrangler deployreports the migration tag applied, not a no-op. - Secrets set per env:
wrangler secret list --env productionlists what you expect.
Old patterns
- Service Worker syntax (
addEventListener('fetch', ...)) — use modules (export default { fetch }). wrangler publish— renamed towrangler deploy. Old command still works but is being removed.- One Pages project per app for new projects — prefer Workers +
[assets]. - Worker → Worker via
fetch('https://other-worker.workers.dev')— use service bindings. - DO classes without
migrations— required since launch; if you see a Worker that "just works" without it, you're looking at one of the legacy bindings. workers_dev = truefor production — fine for staging; in production prefer a Custom Domain or zone route.