Wrangler 4.109 ships an alpha 'turnstile widget create/list/get/update/
delete' subcommand tree that talks to the same Cloudflare API as the
bundled widget-create.sh helper. When wrangler is installed with the
turnstile subcommand available, use it directly; otherwise fall back to
the curl-based script. Also updates Step 2 (CLI check) to name the
preference explicitly.
Server-side, dashboard-created widgets tag deployed_via=dashboard,
wrangler-created widgets tag deployed_via=wrangler, and curl-script
widgets tag deployed_via=api. The agent only needs to write the
turnstile-spin-v2 marker; the deployment channel is inferred from the
User-Agent/host on the create call.
Remove hardcoded "what's supported / not supported" boxes and any
"docs lag the engine" framing from the data-platform references.
The skills now treat the Cloudflare docs as authoritative and point
the agent to the SQL reference, limitations, and troubleshooting pages
for feature support. Keeps code templates, connection values, and
operational gotchas.
Address review feedback: reduce hardcoded prose and drift-prone content
(exhaustive function catalogs, limits, settings tables) in favor of
documentation pointers the agent should pull via the cloudflare-docs
MCP or webfetch. Each reference keeps code examples, templates, the
verified API details/endpoints, and the corrections where docs are
wrong (catalog URI/warehouse format, R2 SQL JOIN/window support).
Adds a "Documentation (pull latest)" link map to each README.
Rewrite the three data-platform references in the cloudflare skill to
match the current state of the products (verified live, June 2026).
Key corrections:
- Catalog URI is https://catalog.cloudflarestorage.com/{ACCOUNT_ID}/{BUCKET}
and warehouse is {ACCOUNT_ID}_{BUCKET} (old iceberg/ path form was wrong)
- R2 SQL endpoint is api.sql.cloudflarestorage.com/api/v1/.../r2-sql/query
- R2 SQL now supports JOINs, subqueries, CTEs, UNION/INTERSECT/EXCEPT,
SELECT DISTINCT, and the full window-function set + QUALIFY (verified);
OFFSET and the named WINDOW clause remain unsupported
- R2 Data Catalog compaction has no hard throughput cap (former 2GB/hour
limit lifted); snapshot expiration now removes unreferenced data files
- Document the new get-table control-plane API
- Pipelines: REST vs CLI field-name differences, pipeline->stream binding
rename, Logpush source, Terraform, lifecycle states, GraphQL observability
Also remove a stray SKILL.md.backup file and add R2 Data Catalog / R2 SQL
to the SKILL.md storage and analytics decision trees.
This skill stays as the v1 agent-led path; the dashboard's 'Set up with
Spin' button is the v2 parallel path. Two small SKILL.md prose edits so
the agent does the right thing when it encounters a v2-created widget:
- Recovery flow: dashboard's Deployment column flips on either v1 or
v2 marker. If the user is recovering a dashboard-created widget, a
Worker is likely already deployed in the account; confirm before
redeploying, or skip to Step 10 to wire the frontend against the
existing Worker URL.
- Telemetry marker: this skill always writes v1, but preserve v2 if
you encounter it on an existing widget. Both feed the same
account-level activation telemetry.
No changes to scripts, references, templates, or tests. Fresh widgets
created via this skill keep the turnstile-spin-v1 marker.
Co-authored-by: jules lemee <jules@cloudflare.com>
This skill stays as the v1 agent-led path; the dashboard's 'Set up with
Spin' button is the v2 parallel path. Two small SKILL.md prose edits so
the agent does the right thing when it encounters a v2-created widget:
- Recovery flow: dashboard's Deployment column flips on either v1 or
v2 marker. If the user is recovering a dashboard-created widget, a
Worker is likely already deployed in the account; confirm before
redeploying, or skip to Step 10 to wire the frontend against the
existing Worker URL.
- Telemetry marker: this skill always writes v1, but preserve v2 if
you encounter it on an existing widget. Both feed the same
account-level activation telemetry.
No changes to scripts, references, templates, or tests. Fresh widgets
created via this skill keep the turnstile-spin-v1 marker.
* Add Turnstile Spin skill
Adds an agent skill at skills/turnstile-spin/ that scaffolds Cloudflare Turnstile end-to-end: scan the codebase, create the widget via the Cloudflare API, deploy the managed siteverify Worker (template bundled at skills/turnstile-spin/templates/worker/), write the frontend snippets, and validate the integration.
Every emitted widget carries action='turnstile-spin-v1' for analytics segmentation.
Mirrors developers.cloudflare.com/turnstile/spin/.
* Refactor turnstile-spin skill: extract deterministic logic to scripts/
Per maintainer feedback (cf https://github.com/cloudflare/skills/pull/58),
SKILL.md is now a thin orchestration layer (~160 LoC, down from ~500)
and the deterministic API calls + retry logic live in 6 helper scripts:
- scripts/auth-probe.sh: token + scope + account-mismatch detection
- scripts/widget-create.sh: Cloudflare API widget creation
- scripts/worker-deploy.sh: degit + wrangler deploy + secret put + retry on name conflict
- scripts/validate.sh: health + dummy-siteverify + hostname-domains end-to-end checks
- scripts/persist-skill.sh: fetch canonical SKILL.md with HTTP 200 + frontmatter validation
- scripts/fetch-secret.sh: recovery-flow secret retrieval via API
Each script outputs structured JSON; the agent branches on the status field
instead of parsing prose. The conversational flow, hard scope boundaries,
recovery decision tree, and CAPTCHA-migration logic remain in SKILL.md
since those are agent-behavior policy, not API mechanics.
* fix(turnstile-spin): multi-account auth probe, Workers scope check, set_secret failure handling
- auth-probe.sh now handles multi-account tokens: emits multiple_accounts
when >1 accounts and CLOUDFLARE_ACCOUNT_ID is unset, checks membership
(not [0] equality) when the env var is set
- auth-probe.sh probes GET /workers/scripts after GET /challenges/widgets
so a token missing Account.Workers Scripts:Edit fails before the agent
creates a widget (irreversible) and then tries to deploy
- worker-deploy.sh makes set_secret failure fatal: previously the script
could emit status:ok with the Worker deployed but TURNSTILE_SECRET_KEY
unset
- SKILL.md Step 3 documents the new statuses (multiple_accounts,
missing_workers_scope) and the re-run loop after the user picks an
account
- SKILL.md Step 9 documents the set_secret_failed recovery path
* fix(turnstile-spin): capture both stdout and stderr in worker-deploy
Wrangler emits the deployed Worker URL on stdout (progress indicators on
stderr). The script captured only stderr and then grepped that file for
the URL, so successful deploys could still emit url_parse_failed.
Capture both streams.
* fix(turnstile-spin): comprehensive sweep before reviewer round 3
Addresses 14 issues found in an internal adversarial review:
Scripts:
- auth-probe.sh: reword Workers scope comment (best-effort proxy,
not a guarantee that Read implies Edit).
- worker-deploy.sh: URL parser falls back from workers.dev regex
to a broader match for custom domains and Workers for Platforms.
set_secret failure now captures wrangler stderr into a temp file
and includes a detail field in the error JSON instead of
swallowing the diagnostic.
- fetch-secret.sh: emit clearance_level and domains so the recovery
flow's pre-clearance check is implementable. Without these the
contract was documentation theatre.
- validate.sh: hit /health (not /); the diagnostic was lying about
the path. Also assert _worker metadata is present in the dummy
siteverify response (Step 7b promised this; the script never
checked).
- persist-skill.sh: install canonical bundle (SKILL.md + scripts/ +
references/ + templates/) via degit from cloudflare/skills
instead of writing the inlined bootstrap index.md. Persisted
skills now re-run without the /tmp/ bootstrap path.
SKILL.md:
- Recovery flow uses fetch-secret.sh's new clearance_level and
domains fields. Drops the ?widget=<id> URL trigger (nothing
parsed it; it was documentation theatre). Recovery is now
invoked verbally.
- Edge case table replaces $WORKER_NAME env var references with
the worker_name field returned by worker-deploy.sh.
- Adds explicit set_secret_failed recovery row.
Worker template:
- parseBody accepts the reCAPTCHA-style `response` field name
alongside `token` and `cf-turnstile-response`, so backends
migrated from reCAPTCHA/hCaptcha work without backend code
changes (drop the secret field, keep the rest).
* fix(turnstile-spin): match docs on suffix entropy + scope parallel-work hint
- worker-deploy.sh now uses openssl rand -hex 3 for the
name-conflict retry suffix, falling back to the previous date
tail if openssl is absent. The docs prose already called this a
hash; the script body now matches.
- SKILL.md Step 3's parallel-work hint is conditional on option 3
(paste in chat). Options 1 and 2 restart the session and lose any
pre-fetched scan state, so the agent no longer pre-fetches in
those cases.
---------
Co-authored-by: jules lemee <jules@cloudflare.com>
* Add Flagship feature flags skill to cloudflare mega-skill
Add reference files for Cloudflare Flagship (feature flag service) under
skills/cloudflare/references/flagship/ following the standard 5-file
structure (README, api, configuration, patterns, gotchas).
Covers:
- Binding API for Workers (env.FLAGS)
- OpenFeature SDK (server + client providers)
- REST API for flag management (CRUD, toggle, targeting rules, rollouts)
- FlagDefinition schema, operators, conditions, rate limits
- Progressive rollout workflows and safe deletion patterns
Also updates the cloudflare mega-skill SKILL.md with a feature flags
decision tree and product index entry.
* fix(cloudflare): remove overly specific Flagship details from skill description
Even when using the Wrangler Skill — I'm seeing that agents (Ex: Codex, via the Cloudflare Plugin) will first go off and call the MCP server to understand the shape of the REST API for Workers — and even attempt to deploy code by manually constructing API requests.
It eventually figures out it needs Wrangler — but it should _start_ here and just always use Wrangler.
This change more explicitly guides the agent to use Wrangler.
* Update cloudflare-email-service skill to match latest docs
Sync skill with updated Cloudflare Email Service documentation:
- Fix REST API endpoint from /email-service/send to /email/sending/send
- Update REST API field names (address vs email, reply_to vs replyTo)
- Update REST API response format (delivered/permanent_bounces/queued)
- Add public beta notice and known limitations
- Add Legacy EmailMessage API section
- Add ForwardableEmailMessage interface with canBeForwarded
- Add suppression lists documentation (global + account)
- Add platform limits table
- Update error codes (add E_RECIPIENT_NOT_ALLOWED, E_HEADER_VALUE_INVALID)
- Add env.EMAIL.send() as recommended reply method for routing
* Trim skill from 2,739 to ~1,000 lines
- Remove Python, Go, Node.js SDK examples (SDKs not ready), keep curl only
- Cut overlapping examples (invoice processing, D1 tracking, magic link, AI agent)
- Reduce wrangler CLI examples, point to docs and --help
- Condense routing, deliverability, and cli-and-mcp references
- Keep all essential API details, error codes, and gotchas
* Add deliverability monitoring, MCP usage, and inline attachments; consolidate reference files
- Add monitoring section to deliverability.md: dashboard, sending limits,
suppression list API, zone-level GraphQL analytics (emailSendingAdaptiveGroups,
emailSendingAdaptive) verified against production schema
- Update cli-and-mcp.md with Cloudflare MCP server search/execute examples
for email endpoints
- Add inline attachment docs (content_id, disposition: "inline") to rest-api.md
- Fix attachment content handling in sending.md (raw string/ArrayBuffer for
Workers binding vs base64 for REST API)
- Move error codes table from SKILL.md to sending.md where it belongs
- Add "Store and Reply Later" pattern to routing.md
- Remove examples.md (consolidated into other references)
- Trim SKILL.md: remove duplicated limits, prerequisites, error codes
Replace legacy building-* guides with a consolidated agents-sdk skill: update SKILL.md to expand capabilities and retrieval links, add multiple new reference pages (client-sdk, configuration, durable-execution, browse-the-web, human-in-the-loop, observability, queue-retries, routing, server-driven-messages, and others), and update command docs (build-agent.md, build-mcp.md) to point to the agents-sdk pages and include scaffold examples. Remove deprecated building-ai-agent-on-cloudflare and building-mcp-server-on-cloudflare content. These changes centralize documentation around the Agents SDK, add scaffold/snippet guidance, and refresh links to the live Cloudflare developer docs.
Address Snyk W007 (HIGH) finding for insecure credential handling.
- Remove `echo "secret-value" | wrangler secret put` pattern; use interactive
prompt as primary method and file redirect for CI
- Replace hardcoded connection string `postgres://user:pass@...` with env var
reference `$HYPERDRIVE_CONNECTION_STRING` and individual params
- Replace `--origin-password "new-password"` with `$DB_PASSWORD` env var
- Fix incorrect `--public-credential` flag to actual wrangler flags
(`--aws-access-key-id`, `--dockerhub-username`) with env var references
- Add security callout blocks in Secrets and Container Registries sections
- Add best practice #9: never embed secrets in commands
* Add GraphQL Analytics API reference skill
New reference covering Cloudflare's GraphQL Analytics API — the single
endpoint for querying analytics across all Cloudflare products (HTTP,
Workers, DNS, Firewall, R2, KV, D1, AI, and 70+ other datasets).
New files:
- references/graphql-api/README.md — Overview, decision tree, dataset
index, naming conventions, reading order
- references/graphql-api/api.md — Query structure, aggregation fields
(sum/avg/quantiles/count/ratio/uniq/confidence), dimensions, filtering
operators, pagination, sorting, introspection, settings node
- references/graphql-api/configuration.md — Auth (API tokens), client
setup (curl, TypeScript, Python, Workers), GraphQL Explorer, schema
introspection, finding zone/account IDs
- references/graphql-api/patterns.md — 15+ ready-to-use query patterns:
time-series, top-N, Workers performance, firewall events, DNS, cache
analytics, R2/KV/D1 storage, AI inference, multi-dataset dashboards
- references/graphql-api/gotchas.md — Rate limits, ABR sampling caveats,
common errors (with solutions), plan-based availability, datetime
handling, performance tips
Modified files:
- SKILL.md — Added analytics/metrics decision tree, added GraphQL API
entry to Developer Tools product index
- analytics-engine/README.md — Added See Also cross-links to graphql-api
and observability references
- api/README.md — Added See Also cross-link to graphql-api reference
- observability/README.md — Added See Also cross-link to graphql-api
- web-analytics/README.md — Added reciprocal cross-link to graphql-api
Testing:
- Thorough human review (read-through of each file)
- Two comprehensive AI reviews using parallel subagents for factual
accuracy, completeness, and style — followed by a validation pass that
filtered false positives. Caught and fixed 8 issues:
- Settings node query was structurally invalid (missing dataset nesting)
- R2 query pattern used nonexistent count field (only sum/dimensions/
confidence exist on r2OperationsAdaptiveGroups)
- Worker example in configuration.md was missing datetime_lt upper
bound, contradicting the skill's own best practice
- Confidence interval example included undocumented isValid field
- Rate limit described as flat 300/5min; corrected to cost-based
default 300, max 320
- Separator convention (-- vs -) mismatched peer references; fixed
across all 5 files
- web-analytics/ was missing reciprocal cross-link
- _notin/_notlike operators initially removed as undocumented, then
re-added after schema introspection confirmed they exist (with note)
- 20 GraphQL queries executed against a live Cloudflare account covering:
zone-scoped (HTTP time-series, top-N countries/paths/errors, firewall
events/blocks, DNS volume, cache breakdown, multi-dataset dashboard,
confidence intervals, daily rollups with uniq, _like filter, _notin
filter, aliases) and account-scoped (Workers overview/error-rate with
quantiles, KV operations, R2 operations, settings node, cost/budget).
19/20 passed on first attempt; the 1 failure (R2 count) was fixed.
* Trim graphql-api reference files to ~200 lines each per review feedback