NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4709 most downloaded on npm
Command-line interface for all things Cloudflare Workers
Last release 2 days ago
02 Oct 2026
Ships on a steady schedule
a new release about every 9 days
Nearly every release is documented
notes for 60 of the last 60 stable releases
119 versions withdrawn
withdrawn after publishing
14 years old
4955 releases · first in 2012
Container placement constraints now accept constraints.jurisdiction: "us" in Wrangler and typed Cloudflare configuration. This makes the US jurisdicti
#15928 7f57b1c Thanks @ichernetsky-cf! - Allow "us" as a jurisdiction for Container applications
Container placement constraints now accept constraints.jurisdiction: "us" in Wrangler and typed Cloudflare configuration. This makes the US jurisdiction available alongside "eu" and "fedramp".
#15974 7f700ef Thanks @martinezjandrew! - Fix wrangler containers list to report live instances
The LIVE INSTANCES column now reports each application's active runtime instances instead of its configured instance count, matching the Cloudflare dashboard. JSON output continues to expose the configured count through the existing instances field.
#15980 90e6a1b Thanks @martinezjandrew! - Accept Durable Object application IDs in Containers commands
wrangler containers instances and wrangler containers delete now accept the 32-character hexadecimal application IDs returned for Durable Object-backed applications, in addition to legacy dashed UUIDs.
#15871 6a4b0fe Thanks @tw4! - Retry transient API failures in wrangler workflows instances list and wrangler workflows instances describe
Previously, a single temporary 5xx response or dropped connection made these read-only commands exit with an error, even though the next request would have succeeded. They now use Wrangler's existing bounded API retry handling. The read that resolves --id latest is retried too, which also benefits the other wrangler workflows instances commands that accept latest; the mutating requests they make afterwards are not retried. Persistent failures are still reported after the retries are exhausted, and under --json any retry notices are written to stderr so stdout stays valid JSON.
Updated dependencies []:
One column per quarter.
…matching the runtime API while preserving the deprecated array form.
#15777 464a582 Thanks @Naapperas! - Support the new Workflows createBatch() API in local development
Local Workflows bindings now accept object-form batches that create instances from a count or a list of instance options. The result includes handles for created instances and indexed per-instance errors, matching the runtime API while preserving the deprecated array form.
#15639 aee2842 Thanks @hugo-vicente11! - Add --allowed-mail to the experimental wrangler tunnel quick-start command
The option forwards exact email addresses, comma-separated lists, and wildcard domains to cloudflared. It can be specified more than once to combine multiple recipient rules.
Email-protected tunnels require cloudflared 2026.9.2 or later. Wrangler checks the selected binary before starting the tunnel and reports an upgrade error when it is incompatible.
#15992 b8e7cc3 Thanks @zebp! - Mark wrangler artifacts commands as open beta
Artifacts has entered open beta, so the wrangler artifacts commands no longer display a "private beta" label in help output and warnings.
#15984 9d7b08e Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260930.2 | ^5.20261001.1 |
| workerd | 1.20260930.2 | 1.20261001.1 |
#15959 efd67e6 Thanks @breken-ai! - Keep colons in wrangler tail --header filter values
wrangler tail --header splits its argument into a header name and an optional value at the colon. It split at every colon and kept only the first two parts, so a value containing a colon was cut short: --header "Origin:https://app.example.com" filtered on https. The value now includes everything after the first colon, so URLs, ports and IPv6 addresses are sent to the tail filter intact.
Declare the zero-configuration binding in wrangler.json with "analytics": { "binding": "ANALYTICS" } . Wrangler uploads the analytics binding type and
#15685 b9f1cdc Thanks @Ankcorn! - Add native support for the Analytics SQL binding
Declare the zero-configuration binding in wrangler.json with "analytics": { "binding": "ANALYTICS" }. Wrangler uploads the analytics binding type and proxies it to the remote service during local development, so wrangler dev can call the binding without unsafe.bindings.
#15943 8468487 Thanks @sejoker! - Graduate SQL, Catalog, and Pipelines under wrangler basin out of beta to stable
Basin SQL is now available under wrangler basin sql, Basin Catalog operations are available under wrangler basin catalog, and Pipelines operations are available under wrangler basin pipelines. These commands are now stable, while the previous wrangler r2 sql, wrangler r2 bucket catalog, and wrangler pipelines command paths remain available as hidden compatibility aliases.
The Basin SQL authentication environment variable is now WRANGLER_BASIN_SQL_AUTH_TOKEN. Update any existing WRANGLER_R2_SQL_AUTH_TOKEN configuration to use the new name. The fallback to CLOUDFLARE_API_TOKEN remains available.
#15948 a0712e5 Thanks @akoval-cf! - Add beta K2 producer bindings for existing streams
Configure a stream created through Wrangler, the Dashboard, or the API in wrangler.json:
The binding supports env.ORDERS.send([{ content: new TextEncoder().encode("order"), headers: { event: "order.created" } }]). Batches use either all ArrayBuffer or all Uint8Array content. Check the returned success value, handle rejected RPC promises, and retry only when the returned error explicitly allows it. Generated environment types describe this producer contract without requiring a separate application dependency.
K2 requires an enabled account. Deployment credentials need Worker deployment and K2 configuration-read access. Default Wrangler logins now request the K2 OAuth scopes; existing OAuth users should run wrangler login again to grant the new permissions. Development always uses a real K2 stream and may incur usage charges; no local simulator is provided. The remote setting can be omitted, remote: true suppresses the usage warning, and remote: false is rejected. Consumption is not part of this Worker binding.
#15948 a0712e5 Thanks @akoval-cf! - Add beta K2 stream management commands
Use wrangler k2 streams create order_events, wrangler k2 streams list, wrangler k2 streams get <stream-id>, and wrangler k2 streams delete <stream-id> to manage K2 streams. Creation enables Worker bindings but not HTTP ingestion by default, matching the dashboard. Pass --http-enabled to enable authenticated HTTP ingestion and print its endpoint. Creation prints the stream ID and a binding configuration with a YOUR_BINDING_NAME placeholder for the Worker's variable name, but does not edit the configuration file automatically.
All four commands support --json. Deletion requires confirmation, or --force/-y to skip it; use --force --json for JSON deletion output. Creation also accepts retention, HTTP authentication, Worker-input, and CORS options; listing supports pagination and a name filter. Default Wrangler logins now request k2.read and k2.write; existing OAuth users should run wrangler login again, or use a custom API token granting K2 Config Write. The account must be enabled for K2.
#15908 ddaa558 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260926.1 | ^5.20260930.2 |
| workerd | 1.20260926.1 | 1.20260930.2 |
OpenSSH only allocates a pseudo-terminal when no remote command is given, so interactive commands such as wrangler containers ssh <ID> -- bash previou
#15919 91a3606 Thanks @flakey5! - Add --tty (-t) flag to wrangler containers ssh to force pseudo-terminal allocation
OpenSSH only allocates a pseudo-terminal when no remote command is given, so interactive commands such as wrangler containers ssh <ID> -- bash previously ran without a prompt or line editing. Pass --tty to force one:
wrangler containers ssh <ID> --tty -- bash
#15951 2a15ae2 Thanks @flakey5! - Support SSH settings for Durable Object-managed Containers in the configuration API
defineContainer now accepts ssh and authorizedKeys with schedulingPolicy: "durable-object", matching the ssh and authorized_keys fields that Wrangler already supports for these Containers. Previously the schema rejected them, so they could not be set from cloudflare.config.ts.
defineContainer({
name: "sandbox",
schedulingPolicy: "durable-object",
ssh: { enabled: true },
authorizedKeys: [{ name: "laptop", publicKey: "ssh-ed25519 AAAA..." }],
});Running wrangler dev with remote bindings on an unpublished worker protected by Access (e.g. using a wildcard on your workers.dev domain) previously f
#15159 7bb6eae Thanks @veggiedefender! - Fix wrangler dev remote bindings for workers.dev subdomains protected by Access
Running wrangler dev with remote bindings on an unpublished worker protected by Access (e.g. using a wildcard on your workers.dev domain) previously failed with a redirect loop. Wrangler now correctly authenticates remote bindings with Access in this situation.
#15923 60ccdbd Thanks @petebacondarwin! - Upgrade the bundled capnweb implementation to 0.12.0
This updates the RPC implementation shipped in Miniflare and remote-binding proxy workers to the latest capnweb release.
#15938 62fd03a Thanks @dieub! - Resolve the affected Undici dependency in new Wrangler and Vite plugin installs
Undici 7.29.1 fixes GHSA-3wwx-pv8p-q78v. Update the shared dependency catalog and matching types used by Miniflare and Wrangler so downstream installs can resolve the patched runtime without an application-level override. A published release is still required for consumers; this changeset does not alter already published package metadata.
#15903 06ed9c8 Thanks @itsmunzir! - Fix custom-domain-only deploys failing for API tokens without Zone Workers Routes read permission
When workers_dev was disabled and routes contained only entries with custom_domain: true, every deploy after the first one fetched /zones/:zoneId/workers/routes to check for route conflicts, even though custom domains are not zone Workers Routes. Tokens scoped to Workers Scripts edit plus custom domains - without Zone > Workers Routes > Read - failed with "No access to the specified resource" after the Worker version had already been uploaded. The conflict check now only covers non-custom-domain routes; custom domain conflicts continue to be reported by the custom domains changeset API.
#15887 86211fe Thanks @alepacheco! - Report an unreachable auth server instead of an expired login when refreshing an OAuth token
When the OAuth token endpoint could not be reached (for example a DNS failure or a connection timeout), the refresh failure was reported as "Your auth token has expired and could not be refreshed", with advice to run wrangler login; in an interactive terminal Wrangler also started a new browser login. A network failure says nothing about the stored refresh token, and a new login would need the same unreachable server. Wrangler now reports that the Cloudflare auth server could not be reached, leaves the stored credentials unchanged, and does not start a login, so the next run can refresh with the same token once the network is back.
Updated dependencies [60ccdbd, 62fd03a, c2bb4c8, eb1efe0, 485cfb3]:
Experimental cloudflare.config.ts projects must now import defineConfig , bindings, triggers, and related helpers from cf/config . Generated declarati
#15914 7f0734c Thanks @jamesopstad! - Use cf/config for cloudflare.config.ts authoring
Experimental cloudflare.config.ts projects must now import defineConfig, bindings, triggers, and related helpers from cf/config. Generated declarations from Wrangler and the Vite plugin also reference this package, so projects using the experimental configuration flow must add cf as a dependency.
The Vite plugin no longer exports @cloudflare/vite-plugin/experimental-config. wrangler/experimental-config remains available for defineWranglerConfig, but no longer re-exports Cloudflare configuration helpers.
A Workflow declared in a Worker's exports is now available on ctx.exports in wrangler dev , the Vite plugin and the Vitest plugin, with the same API a
#15856 4c2993b Thanks @Naapperas! - Support Workflows declared in exports on ctx.exports in local development
A Workflow declared in a Worker's exports is now available on ctx.exports in wrangler dev, the Vite plugin and the Vitest plugin, with the same API as a Workflow binding:
const instance = await ctx.exports.MyWorkflow.create({
params: { name: "World" },
});ctx.exports and workflows bindings with the same Workflow name share their instances, including instances created before the Workflow was declared in exports. Two Workers can't export the same Workflow name, and a binding to an exported Workflow must refer to the Worker and class that export it. getPlatformProxy() ignores Workflows declared in exports, since it doesn't run the Worker's code.
wrangler workflows commands run with --local also work with Workflows declared only in exports, without a workflows binding.
In the Vitest plugin, introspectWorkflow() and introspectWorkflowInstance() still need a Workflow binding, and now explain how to add one when passed a Workflow from ctx.exports. Instances created through ctx.exports are introspected too. A workflows binding whose script_name is the Worker's own name now resolves to the Worker itself again.
#15891 8dc53ae Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260925.1 | ^5.20260926.1 |
| workerd | 1.20260925.1 | 1.20260926.1 |
Use --durable-objects-code-update-mode immediate with wrangler deploy , wrangler versions deploy , and wrangler rollback to update code without waitin
#15658 8280086 Thanks @jqmmes! - Add Durable Objects code update strategies to Worker deployments
Use --durable-objects-code-update-mode immediate with wrangler deploy, wrangler versions deploy, and wrangler rollback to update code without waiting for active instances to hibernate. Use --durable-objects-code-update-mode deferred 30s to set a maximum delay, or configure durable_objects.code_update_strategy with mode and max_delay. When unset, the strategy defaults to deferred with a 5-minute maximum delay; delays cannot exceed 24 hours and must use millisecond precision.
#15800 bd56b98 Thanks @Refaerds! - Add Browser Run as an event source for Queue subscriptions
You can now create Queue subscriptions with --source browserRun.
#15864 ee2b200 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260923.1 | ^5.20260925.1 |
| workerd | 1.20260923.1 | 1.20260925.1 |
#15207 805af2f Thanks @exKAZUu! - Show the stack and cause of failed proxied requests in wrangler dev debug logs
When a request proxied to the local Worker fails, running with --log-level debug now shows the underlying error's stack and cause chain.
Minor Changes #15822 8f7916c Thanks @GregBrimble ! - Support Containers in Worker Preview deployments with the Build Output. Patch Changes Updated dep
8f7916c Thanks @GregBrimble! - Support Containers in Worker Preview deployments with the Build Output.Set containers[].ssh and containers[].authorized_keys when using scheduling_policy: "durable_object" . These are application-wide settings that follow
#15792 479e1e8 Thanks @flakey5! - Configure SSH for experimental Durable Object-managed Containers
Set containers[].ssh and containers[].authorized_keys when using scheduling_policy: "durable_object". These are application-wide settings that follow the same rules as the existing Durable Object-managed Container settings: normal deployments create missing applications and update explicitly configured values, while omitted settings preserve the existing application configuration.
// wrangler.jsonc
{
"containers": [
{
"name": "sandbox",
"class_name": "Sandbox",
"scheduling_policy": "durable_object",
"ssh": { "enabled": true },
"authorized_keys": [
{ "name": "laptop", "public_key": "ssh-ed25519 AAAA..." }
]
}
]
}#15648 52c0e9f Thanks @tpmmorris! - Expose configured Cron Triggers to local development consumers
Wrangler now passes the active environment's exact Cron Trigger expressions to Miniflare so Local Explorer can display them. Headless agent sessions also advertise the Local Explorer scheduled invocation API.
#15786 bdda4c3 Thanks @ThomasRubini! - Support UDP connect handlers in local development
The experimental connect configuration now accepts protocol: "udp", with optional idle_timeout_ms and max_pending_bytes settings. UDP datagrams are delivered to the Worker's connect() handler using workerd's value-mode socket streams, and can be tested with Miniflare#dispatchConnect({ protocol: "udp" }).
#15779 fc3cbaa Thanks @Naapperas! - Support workflow entries in the exports configuration map
A Worker can now declare the Workflows it defines in exports, keyed by the WorkflowEntrypoint class name:
{
"exports": {
"MyWorkflow": {
"type": "workflow",
"name": "my-workflow",
"limits": { "steps": 100 },
"schedules": "0 * * * *"
}
}
}A workflow export accepts the same settings as a workflows binding: limits, concurrency, schedules, and default_retention. wrangler deploy and wrangler versions upload send these entries to the upload API by name, and wrangler deploy and wrangler triggers deploy provision the Workflow with its settings, just as they do for workflows bindings owned by the Worker. A Workflow may be declared both as a binding and as an export, as long as both declarations use the same class and do not set the same setting to different values. A binding to another Worker's Workflow cannot share a name with an export. @cloudflare/config adds the matching exports.workflow() helper. Local development does not yet act on these entries.
#15796 be72815 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260921.1 | ^5.20260923.1 |
| workerd | 1.20260921.1 | 1.20260923.1 |
#14847 940c692 Thanks @TheSaiEaranti! - Emulate the deterministic-ID uniqueness contract in the local Workflows binding
The local Workflows binding now matches the documented production behavior for deterministic instance IDs: create({ id }) with an ID that already exists throws (instance.already_exists) and retains the existing instance, and createBatch() skips IDs that already exist or repeat within the batch, excluding them from the result instead of creating duplicate executions. Previously both paths silently created duplicates, so code relying on deterministic IDs for idempotency (for example a Queue consumer creating one workflow per message) appeared to work locally while double-executing workflow bodies.
#15803 cd60c9c Thanks @pmiguel! - Show --jurisdiction in help for wrangler kv namespace create
The option was supported but omitted from the command's help output. Users can now discover how to create KV namespaces in a specific jurisdiction.
#15838 15799d4 Thanks @oddharsh! - Update smol-toml to 1.9.0 to fix slow parsing of very large TOML files
Parse time for TOML config files now grows linearly with their size, instead of with its square: a 40,000-line file that took 259 ms to parse now takes 17 ms, while typical wrangler.toml files parse in the same time as before. This addresses the GHSA-r4xh-jqrq-34v2 advisory against earlier versions of the parser.
Some TOML syntax errors now point at the character that caused them. For example, a wrangler.toml containing INVALID "FILE is now reported as illegal character in key at the ", rather than incomplete key-value at the start of the line.
Updated dependencies [52c0e9f, 44f5295, be72815, 940c692, bdda4c3, fc3cbaa]:
Use wrangler deploy --temporary --event-code <code> to provision an account for an event. Wrangler requires explicit server acknowledgement before cac
#15776 b03f960 Thanks @edevil! - Add event-code support to temporary Worker deployments
Use wrangler deploy --temporary --event-code <code> to provision an account for an event. Wrangler requires explicit server acknowledgement before caching the account and keeps the event code out of its cache and telemetry.
#15817 6e77c53 Thanks @jamesopstad! - Allow framework commands to produce Preview Build Output with the experimental config
When cf previews deploy invokes a framework build command, Preview intent is now preserved. Function-based cloudflare.config.ts files receive isPreview: true, and generated Build Output is marked as a Preview build.
When Wrangler's --experimental-new-config flag or Vite's experimental.newConfig option is enabled, inferred configuration and runtime declarations are
#15778 cd7508c Thanks @jamesopstad! - Generate types during development and supported builds with Vite's experimental.newConfig option or Wrangler's --experimental-new-config flag (and --experimental-cf-build-output for builds)
When Wrangler's --experimental-new-config flag or Vite's experimental.newConfig option is enabled, inferred configuration and runtime declarations are now kept in .cloudflare/types/index.d.ts. Vite refreshes them during development and production builds. Wrangler refreshes them during development and when building with both --experimental-new-config and --experimental-cf-build-output. In the experimental wrangler.config.ts format, the types option is now top-level because it applies to both commands.
#15765 1bdb96d Thanks @th0m! - Prepare the required egress sidecar for local Containers without configured images
Wrangler dev and Vite dev/preview now pull the required sidecar for Durable Object-managed Containers that select their application image at start time. Previously, these Containers failed to start unless the sidecar image was already cached in Docker.
#15712 f5605f5 Thanks @alsuren! - Match D1 SQL statement splitting to the local SQLite runtime
Wrangler now uses SQLite's statement-completion state machine when splitting D1 SQL files. This keeps trigger, quoted identifier, comment, and keyword handling consistent with local execution.
This updates the bundled TOML parser that reads wrangler.toml to a version that addresses two advisories against 1.5.2: GHSA-7w5x-hrqm-74c2 (a value f
#15662 59267fc Thanks @oddharsh! - Update smol-toml to 1.8.0
This updates the bundled TOML parser that reads wrangler.toml to a version that addresses two advisories against 1.5.2: GHSA-7w5x-hrqm-74c2 (a value followed by a comment with no trailing newline, such as a=[1 #, put the parser in an infinite loop) and GHSA-v3rj-xjv7-4jmq (thousands of consecutive comment lines overflowed the stack). On the old version, wrangler deploy against a wrangler.toml ending in a=[1 # never returned; it now fails with Invalid TOML document: cannot find end of structure.
#15760 6906bf0 Thanks @yomna-shousha! - Warn when wrangler preview returns only non-custom-domain URLs even though custom-domain Preview URLs are configured.
#15761 354ebdb Thanks @podonnell-dev! - Fix Preview output artifacts to always include the resolved parent Worker name
Preview artifacts now use Wrangler's resolved Worker name instead of relying on the Preview API response to include it.
Updated dependencies []:
Runtime type headers without compatibility flags now end at the compatibility date, keeping generated types reproducible when tools remove trailing wh
#15762 ad20547 Thanks @podonnell-dev! - Fix wrangler types generating runtime headers with trailing whitespace
Runtime type headers without compatibility flags now end at the compatibility date, keeping generated types reproducible when tools remove trailing whitespace.
#15703 02c1d83 Thanks @KianNH! - Improve Container image listing and deletion
List all image pages using read-only credentials, validate tags before deletion, and report successful deletion when the garbage-collection request fails.
#15700 275184d Thanks @KianNH! - Fix Container SSH connection setup and shutdown
Prevent SSH connections from stalling during setup and ensure proxy processes exit when sessions close.
#15759 bd59eca Thanks @petebacondarwin! - Show valid sha256-prefixed tags in Container image listings
Container image listings now distinguish valid OCI tags such as sha256-release from synthetic digest entries such as sha256:<digest>.
Updated dependencies []:
Wrangler now displays placeholder replacement guidance directly beneath the suggested Preview configuration instead of as a separate warning. JSON out
#15744 0ed4c54 Thanks @podonnell-dev! - Improve wrangler preview onboarding guidance
Wrangler now displays placeholder replacement guidance directly beneath the suggested Preview configuration instead of as a separate warning. JSON output continues to include the guidance in its structured onboarding messages.
#15678 703922d Thanks @christhorwarth! - Read workers.dev URLs from the Worker resource during deployment
Wrangler no longer requires account-level subdomain permission to display Worker and version-preview URLs. It now uses the Worker-scoped URL fields while preserving account-level registration for accounts without a workers.dev subdomain.
Updated dependencies [14d946d]:
The root remains config.json , Worker configs are now worker.config.json , and Container configs are now container.config.json . Resource configs no l
#15713 3c75cad Thanks @jamesopstad! - Identify experimental Build Output resource configs by filename and location
The root remains config.json, Worker configs are now worker.config.json, and Container configs are now container.config.json. Resource configs no longer contain top-level type discriminators, while settings and build context are stored together in the root config.
#15713 3c75cad Thanks @jamesopstad! - Define experimental Cloudflare configuration with a single default export
Experimental cloudflare.config.ts files now define settings and resources together in a default-exported defineConfig() call. Add a Worker under worker, add Containers to the containers array, or omit both to provide settings only.
import * as entrypoint from "./src/index.ts" with { type: "cf-worker" };
export default defineConfig({
accountId: "...",
complianceRegion: "public",
worker: {
name: "my-worker",
compatibilityDate: "2026-09-18",
entrypoint,
},
});#15720 35668d7 Thanks @alexkli! - Add experimental --zone and --zone-id flags to wrangler deploy and wrangler triggers deploy to attach a zone to routes passed via --route
Routes passed on the command line were always sent to the Cloudflare API as bare patterns. Zones with an SSL for SaaS entitlement reject such routes with error 10082 ("When using wildcard host ssl for saas entitlement you must specify the zone per route using zone_id or zone_name"), and until now the only way to set a zone was in the config file, which --route overrides.
The new flags are experimental and must be enabled with --experimental-route-zones (alias --x-route-zones). Pass a single zone to apply it to all routes, or one zone per route in the same order as the --route flags:
wrangler deploy --x-route-zones --route "app.example.com/*" --route "api.example.com/*" --zone example.com
wrangler deploy --x-route-zones --route "a.example.com/*" --zone example.com --route "b.example.net/*" --zone example.net
--zone sets zone_name and --zone-id sets zone_id on each route. The two flags cannot be combined, and passing more than one zone requires exactly one per --route. Routes without zone flags behave exactly as before.
#15699 45b3b81 Thanks @skepticfx! - Remove the experimental Container image environment binding
Durable Object-managed Containers now use ctx.container.images without Wrangler generating env.EXPERIMENTAL_CLOUDFLARE_CONTAINER_IMAGES. Update code using the experimental environment binding to read ctx.container.images and regenerate your Worker types.
Version deployments identify managed applications from native named images, and --containers-rollout=none preserves native Container metadata. Containers without named images must first be provisioned with wrangler deploy; versions upload verifies that their applications already exist. The old binding is no longer read or reserved, including on previously uploaded versions. keep_vars retains existing variables as usual; redeploy without it to remove an existing experimental binding.
#15702 8235e6a Thanks @podonnell-dev! - Return structured configuration errors from wrangler preview --json
When a Worker is missing its Preview configuration, JSON mode now returns an error, a suggested_config patch, and any associated onboarding messages without interactive output or terminal formatting. This changes the private-beta Preview command to make automated onboarding reliable.
#15577 731a2ee Thanks @sdnts! - Add support for jurisdictions to Queues subcommands
#15711 91e2f86 Thanks @ghostwriternr! - Allow local Container images without exposed ports
Wrangler and the Cloudflare Vite plugin no longer reject images that omit Docker EXPOSE metadata. Local Containers can run command-only workloads or serve traffic through workerd without declaring an unused image port.
#15740 c5913a6 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260918.1 | ^5.20260921.1 |
| workerd | 1.20260918.1 | 1.20260921.1 |
#15471 0751490 Thanks @edmundhung! - Fix cf builds for static projects that serve assets from the project root
The experimental Build Output path now omits the reserved .cloudflare directory when the project root is used for static assets. This prevents recursive output copying in Wrangler while preserving the existing behaviour for other asset directories.
#15440 43b1f85 Thanks @HuzaifaAbdulRehman! - Rebase absolute non-JavaScript module specifiers when preserve_file_names is enabled
With preserve_file_names set, a non-JS module imported by an absolute path kept that path as its module name. The build machine's filesystem layout ended up inside the deployed Worker, and the module was never written to --outdir. A local dry run reported success while the upload failed server-side with error code 10021. Tooling that rewrites externals to absolute paths hits this, which is how it was found in @opennextjs/cloudflare with WASM imports.
Absolute specifiers are now rebased to ./<basename>, which is what the hashed branch of the same code already does minus the hash prefix. Relative specifiers keep the behaviour they had.
Wrangler and the Cloudflare Vite plugin now build Dockerfile-backed Container images when experimental Build Output is enabled. Container configs are
#15609 1f070c8 Thanks @emily-shen! - Build Containers when emitting experimental Build Output
Wrangler and the Cloudflare Vite plugin now build Dockerfile-backed Container images when experimental Build Output is enabled. Container configs are emitted under .cloudflare/output/v0/containers with local image references, while existing registry references pass through unchanged.
#15329 c4c9b75 Thanks @akshitsinha! - Evaluate Flagship flags locally during development
Flagship bindings now use the local Miniflare store by default in Wrangler and the Vite plugin, keeping development offline and isolated from production flags. Set remote: true on a binding to continue using its remote app.
Use wrangler flagship flags pull <APP_ID> to seed the store from a remote app. Flag management commands also accept --local to read and update the local store directly.
#15701 643e5cc Thanks @WillTaylorDev! - Pass Preview intent to defineWorker and upload its resolved configuration
Preview builds now evaluate programmatic Worker configuration with ctx.isPreview set to true and record that intent in Build Output. The shared Preview uploader deploys the resolved bindings and settings while preserving configured Preview base values when it creates a Preview.
#15705 a0485d5 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260917.1 | ^5.20260918.1 |
| workerd | 1.20260917.1 | 1.20260918.1 |
#15587 629ddef Thanks @Kuldeeep18! - Fix duration calculation for running workflow instances, steps, and attempts in wrangler workflows instances describe
wrangler workflows instances describe previously distorted the elapsed duration of in-progress instances, steps, and attempts across non-UTC timezones by stripping " GMT" from toUTCString(), causing new Date(...) to parse the timestamp in the local client timezone. The duration is now correctly computed against the current time.
Updated dependencies [a0485d5]:
Wrangler now validates and uploads the Issues setting alongside the existing logs and traces observability options. The experimental configuration for
#15684 6874aa9 Thanks @Ankcorn! - Add support for configuring real-time Issues with observability.issues.enabled
Wrangler now validates and uploads the Issues setting alongside the existing logs and traces observability options. The experimental configuration format supports the equivalent observability.issues.enabled option.
#15681 d96b319 Thanks @podonnell-dev! - Mark wrangler preview commands as open beta
Wrangler now labels Preview commands as open beta in help output and command warnings, matching the feature's public availability.
#15673 2b39fc2 Thanks @ghostwriternr! - Support explicit named Container image selection in Wrangler local development
Wrangler builds or pulls named images configured through Wrangler JSON or TOML and exposes their local tags through ctx.container.images. Pass one of those references to ctx.container.start({ image }) to select the image.
This extends the experimental Durable Object-managed Containers interface. Named images are opt-in and do not become the Container's default image. A Container without a default image must supply an image or full Container snapshot when starting.
#15689 876eea1 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260916.1 | ^5.20260917.1 |
| workerd | 1.20260916.1 | 1.20260917.1 |
You can now configure placement in the previews block. Preview-specific placement overrides the top-level placement configuration for Preview Defaults
#15600 bac0c6a Thanks @podonnell-dev! - Add placement configuration for Previews
You can now configure placement in the previews block. Preview-specific placement overrides the top-level placement configuration for Preview Defaults and deployments.
#15600 bac0c6a Thanks @podonnell-dev! - Improve onboarding guidance for Previews (when previews block is missing from configuration file)
When a local previews block is absent, Wrangler writes the Preview Base configuration to the local config file. When no Preview Base configuration exists, Wrangler prints a placeholder configuration derived from production bindings and warns against reusing production binding configuration.
#15483 71b6f10 Thanks @tpmmorris! - Align Local Explorer Workflow instance status requests with production
Local Explorer and Wrangler local mode now use the production-compatible status request field for pausing, resuming, restarting, and terminating Workflow instances. Direct Local Explorer API consumers must replace the previous action field with status.
Successful Local Explorer status updates now return the production-compatible instance status and response timestamp instead of the local-only result.success acknowledgement.
#15665 ad23e6e Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260915.1 | ^5.20260916.1 |
| workerd | 1.20260915.1 | 1.20260916.1 |
#15655 be2437a Thanks @WillTaylorDev! - Send exports with Worker Preview deployments
wrangler preview dropped the exports block from deployment requests. Durable Objects reached through ctx.exports had no Preview namespace, and cache settings for each entrypoint were lost too.
Command telemetry now records a coarse category for the entry-point/assets positional ( wrangler deploy <path> ) under sanitizedArgs.path , so we can
#14587 76c0ce6 Thanks @MattieTK! - Categorise the positional path argument to wrangler deploy and wrangler versions upload in command telemetry
Command telemetry now records a coarse category for the entry-point/assets positional (wrangler deploy <path>) under sanitizedArgs.path, so we can understand whether people pass a file, a directory, or a relational reference such as . or ../example. The possible values are file, directory, current-dir, parent-relative, and not-found, or null when no positional is provided. The raw path is never sent — only the category.
#15597 a83d7ac Thanks @skepticfx! - Configure application-wide logs for experimental Durable Object-managed Containers
Set containers[].observability.enabled or containers[].observability.logs.enabled when using scheduling_policy: "durable_object". Normal deployments create missing applications and update explicitly configured log settings without a Container rollout. Omitted settings preserve the application configuration; root Worker observability is not inherited for this policy.
Version uploads may initialize missing applications but preserve existing settings. Deploying or rolling back Worker versions also preserves existing application settings, and --containers-rollout=none skips their updates.
#15597 a83d7ac Thanks @skepticfx! - Support per-image build options for experimental Durable Object-managed Containers
Set build_context and build_vars alongside dockerfile in a Container's named images entries. Context paths resolve relative to the Wrangler configuration file and default to the Dockerfile's directory. Build variables are passed as Docker build arguments. Entries using the same Dockerfile with different contexts or variables are built separately.
{
"containers": [
{
"class_name": "Sandbox",
"scheduling_policy": "durable_object",
"images": {
"app": {
"dockerfile": "./docker/Dockerfile",
"build_context": ".",
"build_vars": { "APP_ENV": "production" }
}
}
}
]
}#15638 fa79b26 Thanks @G4brym! - Support AI Search bindings in Worker Previews
wrangler preview now accepts ai_search and ai_search_namespaces entries in the previews block and includes them in Preview deployment bindings. This lets Workers that use AI Search instance or namespace bindings attach existing resources to Preview deployments, including preview-specific instance or namespace names.
These bindings are non-inheritable: declare them explicitly under previews. They attach to existing AI Search resources; preview does not provision new isolated instances or namespaces.
#15256 16d1310 Thanks @theoephraim! - [private beta]: Add --secrets-file and --var flags to wrangler preview
Like wrangler deploy and wrangler versions upload, wrangler preview now accepts a --secrets-file flag pointing to a JSON or .env format file, and --var KEY:VALUE pairs that are injected into the Preview deployment as plain text variables. CLI vars override same-named vars from the previews section of your config file, and secrets from the file take precedence over both:
wrangler preview --secrets-file .env.preview --var API_URL:https://api.example.com
#15453 ca71205 Thanks @G4brym! - Remove the gated Web Search binding and Wrangler command
The unreleased search binding and its experimental command have been removed from Wrangler, Miniflare, and configuration APIs.
#15597 a83d7ac Thanks @skepticfx! - Allow experimental Durable Object-managed Containers to link by name through exports
Containers using scheduling_policy: "durable_object" can now specify name and link from exports.<Class>.container without repeating class_name. Deploy and version upload resolve that link for image preparation, Worker metadata, and Container application creation.
#14775 1be7b97 Thanks @dario-piotrowicz! - Sync Local Explorer endpoint lists across agent hints
The Local Explorer endpoint list is now consistent across the three places it appears: the AGENTS.md template in create-cloudflare, the runtime agent hint in wrangler dev, and the Vite plugin agent hint. All three now include the observability/clear endpoint, use the canonical /cdn-cgi/local/explorer path, and have cross-reference comments pointing to each other.
#15409 b149147 Thanks @tpmmorris! - Fix per-query overrides for wrangler ai-search search
--score-threshold, --max-num-results, --filter, and --reranking are now sent using the AI Search request schema, so the service applies them to searches instead of ignoring them.
#15633 7db596c Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260911.1 | ^5.20260915.1 |
| workerd | 1.20260911.1 | 1.20260915.1 |
#14906 a0856da Thanks @exKAZUu! - Surface the original error message, name and stack when the dev server reports an internal error
Previously wrangler dev could exit with an empty ✘ [ERROR] log that gave no indication of what went wrong (e.g. Network connection lost., see #14641). These errors now include their original message, name and stack, so the failure is actually diagnosable.
#15179 cb0955f Thanks @rioaguspermana! - Treat 502, 503, and 504 as gateway errors during asset upload retries
Pages and Workers asset uploads now retry more patiently when the Cloudflare API responds with a 502, 503 or 504 gateway error, reducing concurrency and waiting longer between attempts instead of failing the deploy quickly.
#15399 982b806 Thanks @tpmmorris! - Improve over-limit run_worker_first errors when duplicate rules are present
The error now reports distinct and duplicate-entry counts and lists duplicated rules, making it clear when removing redundant entries can bring the configuration within the limit.
Too many `run_worker_first` rules were provided; 105 rules provided (99 distinct, 6 duplicate entries) exceeds max of 100. Note: duplicate entries count towards the route limit. Ensure that no duplicate rules are present in your `run_worker_first` configuration.
The duplicated rules found are:
- "/rule/0"
- "/rule/1"
- "/rule/2"
- "/rule/3"
- "/rule/4"
...and 1 more duplicated rule.
#12369 ffabe74 Thanks @43081j! - Replace execa with tinyexec for running subprocesses, shrinking the bundled Wrangler output.
#15633 7db596c Thanks @dependabot! - Preserve service-worker middleware error propagation with spec-compliant event dispatch
Wrangler's synthetic service-worker events now propagate listener exceptions to middleware without changing the behavior of user-created EventTarget instances.
#15400 e03822a Thanks @james-elicx! - Reduce the size of Wrangler's published package
Exclude test-only, build-only, and obsolete template files from the npm package while retaining all runtime templates.
#15631 c4a6279 Thanks @petebacondarwin! - Restore static asset upload concurrency after gateway errors
Static asset uploads previously remained at concurrency one for the rest of the deployment after any 524 response, which could make large deployments exceed the upload session lifetime. Successful uploads now restore the session's original concurrency gradually while retaining gateway throttling. Requests that were already in flight when throttling began do not restore capacity, so a burst of stale successes cannot immediately undo backpressure.
Updated dependencies [7db596c, e35c4a1, d3565a5, ca71205, 1015cfb, 982b806, 641df47]:
Updated dependencies [ 8997652 ]:
8997652]:
Wrangler now explains that DNS and TLS certificate provisioning may continue after a deploy adds a custom domain or enables its Preview URLs. Stable r
#15592 945aaa3 Thanks @WillTaylorDev! - Add a provisioning delay note when custom domain Preview URLs change
Wrangler now explains that DNS and TLS certificate provisioning may continue after a deploy adds a custom domain or enables its Preview URLs. Stable redeploys don't repeat the note.
This assumes that a request which matches the stored custom domain state doesn't restart provisioning. The client infers this from the API changeset and current domain record because this repository can't verify the backend behavior.
#15592 945aaa3 Thanks @WillTaylorDev! - Clarify production status labels for custom domain routes
Wrangler now prefixes explicit custom domain production states with production: so they match Preview labels. The updated labels appear in deployed trigger output and WRANGLER_OUTPUT_FILE_PATH.
#15602 47d906f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260910.1 | ^5.20260911.1 |
| workerd | 1.20260910.1 | 1.20260911.1 |
#15592 945aaa3 Thanks @WillTaylorDev! - Avoid replacement prompts for custom domains already on the Worker
Wrangler now updates Preview settings without asking to replace a custom domain when that domain already belongs to the deployed Worker. It still asks before replacing domains attached to another Worker.
#15592 945aaa3 Thanks @WillTaylorDev! - Explain how to enable Preview URLs when a Preview deployment has none
wrangler preview now shows URL shapes and configuration snippets for Workers.dev and custom domains. The custom domain snippet preserves every configured route, and the guidance distinguishes missing settings from disabled ones.
This changes a private beta feature. The warning also makes clear that wrangler deploy publishes code from the current checkout.
shell-quote@1.8.1 is affected by a ReDoS in parse() ( CVE-2026-13311 / GHSA-395f-4hp3-45gv — an unauthenticated attacker who can feed a string into pa…
#15480 36aed7f Thanks @skepticfx! - Add Durable Object-managed Containers to top-level container configuration
Wrangler now accepts scheduling_policy: "durable_object" in the top-level containers array and creates its namespace-backed application after the Worker upload resolves the Durable Object namespace ID. The namespace ID is also the application ID, so repeated deploys idempotently ensure the same application without name-based lookup, modification, or a Containers rollout.
Durable Object-managed entries accept class_name, scheduling_policy, an optional name, and an optional named images map. Scheduler-only fields are rejected. Each image provides either a local dockerfile or a digest-pinned managed-registry image. Wrangler builds or resolves each image, waits while Cloudflare prepares it for the Containers runtime, and uploads the resulting references with the Worker version for access through ctx.container.images and env.EXPERIMENTAL_CLOUDFLARE_CONTAINER_IMAGES. Local development support for these entries is deferred to a follow-up.
Existing scheduler-backed entries and Durable Object migrations continue to work unchanged.
With --containers-rollout=none, existing Workers retain their deployed Container metadata and image binding even when local containers is omitted or empty; local scheduler edits are also ignored. The upload stops if the deployed versions cannot be recovered. Existing Workers for Platforms dispatch scripts reject this flag before upload because their API does not expose enough metadata to preserve Container associations safely. First deployments can still skip Container preparation and rollout. Without this flag, removing managed Containers, including by omitting containers entirely, clears the experimental image binding even with keep_vars.
versions deploy validates the selected versions before changing traffic and creates their Durable Object-managed applications only after deployment succeeds. Both deploy and versions deploy report partial completion if application creation fails afterward, with instructions to retry the same command.
EXPERIMENTAL_CLOUDFLARE_CONTAINER_IMAGES is a temporary, reserved Wrangler binding until native Container image metadata is available. Its class keys identify managed applications during versions deploy, including classes with empty image maps. User configuration cannot declare a binding with this name; existing versions that already use it are treated as Container configuration.
#15493 493e635 Thanks @GregBrimble! - Remove wrangler preview settings commands
The private-beta wrangler preview settings and wrangler preview settings update commands are no longer available.
#15411 0b43395 Thanks @xgame92! - Fail wrangler versions upload early when a Worker has a pending Durable Object migration
Wrangler now directs users to run wrangler deploy to apply the migration instead of sending a version upload request that the API will reject.
#15518 9d75006 Thanks @taylorlee! - Detect named-only module Worker entrypoints correctly
Wrangler now distinguishes named-only module Workers from legacy Service Workers that happen to have named exports. A default export identifies a module Worker; otherwise, legacy addEventListener registration identifies Service Worker format.
#15581 b605aa6 Thanks @MattieTK! - Correct Pages-to-Workers delegation analytics for forced and ineligible commands
The legacy forced result counted every agent-driven Pages command using --force, including commands that could never have been delegated. Wrangler now emits eligible_forced only when --force prevents an otherwise eligible delegation, and records other agent commands as ineligible with a bounded reason and whether force was used.
#15432 f45b596 Thanks @razethion! - Prevent delayed internal errors from fetch-only remote bindings
Fetch-only remote bindings such as D1 and R2 previously opened an unused WebSocket RPC session. RPC sessions are now created only when an RPC method is called.
#15585 f69f95a Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260908.1 | ^5.20260910.1 |
| workerd | 1.20260908.1 | 1.20260910.1 |
#15554 bff525d Thanks @XiaoZ-0218! - Add the missing transferred_classes migration to the config schema
DurableObjectMigration described new_classes, new_sqlite_classes, renamed_classes and deleted_classes, but not transferred_classes. normalizeAndValidateConfig has always validated that key, and the deploy path forwards it to the API along with the rest of the step, so Transfer migrations worked — but config-schema.json is generated from the type, so an editor resolving $schema reported a valid, documented migration as an unknown key.
Adding the field to the type puts it in the generated schema. No runtime change.
#15584 96688b3 Thanks @Svector-anu! - Bump shell-quote to 1.9.0+ to pick up two disclosed advisories
shell-quote@1.8.1 is affected by a ReDoS in parse() (CVE-2026-13311 / GHSA-395f-4hp3-45gv — an unauthenticated attacker who can feed a string into parse() can block the event loop for tens of seconds with plain space-separated input, no shell metacharacters required) and by an object-token escaping bug in quote() (CVE-2026-9277 / GHSA-w7jw-789q-3m8p), both fixed upstream in 1.9.0. Wrangler's parse() wrapper (src/utils/shell-quote.ts) is reachable from pages dev/init command-line parsing, so the ReDoS applies; the quote() call site only ever passes string arguments, so the object-token issue was not reachable here, but there is no reason to stay on a vulnerable range once a patch exists.
#15563 ed5797a Thanks @Bortlesboat! - Encode filenames in Pages HTML redirects
Fix wrangler pages dev returning a 502 response when redirecting HTML paths containing Unicode characters. Keep reserved characters in filenames encoded in the redirect destination and preserve the request query string.
#14889 128235a Thanks @chinesepowered! - Fix wrangler types --strict-vars=false emitting invalid TypeScript for an empty array var
A var whose value was an empty array produced ()[], which is a syntax error. Because this lands in the generated worker-configuration.d.ts, it did not just break that one line — the whole file failed to parse, so no binding types resolved at all. An empty array now generates unknown[].
#15494 f8aea7e Thanks @GregBrimble! - Use previews_base_config for Preview configuration
Preview commands now read the Worker Previews Base configuration from the previews_base_config API field.
#15569 24ef86b Thanks @RealBhupesh! - Fix wrangler workflows instances describe crashing on dynamic retry delays
The Workflows API serializes function retry delays as "[dynamic]". The describe command previously parsed that as a duration, produced an Invalid Date, and threw RangeError: Invalid time value before printing remaining steps. It now renders unknown (dynamic delay) and also tolerates attempts whose end timestamp is missing.
Updated dependencies [f45b596, f69f95a, a549e58, dbb3ff4, fea3cd0, 6bd7b6c, 15cd6e1, be1caec, dbc9506]:
Wrangler now accepts container-specific observability settings via containers[].observability , including application-level targeting fields for Conta
#14372 dbf6aad Thanks @ichernetsky-cf! - Add containers[].observability support to wrangler deploy
Wrangler now accepts container-specific observability settings via containers[].observability, including application-level targeting fields for Containers. Root observability continues to work as a fallback when a container does not define its own observability settings.
wrangler deploy now preserves legacy configuration.observability for existing container apps that still use rollout-based observability, while using top-level application observability for new or already-migrated apps.
Existing application diffs are now normalized even when stored resource limits cannot be mapped to a named instance type. API-only metadata and equivalent managed-registry image names no longer appear as edits or affect whether deployment changes require a rollout.
#15004 e20df20 Thanks @MattieTK! - Delegate agent Pages project creation with a production branch to Workers
When run by an AI agent, wrangler pages project create --production-branch <name> is now eligible for delegation to a Workers static-assets deploy. The production branch names the target that a Workers deploy would publish to, so it does not need to disqualify a brand-new project from delegation.
wrangler pages deploy --branch <name> remains on Pages because an interactive new-project flow separately prompts for its production branch. The deployment branch may therefore represent a preview and cannot safely be converted into a production Workers deployment.
#15004 e20df20 Thanks @MattieTK! - Widen agent Pages-to-Workers delegation to new projects on accounts that already use Pages
When run by an AI agent, wrangler pages deploy and wrangler pages project create now delegate a brand-new static Pages project to a Workers static-assets deploy even when the account already has other Pages projects. The gate is now per-project rather than per-account: a command targeting a project that already exists stays on Pages, but a new project is delegated regardless of the account's other Pages projects.
A project name restored from the Pages configuration cache is only used when the cache belongs to the currently authenticated account. An account-matching cached name remains on Pages even when the project is missing remotely, preserving the user's recorded Pages intent. After switching accounts, an otherwise unnamed deploy stays on Pages rather than treating a stale cached project name as a new project on the selected account.
#15560 edb3631 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260907.1 | ^5.20260908.1 |
| workerd | 1.20260907.1 | 1.20260908.1 |
#15557 63c7ff1 Thanks @tomekancu! - Fix wrangler d1 execute --local being extremely slow with large SQL files or commands
The local SQL splitter consumed quoted strings and comments character-by-character, re-checking the full accumulated string each time. This made splitting a large quoted value or comment quadratic, so seed files could take tens of seconds to run. The splitter now only inspects a bounded trailing window on each step, making splitting effectively linear. The remote path is unaffected as it imports the file server-side.
#15542 a4e41df Thanks @NAVEENKUMARKR777! - Fix wrangler dev running the custom build command twice on startup and on every config change
Wrangler already runs the custom build.command once before starting wrangler dev, to resolve the Worker's entry point. When dev.watch wasn't explicitly disabled, BundlerController then unconditionally ran the same build command again the moment it started watching for changes, and repeated this on every subsequent config reload too.
For fast build commands this just meant duplicate log output (e.g. a vite build visibly running twice at startup). For slower or stateful build commands, running two builds concurrently against the same output files could corrupt the result or fail outright (for example, non-deterministic wasm-opt failures have been reported for Rust builds).
The initial watcher setup now only bundles the output the build command already produced, instead of re-running the command. Real file changes detected by the watcher still re-run the build command as before.
The following dependency versions have been updated:
#15502 8bbcb9f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260903.1 | ^5.20260904.1 |
| workerd | 1.20260903.1 | 1.20260904.1 |
#15543 2b42d6f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260904.1 | ^5.20260907.1 |
| workerd | 1.20260904.1 | 1.20260907.1 |
#15323 ea5634e Thanks @Sakshamm-Goyal! - Prevent Wrangler from exiting when a process capturing its output closes the pipe.
Wrangler now ignores broken-pipe errors from stdout and stderr while preserving the existing failure behavior for other output errors.
#14001 c0c6504 Thanks @for-the-kidz! - Update bundle size warning thresholds to use uncompressed size instead of gzip size
The compressed script size limits (3 MiB free / 10 MiB paid) have been removed server-side in favor of a single 64 MiB uncompressed limit. The bundle size reporter now compares the uncompressed bundle size against this 64 MiB limit for its color-coded warnings, instead of comparing gzip size against the old 3 MiB compressed limit.
#15499 ffc7efd Thanks @WillTaylorDev! - Honor Workers Builds name overrides in wrangler preview
Preview commands now target the Worker name supplied by Workers Builds instead of the name in local Wrangler configuration. This prevents preview builds from failing when the two names differ.
#15252 682cd44 Thanks @GregoryCollett! - wrangler dev no longer exits when a request to your Worker fails transiently
Previously, a transient network failure on a single request — most commonly a request arriving just as an idle internal connection was closed, after roughly five seconds without traffic — could take down the whole dev server with an empty ✘ [ERROR], leaving the port unbound until restarted. In CI test suites, one such failure caused every remaining test to fail with connection errors.
wrangler dev now automatically retries the affected request if it is safe to repeat (GET and HEAD requests). If a request still fails, it fails individually — the error is logged with the request method and URL — and the dev server keeps serving.
Updated dependencies [8bbcb9f, 2b42d6f]:
Pipelines is in open beta. wrangler pipelines sinks create and the interactive setup flow now pass the selected JSON compression to the Pipelines API.
#15460 93d72a5 Thanks @QnJ1c2kNCg! - Support gzip compression for JSON Pipelines sinks
Pipelines is in open beta. wrangler pipelines sinks create and the interactive setup flow now pass the selected JSON compression to the Pipelines API. JSON sinks accept uncompressed or gzip, while Parquet retains its existing compression options and zstd default.
#15358 d2d8eea Thanks @pombosilva! - Add a --json flag to the wrangler workflows commands
Every wrangler workflows command now accepts --json, which emits the raw API payload instead of the human-readable rendering. The formatted output remains the default, so existing usage is unaffected:
wrangler workflows instances list my-workflow --json
The JSON output carries raw values rather than a serialisation of the formatted view: ISO timestamps instead of locale-formatted dates, plain status strings instead of emojified labels, and no presentation-only derived fields.
#15469 d40a634 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260831.1 | ^5.20260902.1 |
| workerd | 1.20260831.1 | 1.20260902.1 |
#15481 7c1b2a6 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260902.1 | ^5.20260903.1 |
| workerd | 1.20260902.1 | 1.20260903.1 |
#15472 f6fb347 Thanks @emily-shen! - Tolerate missing permissions during wrangler delete cleanup checks
wrangler delete now warns and continues when it cannot inspect Worker dependencies or clean up legacy Workers Sites KV namespaces because of missing permissions. The Worker delete request itself still fails normally if the token cannot delete the Worker.
#15472 f6fb347 Thanks @emily-shen! - Tolerate missing resource permissions during resource provisioning
When Wrangler cannot check whether a bound resource exists because the API returns a 403, it now skips automatic provisioning for that resource type and continues the deploy. The deploy may still fail later if the resource is missing.
#15476 dc24057 Thanks @christhorwarth! - Fix remote development with static assets for API tokens using granular Worker permissions
Wrangler now creates Workers.dev preview sessions through the Worker-scoped endpoint and derives the preview hostname from the session response. This avoids requiring account-level Workers subdomain access.
Binding conversion, printing, and local-development validation are now exported from @cloudflare/workers-utils so they can be shared by Wrangler, the
#15454 dbbb795 Thanks @jamesopstad! - Move binding utilities into @cloudflare/workers-utils
Binding conversion, printing, and local-development validation are now exported from @cloudflare/workers-utils so they can be shared by Wrangler, the Cloudflare Vite plugin, and other consumers.
The corresponding exports have been removed from @cloudflare/deploy-helpers. Consumers should import them directly from @cloudflare/workers-utils instead.
Wrangler's unstable_printBindings API now accepts the bindings and an options object instead of five positional parameters.
#15353 87a7acf Thanks @pombosilva! - Add --date-start and --date-end filters to wrangler workflows instances list
You can now narrow an instance listing to a creation-time window:
wrangler workflows instances list my-workflow --date-start 2026-01-01 --date-end 2026-01-31
Either flag can be used independently. Both accept an ISO 8601 date or timestamp and are normalised to UTC before being sent, so a date-only value such as 2026-01-01 works as well as a full 2026-01-01T13:00:00Z. The bounds are inclusive and compose with the existing --status filter.
#15379 ea28cc3 Thanks @ibbykhazanchi! - Add query string redaction to Workers observability configuration
Set observability.redact_query_string in wrangler.json or observability.redactQueryString in the experimental cloudflare.config.ts format to remove query strings from request URLs in logs and traces.
#14915 707cb6f Thanks @longlho! - Include exact raw and gzip-compressed Worker bundle sizes in structured deploy and version-upload output.
#15436 200780f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260828.1 | ^5.20260831.1 |
| workerd | 1.20260828.1 | 1.20260831.1 |
#15406 b3f2628 Thanks @james-elicx! - Reduce the installed bundle sizes of Wrangler and Miniflare
Wrangler now resolves bundled workspace dependencies from source during monorepo builds so unused exports can be removed. Miniflare, its shared CLI and container dependencies now use granular @cloudflare/workers-utils entry points instead of loading the package barrel, reducing the raw Wrangler and Miniflare artifacts by 6.16 MiB (31.4%) and 1.06 MiB (22.9%) respectively without changing runtime behavior or installed dependencies.
#15398 1809c5e Thanks @james-elicx! - Reduce Wrangler's published package size
Stop including the unused build metafile in the npm package, reducing its unpacked size by approximately 3.1 MiB.
#15382 b3fb2bf Thanks @Om-singhaI! - Skip the skills install status lookup when telemetry is disabled
Telemetry events include a currentAgentSkillsInstalled property, and computing it can query the GitHub API. The lookup used to start before the telemetry permission was checked, so users who opted out via WRANGLER_SEND_METRICS, DO_NOT_TRACK, or send_metrics in their Wrangler config still triggered network requests on behalf of telemetry. The dispatcher now checks the permission first and only performs the lookup when telemetry is enabled.
The following dependency versions have been updated:
#15383 eb01850 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260826.1 | ^5.20260827.1 |
| workerd | 1.20260826.1 | 1.20260827.1 |
#15393 e1df91a Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260827.1 | ^5.20260828.1 |
| workerd | 1.20260827.1 | 1.20260828.1 |
Updated dependencies [eb01850, e1df91a, b23de74, 015550a, 015550a, 015550a, 3650d29, b23de74]:
The limit is the maximum number of Workflow instances that can run concurrently. It is validated as a positive integer and persisted on deploy; the ce
#15356 fe265f8 Thanks @rubuy-74! - Add support for configuring a per-workflow max concurrency limit via workflows[].concurrency.limit in your Wrangler config.
The limit is the maximum number of Workflow instances that can run concurrently. It is validated as a positive integer and persisted on deploy; the ceiling is enforced server-side. Concurrency is ignored in local development.
{
"workflows": [
{
"binding": "MY_WORKFLOW",
"name": "my-workflow",
"class_name": "MyWorkflow",
"concurrency": { "limit": 10 }
}
]
}
#15367 412c79e Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260825.1 | ^5.20260826.1 |
| workerd | 1.20260825.1 | 1.20260826.1 |
#15375 92874f6 Thanks @WillTaylorDev! - Upload wrangler preview modules as multipart form data
wrangler preview used to base64 the bundle, its modules, and any sourcemaps into a single JSON request body. Base64 inflates content by a third, so a Worker with a large sourcemap could exceed the API request size limit and fail to deploy.
The preview deployment request is now multipart/form-data. The deployment settings travel in a metadata part and each module follows as its own part carrying raw bytes, matching how wrangler deploy already uploads a Worker.
Updated dependencies [412c79e]:
Workflow instances are retained for an account-wide default period after they finish. You can now set a per-Workflow default in your Wrangler configur
#15332 d1cc3af Thanks @pombosilva! - Add default_retention to Workflow bindings for configuring how long instances are retained
Workflow instances are retained for an account-wide default period after they finish. You can now set a per-Workflow default in your Wrangler configuration, applied to instances that do not specify their own retention:
{
"workflows": [
{
"binding": "MY_WORKFLOW",
"name": "my-workflow",
"class_name": "MyWorkflow",
"default_retention": {
"success_retention": "3 days",
"error_retention": "7 days"
}
}
]
}Each side is optional and accepts either a duration string such as "3 days" or a whole number of milliseconds. Durations are interpreted by the Workflows API, which also caps them at your account's retention limit.
#15064 693ca29 Thanks @tpmmorris! - Include a chronological list of handler events in email test harness results, so programmatic local email tests can assert the order in which messages are received, forwarded, replied to, or rejected.
const result = await server.getWorker().email({
from: "sender@example.com",
to: "inbox@example.com",
raw: [
"From: Sender <sender@example.com>",
"To: Inbox <inbox@example.com>",
"Message-ID: <test@example.com>",
"Subject: Test email",
"",
"Hello from the test harness",
].join("\r\n"),
});
expect(result.events).toEqual([
{ type: "received", timestamp: expect.any(String) },
{
type: "forward",
timestamp: expect.any(String),
messageId: expect.any(String),
},
{
type: "reply",
timestamp: expect.any(String),
messageId: expect.any(String),
},
]);#15065 ad89456 Thanks @mtlemilio! - Add experimental wrangler hyperdrive planetscale signature for provisioning Cloudflare-billed PlanetScale databases
wrangler hyperdrive planetscale signature prints a signed authorization as JSON, proving to PlanetScale that Cloudflare will be billed for the database you are about to create:
npx wrangler hyperdrive planetscale signature | \
pscale database create <name> \
--org <org> \
--engine postgresql \
--cloudflare-billing @- \
--format jsonpscale database create defaults to Vitess, so pass --engine postgresql for a Postgres database, and --format json is recommended when the output is consumed by an agent.
This requires pscale v0.313.0 or newer. Wrangler authorizes the Cloudflare billing side only, so your PlanetScale credentials stay between you and pscale.
The signature is a cryptographically signed token that authorizes creating a database billed to your Cloudflare account. Treat it as a credential and do not share it. Piping it, as above, is recommended over passing it as a command line argument.
This command is experimental and its interface may change.
#15134 c66d2d5 Thanks @gpanders! - Enable FUSE-capable local container development
Miniflare now automatically passes the Docker privileges needed for FUSE to local Durable Object containers when using local rootless Docker on Linux with /dev/fuse available, or a local Docker engine on macOS or through WSL where Linux containers run in a VM. This applies to Wrangler, the Cloudflare Vite plugin, and direct Miniflare use.
#15326 9fcb1c9 Thanks @jamesopstad! - Record the selected mode in the Build Output Specification top-level config.json
The mode a build was produced in is now written to .cloudflare/output/v0/config.json as a mode field, alongside the account and compliance settings.
#14966 a4c3458 Thanks @yomna-shousha! - Add pull request metadata to wrangler preview deployments
wrangler preview now detects the pull request associated with the current CI run (GitHub Actions, GitLab CI, CircleCI, and a generic PULL_REQUEST_URL/PR_URL/CHANGE_URL fallback) and attaches it, along with the repository URL, to the preview deployment as annotations (workers/pull_request_number, workers/pull_request_url, workers/repository_url).
This is best effort: if no pull request can be detected, nothing changes. When a pull request is detected, its URL is now also shown in the wrangler preview command output.
#15307 433fa98 Thanks @for-the-kidz! - Add pull request title to wrangler preview deployment annotations
wrangler preview now also detects the title of the pull/merge request associated with the current CI run (GitHub Actions and GitLab CI, plus a generic PULL_REQUEST_TITLE fallback) and attaches it to the preview deployment as the workers/pull_request_title annotation, alongside the existing pull request number/URL, repository URL, and commit SHA annotations.
This is best effort: if no pull request title can be detected, nothing changes.
#15294 4a67a28 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260820.1 | ^5.20260821.1 |
| workerd | 1.20260820.1 | 1.20260821.1 |
#15328 2d78137 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260821.1 | ^5.20260823.1 |
| workerd | 1.20260821.1 | 1.20260824.1 |
#15346 04e8564 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260823.1 | ^5.20260825.1 |
| workerd | 1.20260824.1 | 1.20260825.1 |
#15246 daefb3c Thanks @edmundhung! - Prepare autoconfig for multiple configuration targets
Add target-specific configuration output and command detection while preserving Wrangler's existing setup and deployment behavior.
#15320 c809851 Thanks @Om-singhaI! - Fix wrangler login --use-keyring incorrectly reporting that secret-tool is missing on Linux
Libsecret's secret-tool does not support --version; it prints usage and exits 2, which Wrangler previously interpreted as unavailable. Wrangler now reports it missing only when launching the executable fails.
#15336 22182da Thanks @podonnell-dev! - [private beta]: Explain unavailable Preview URLs after wrangler preview deployments
When a Preview deployment has no active URLs, Wrangler now explains how to enable Preview Deployments on workers.dev or a custom domain.
#15296 d589d30 Thanks @MattieTK! - Stop automatically offering to install Cloudflare skills for new users
Wrangler will no longer prompt new users to install Cloudflare skills after commands complete. It will continue to offer updates to skills that Wrangler previously installed.
Updated dependencies [aa54b49, 4a67a28, 2d78137, 04e8564, 693ca29, 693ca29, 693ca29, 37ed753, f76b68e, c66d2d5, 693ca29, 74de3ab, 0cb8690, dd5148d, 82d11fc]:
You can now configure a Worker to receive raw socket connections during wrangler dev , delivered directly to the Worker's connect(socket, env, ctx) ha
#14995 59872c4 Thanks @ThomasRubini! - Add connect trigger for raw sockets
You can now configure a Worker to receive raw socket connections during wrangler dev, delivered directly to the Worker's connect(socket, env, ctx) handler:
{
"connect": [{ "protocol": "tcp", "port": 5432 }]
}Each entry opens a listening socket on 127.0.0.1 (or the given address) that forwards incoming connections straight to the Worker, bypassing the local dev HTTP entry point. This requires the experimental compatibility flag. Only "tcp" is supported at the moment.
@cloudflare/config also supports declaring this trigger via triggers.connect(...), which lowers to the connect field above:
import { defineWorker, triggers } from "@cloudflare/config";
export default defineWorker({
triggers: [
triggers.connect({ protocol: "tcp", port: 5432, address: "127.0.0.1" }),
],
});#15172 c68f9cb Thanks @WillTaylorDev! - Add container support to worker previews
Worker previews now support containers through a new previews.containers configuration block. Container configuration doesn't inherit, so declare containers explicitly in the previews block to enable them for previews. This mirrors how previews.durable_objects works today. Wrangler names each preview container application {worker_name}_{preview_slug}_{class_name}, normalising and shortening the result to what the API accepts. Either change appends a short digest of the composed name, so two names that would otherwise land on one stay distinct. An entry cannot set its own name, because application names are unique to an account and a fixed name would collide between two previews of the same Worker. A Durable Object class is backed by at most one container application, so the validator rejects two entries that share a class_name. Wrangler skips container applications bound to Durable Object classes that another Worker implements through script_name, because the implementing Worker owns its own container application. A binding is not required: a Durable Object declared through migrations or exports and reached only over ctx.exports can still back a container. Every entry must set class_name. A previews.containers entry whose class_name matches no Durable Object class at all is rejected before the preview deployment is created, so a typo fails loudly instead of producing a preview with no container.
Wrangler creates the container applications on wrangler preview. Deleting a preview tears them down server side, so wrangler preview delete doesn't remove them.
Container build and deploy progress prints to stdout. wrangler preview --json suppresses wrangler's own output so it doesn't interleave with the payload, and warnings and errors still go to stderr. Docker's build output and the progress spinner write to stdout directly and bypass that suppression, so parse --json from a non interactive shell, where the spinner is skipped, and prefer a prebuilt image over a Dockerfile.
#15174 649f667 Thanks @WillTaylorDev! - [private beta]: Create the parent Worker automatically when wrangler preview targets one that doesn't exist yet
Previews hang off a parent Worker, so running wrangler preview before the Worker had ever been deployed failed with a raw API error naming the Preview endpoint. Wrangler now offers to create an empty parent Worker and then carries on creating the Preview. The parent uses the same workers.dev and Preview URL settings that wrangler deploy would resolve, without applying routes or cron triggers. In non-interactive environments, Wrangler creates the Worker without asking.
#14735 30c2d47 Thanks @vaishnav-mk! - Add individual and batch Workflow instance deletion to the runtime and SDK.
WorkflowInstance.delete() deletes one instance. Self-deletion stops the current execution.env.MY_WORKFLOW.deleteBatch(instanceIds) deletes up to 100 instances and returns { deleted, errors } per input position.wrangler workflows instances delete <name> [id..] deletes instances remotely or with --local; IDs can also come from a JSON array passed with --filename, with a combined limit of 100.#15260 5ae9d5b Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260815.1 | ^5.20260816.1 |
| workerd | 1.20260815.1 | 1.20260816.1 |
#15264 4b52975 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260816.1 | ^5.20260819.1 |
| workerd | 1.20260816.1 | 1.20260819.1 |
#15277 ce9b151 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260819.1 | ^5.20260820.1 |
| workerd | 1.20260819.1 | 1.20260820.1 |
#15192 ef73a28 Thanks @ondraulehla! - Fixes kv bulk put corrupting binary values written to local KV
Values marked base64: true were stored incorrectly whenever they contained bytes that do not form valid UTF-8, which covers images, compressed data and most other binary payloads. A Worker reading such a key back under wrangler dev got a different, longer value than the one that was written: a 12 byte PNG header came back as 20 bytes.
kv bulk put writes to local KV by default, so the plain command was the affected one. Remote writes were never affected, and neither were entries without base64 or values written with kv key put.
#15284 39dcea6 Thanks @emily-shen! - Move deploy output writing into shared deploy helpers
#15130 99a1f49 Thanks @emily-shen! - Remove unsupported remote configuration from Workflow bindings
Workflow bindings no longer accept remote in configuration, as remote Workflow bindings have never actually been supported.
#15278 f2437e6 Thanks @Sosokker! - Fix the --temporary error on commands that authenticate more than one time
wrangler d1 migrations apply --remote --temporary failed with this error: You're already authenticated with Cloudflare, so --temporary can't be used. The failure occurred with no login and with no CLOUDFLARE_API_TOKEN. This command authenticates one time for each statement that it runs. The first authentication makes a temporary preview account. The second authentication read the token of this new account as an earlier login.
Wrangler now uses again the temporary account from the same command run. Commands that authenticate more than one time now work as wrangler deploy --temporary works. If real credentials are available, --temporary is still an error.
Updated dependencies [59872c4, 99a1f49, 5ae9d5b, 4b52975, ce9b151, 99a1f49, 99a1f49, 30c2d47]:
A container can now be linked to its Durable Object from the export side, using a new container field that names an entry in the containers array. As
#15026 6529f0c Thanks @petebacondarwin! - Allow containers to be attached to a Durable Object from its exports entry
A container can now be linked to its Durable Object from the export side, using a new container field that names an entry in the containers array. As a result containers[].class_name is now optional — a container that is referenced this way only needs a name:
{
"name": "my-worker",
"main": "worker.js",
"compatibility_date": "2026-07-01",
"containers": [
{ "name": "my-container", "image": "./Dockerfile", "max_instances": 1 }
],
"exports": {
"MyContainerDO": {
"type": "durable-object",
"storage": "sqlite",
"container": "my-container"
}
}
}
The existing containers[].class_name direction keeps working and either direction may be used, but the two must agree: a container that names its Durable Object cannot also be claimed by a different one.
container is only valid on live durable-object exports (created and expecting-transfer) and requires storage: "sqlite". Wrangler now also reports an error when:
container reference names a container that does not existnameclass_name names a Durable Object whose storage is legacy-kvThat last case was previously accepted but could never work: workerd attaches a single container per Durable Object namespace, and in local development every container for a class builds into the same image tag, so one silently overwrote the other. If you have two containers on one class_name, give each its own Durable Object class.
#15211 bc5726b Thanks @nithin42! - Honor access.dev when running Workers with @cloudflare/vitest-pool-workers, so ctx.access.getIdentity() returns the configured identity just as it does with wrangler dev.
#14999 ba54f0d Thanks @mittalpk! - Fix .env loading on Windows leaking stale, differently-cased duplicate keys
On Windows, wrangler loads .env values through a case-insensitive Proxy wrapper so lookups like env.PATH and env.Path resolve to the same value, and this object is assigned directly to process.env. When a key was set again under a different casing (e.g. a value in .env.local overriding one from .env with different casing), the previous casing was never removed from the underlying object. env.PATH/env.Path still returned the correct, latest value, but anything that enumerates process.env — Object.keys, for...in, JSON.stringify, object spread, or a spawned subprocess inheriting the environment — would see both the stale and current key.
Duplicate entries no longer appear, so environment variables passed to subprocesses and any code that lists the environment now see only the latest value for each variable.
#15044 b7422b0 Thanks @stareezy-1! - Normalize structural CRLF line endings before sending D1 commands to the remote query API
wrangler d1 migrations apply --remote and wrangler d1 execute --remote --command failed with incomplete input: SQLITE_ERROR when the SQL contained CRLF line endings inside a compound statement such as a CREATE TRIGGER ... BEGIN ... END; body. Structural line endings are now normalized to LF before the command is sent to the D1 query API, while CRLF inside quoted values and identifiers remains unchanged.
#15046 186339c Thanks @erwinzhang7! - Fixes D1 SQL statements not handling lowercase ends correctly
wrangler d1 execute and wrangler d1 migrations apply split a SQL file into statements before running them. A BEGIN or CASE block closed with a lowercase end was not recognised as closed, so every statement after it was folded into that block instead of being run on its own. SQLite accepts either case, so a file like this applied only the trigger and silently skipped the table:
CREATE TRIGGER IF NOT EXISTS update_trigger AFTER UPDATE ON items
begin
DELETE FROM updates WHERE item_id=old.id;
end;
CREATE TABLE after_the_trigger (id TEXT PRIMARY KEY);
Files written with an uppercase END were unaffected. Both cases now behave the same.
#15231 4f922dc Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260811.1 | ^5.20260814.1 |
| workerd | 1.20260811.1 | 1.20260814.1 |
#15248 4d74b8d Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260814.1 | ^5.20260815.1 |
| workerd | 1.20260814.1 | 1.20260815.1 |
#15185 1f79ace Thanks @jamesopstad! - Resolve --latest to the newest compatibility date supported by the installed runtime
wrangler deploy --latest and wrangler versions upload --latest resolved the compatibility date to the current date, and wrangler pages download config did the same for projects configured to always use the latest compatibility date. Both write that date into a configuration file for subsequent commands to use, so a date that the installed workerd did not yet support left the project unable to run wrangler dev.
These now resolve to the latest compatibility date supported by this version of Wrangler, which is the release date of the workerd it ships with.
#15151 49f73de Thanks @maximilliangrand! - Fix spurious Trailing comma jsonc(519) warnings for wrangler.jsonc in VS Code 1.131+
Trailing commas in wrangler.jsonc files that reference Wrangler's JSON schema are no longer reported as errors by recent versions of VS Code. Wrangler always accepted these files; only the editor warning was wrong.
#14983 7cee278 Thanks @kdelay! - Respect CLOUDFLARE_ACCOUNT_ID in wrangler pages project list, create and delete
These three commands could target a previously used account even when CLOUDFLARE_ACCOUNT_ID was set, failing with Authentication error [code: 10000] in setups with more than one account. They now use the account named by CLOUDFLARE_ACCOUNT_ID, matching the rest of wrangler pages. When the variable is unset, the previously used account is still selected, as before.
#15153 265256a Thanks @podonnell-dev! - Fix wrangler preview base-config commands showing an inherited script positional
#15185 1f79ace Thanks @jamesopstad! - Use a fixed default compatibility date rather than the current date
When no compatibility date was set, Wrangler, C3 and the Vitest pool all defaulted to the current date. workerd only accepts a compatibility date up to 7 days beyond its own release, so whenever a workerd release was delayed the default could get ahead of the runtime that had been installed, and local development would fail to start.
The default is now fixed at the release date of the workerd version that ships with each release, which leaves a week of headroom and updates as workerd is upgraded. @cloudflare/vite-plugin previously inlined the date at which it was built. It now shares the same default.
#15239 f431166 Thanks @jamesopstad! - Prevent date-enabled Node.js compatibility from adding conflicting globals to generated runtime types
Runtime type generation now treats Node.js compatibility enabled by a compatibility date the same way as an explicit nodejs_compat flag. Node.js globals continue to come from @types/node instead of being generated as any declarations that override those types.
#15196 8fb2b87 Thanks @skepticfx! - Use the FedRAMP High managed container registry when Wrangler targets the FedRAMP High compliance region
Container builds, pushes, deployments, image commands, and local development now select the corresponding production or staging FedRAMP registry and API from either compliance_region or CLOUDFLARE_COMPLIANCE_REGION.
#15082 75cf407 Thanks @penalosa! - Enable the new configuration format in the cf-wrangler dev delegate
Projects started through cf dev now load cloudflare.config.ts and optional wrangler.config.ts, matching the configuration used by the delegate's build path.
Updated dependencies [1277a72, 4f922dc, 4d74b8d, 2e0c962, 8777180]:
You can now configure a mock Cloudflare Access identity in wrangler.json so that ctx.access.getIdentity() returns it during local development.
#15113 b8fd112 Thanks @BSFishy! - Add local dev simulation for Cloudflare Access ctx.access.getIdentity()
You can now configure a mock Cloudflare Access identity in wrangler.json so that ctx.access.getIdentity() returns it during local development.
// wrangler.json
{
"access": {
"dev": {
"aud": "my-app-aud-tag",
"identity": {
"email": "user@example.com",
"name": "Test User"
}
}
}
}
#15152 f0f2054 Thanks @GregBrimble! - [private beta]: Updates the --ignore-defaults flag to --ignore-base-config on wrangler preview commands.
--ignore-base-config now only takes effect on Preview creation, rather than on each deployment, since Preview base configuration is now copy-on-create rather than inherit-on-deploy.
#14872 339509d Thanks @dario-piotrowicz! - Add automatic update prompts for out-of-date Cloudflare agent skills
When Cloudflare skills were previously installed by Wrangler and the upstream cloudflare/skills repository has newer content, Wrangler now offers to update them after eligible commands complete.
To reduce prompt fatigue, the update check only runs once a month (30 days since the last install or update). Declining suppresses the prompt until the next upstream change.
When declining an update, Wrangler offers the option to permanently disable future update prompts. This preference is stored globally in ~/.wrangler/agents-skills-install.jsonc. The WRANGLER_NO_SKILLS_UPDATE_PROMPTS=true environment variable can also be used to suppress prompts. The --install-skills flag remains available regardless of these settings.
b8fd112]:
As of compatibility date 2026-08-04, workerd enables the nodejs_compat and nodejs_compat_v2 compatibility flags by default. Previously these tools onl
#15123 d0c976c Thanks @dependabot! - Detect Node.js compatibility from the compatibility date, now that nodejs_compat is enabled by default
As of compatibility date 2026-08-04, workerd enables the nodejs_compat and nodejs_compat_v2 compatibility flags by default. Previously these tools only treated Node.js compatibility as enabled when one of those flags was listed explicitly, so a Worker on a compatibility date of 2026-08-04 or later without the flag would get Node.js APIs from the runtime but no Node.js polyfills from the bundler, and process.env could be substituted with an empty object at build time. They now resolve these flags the same way workerd does, and honour no_nodejs_compat to opt out.
To keep Node.js compatibility switched off on a newer compatibility date, specify both no_nodejs_compat and no_nodejs_compat_v2, since each flag has its own default.
@cloudflare/vitest-pool-workers needs nodejs_compat_v2 for its own test runner, so it continues to override a project that opts out of it. On a compatibility date that enables the flag anyway, it now drops the opt-out rather than adding the flag back, which workerd would reject — previously this stopped such a project from running any tests at all.
wrangler types also no longer attributes its @types/node suggestion to "the nodejs_compat flag", which it can now make for Workers that do not set the flag at all.
#15123 d0c976c Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260804.1 | ^5.20260811.1 |
| workerd | 1.20260804.1 | 1.20260811.1 |
#15148 0b82b15 Thanks @jamesopstad! - Ignore a nodejs_compat compatibility flag that the compatibility date already enables
workerd rejects a compatibility flag that its compatibility date enables by default, so a Worker configured with both a compatibility date of 2026-08-04 or later and nodejs_compat failed to start locally with "The compatibility flag nodejs_compat became the default as of 2026-08-04 so does not need to be specified anymore".
The redundant nodejs_compat and nodejs_compat_v2 flags are now dropped when starting the runtime, which has no effect on the resulting Worker because the compatibility date enables both anyway. no_nodejs_compat and no_nodejs_compat_v2 still switch Node.js compatibility off, and a flag specified alongside its own opt-out is left alone so that workerd still reports those as contradictory.
#15123 d0c976c Thanks @dependabot! - Stop adding a redundant nodejs_compat flag to generated Wrangler configurations
create-cloudflare and wrangler setup write today's date as the compatibility_date, and from 2026-08-04 that already enables nodejs_compat. Adding the flag as well made the generated project fail to start with "The compatibility flag nodejs_compat became the default as of 2026-08-04 so does not need to be specified anymore", so the flag is now only added for earlier compatibility dates.
create-cloudflare also removes the flag when a template, or a framework's own scaffolder, already wrote it into a configuration that ends up using such a compatibility date, and still installs @types/node for these projects even though there is no longer a flag to detect them by.
wrangler setup does the same for a wrangler.json(c) that is already in the project: it writes today's date over whatever date that configuration was written for, so a nodejs_compat it finds there is removed as part of writing the file.
#15142 3b02915 Thanks @penalosa! - Fix remote binding sessions reusing stale binding configurations
Starting a new remote bindings session that reuses a Worker name no longer picks up the bindings from a previous session, which could cause Binding "..." not found errors.
Updated dependencies [d0c976c, d0c976c, 0b82b15, d0c976c, 90dd5e5]:
Wrangler now manages Worker Preview base config secrets with wrangler preview base-config secret put, delete, list, and bulk. These commands update th
#15079 15cad03 Thanks @podonnell-dev! - Add Preview base config secret commands
Wrangler now manages Worker Preview base config secrets with wrangler preview base-config secret put, delete, list, and bulk. These commands update the Worker's previews_base_config.env, keeping shared defaults scoped to all of that Worker's Previews. wrangler preview base-config secret list reads from the Worker's Preview base config and prints secret names with values masked. wrangler preview base-config secret bulk deletes a secret when its value is null, matching wrangler secret bulk.
#15000 731b33a Thanks @edmundhung! - Allow Wrangler projects to build a Worker once and reuse it in createTestHarness()
Build the Worker once:
wrangler deploy --dry-run --outdir ./worker-output
Then reuse the emitted Worker during test harness startup and reset:
const server = createTestHarness({
workers: [
{
configPath: "./wrangler.jsonc",
prebuiltWorkerDir: "./worker-output",
},
],
});
#14737 e1b5b4b Thanks @ttoino! - Add email.sending as an event subscription source for queues
wrangler queues subscription create now accepts --source email.sending alongside two new flags, --zone-id and --domain, which identify the zone and the sending domain (zone apex or a verified subdomain) to subscribe to. Both flags are required for this source. The subscription's resource is displayed as the sending domain in wrangler queues subscription get.
#15073 d669088 Thanks @FlorentCollin! - Add US jurisdiction support to wrangler d1 create
You can now create a D1 database in the US jurisdiction with wrangler d1 create <name> --jurisdiction us. The new jurisdiction is also listed in the command's help output.
#15079 15cad03 Thanks @podonnell-dev! - Use Preview deployment PATCH APIs for Preview secret commands
Wrangler now updates Worker Preview secrets by patching the named Preview's latest deployment instead of patching the Worker's Previews settings. This keeps secret changes scoped to one Preview, avoids affecting production or other Previews, and creates a new Preview deployment that goes live at 100% immediately. wrangler preview secret list now reads from the named Preview's latest deployment and prints secret names with values masked. wrangler preview secret bulk now deletes a secret when its value is null, matching wrangler secret bulk.
#14924 0aa8fa5 Thanks @ariesclark! - Honor DO_NOT_TRACK=1 as a telemetry opt-out
Wrangler now disables telemetry when DO_NOT_TRACK=1 is set, regardless of other telemetry settings.
#15081 026e058 Thanks @podonnell-dev! - Compact wrangler preview deployment success output
wrangler preview now prints a concise success summary with the Preview name, Preview URL, deployment ID, and Deployment URL instead of the previous box-art settings summary.
#15132 5b1b930 Thanks @dario-piotrowicz! - Fetch script metadata directly instead of listing all scripts
When resolving Durable Object migrations, fetch the specific script's service metadata via /workers/services/{name} instead of listing all scripts in the account via /workers/scripts. This avoids downloading metadata for every Worker in the account just to find one script's migration tag.
#15032 6e7d37d Thanks @Sertug17! - Fix wrangler dev commands crashing with No such module "wrangler:modules-watch" when "no_bundle": true
Running wrangler dev or wrangler pages dev with bundling disabled ("no_bundle": true in wrangler.json, or the --no-bundle flag) no longer crashes at startup with Uncaught Error: No such module "wrangler:modules-watch". Live reloading on file changes continues to work as before.
Updated dependencies [c7aede7]:
The following dependency versions have been updated:
#15072 6dbd192 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260801.1 | ^5.20260804.1 |
| workerd | 1.20260801.1 | 1.20260804.1 |
#14994 2194f88 Thanks @emily-shen! - Update local development for Miniflare's config-based options
Wrangler now converts the Miniflare options it creates for local development to Miniflare's config-based workers shape.
Users should not expect to notice any changes.
Updated dependencies [6dbd192, 2194f88, 2194f88, 2194f88, 2194f88, 2194f88, 2194f88]:
wrangler containers instances --search now searches every page and returns exact matches in human-readable or JSON output. JSON returns a top-level ar
#15008 35c87e9 Thanks @skepticfx! - Adds the ability to find container instances by exact ID or name
wrangler containers instances <application_id> --search <instance_id_or_name> now searches every page and returns exact matches in human-readable or JSON output. JSON returns a top-level array, including an empty array when there is no match, while human-readable output prints a no-match message. If multiple instances have the same exact name, every matching instance is returned.
#15008 35c87e9 Thanks @skepticfx! - Add explicit pagination to container instance JSON output
Use wrangler containers instances <application_id> --json --per-page <size> to return one page with machine-readable result_info, then pass its next_page_token to --page-token to retrieve the next page. Plain --json remains backward-compatible: it requests the complete list and returns the existing top-level array.
#15013 8cf78c8 Thanks @dario-piotrowicz! - Update undici from 7.28.0 to 7.29.0
#15015 a60ff4d Thanks @nickpatt! - Cut the per-request cost of local observability capture
Every tail event was written to the trace store as its own Durable Object call, so a request paid two or three round-trips per span. On a module-heavy app under the Vite plugin that dominated dev request latency. Rows are now buffered and written in batches, taking a request from roughly thirty calls to three.
Work in progress still shows up as it happens: the root span is written immediately, console logs and exceptions as they arrive, and a span's completion is written on the next event once 100ms has passed. An invocation that goes completely quiet writes nothing further until it ends, since the flush is driven by tail events rather than a timer.
The Vite plugin's own router, asset and proxy workers are also no longer captured. Their traces were noise the Observability views already hid, and skipping them cuts the spans recorded per request — a side benefit being that a trace's root is now your Worker rather than __router-worker__.
Updated dependencies [b4f0c97, 8cf78c8, a60ff4d, 99eb50c]:
wrangler ai-search create now accepts --parse-type to control how a website data source discovers URLs. sitemap (the default) reads XML sitemaps; disc
#14952 20470fa Thanks @nelsonjsduarte! - Add --parse-type flag to wrangler ai-search create
wrangler ai-search create now accepts --parse-type to control how a website data source discovers URLs. sitemap (the default) reads XML sitemaps; discover follows links recursively.
Previously the parse type could only be chosen through the interactive wizard, which was skipped whenever --source was supplied — so it was impossible to create a discover instance from a script.
wrangler ai-search create my-instance \
--type web-crawler \
--source https://example.com \
--parse-type discover
The interactive wizard now offers Discover alongside Sitemap. --parse-type is only valid with --type web-crawler; passing it with --type builtin or --type r2 is rejected, since the API stores the value for those source types but never reads it. When the flag is omitted in non-interactive mode the field is left unset and the API default (sitemap) applies.
#14941 266172b Thanks @nickpatt! - Improve the Local Explorer's Observability views
console.log messages now render the way the console would (JSON-encoded strings are unwrapped and multi-argument logs are joined), traces and events can be looked up by trace or span id from the search bar, and an event's "View trace" button jumps to the exact invocation that emitted it — even when a trace_id spans several invocations (e.g. a subrequest or self fetch).
#14064 a9e5abb Thanks @petebacondarwin! - Add support for OAuth 2.0 Device Authorization Grant to wrangler login
Run wrangler login --device to authenticate without a local callback server. Useful in containers, remote SSH sessions, Codespaces, and any other environment where localhost:8976 is unreachable from your browser.
The new flow:
--browser=false),The verification URL is supplied by the authorization server, so it is rejected unless it is an https URL on the same auth domain the device code was requested from — it is never printed or opened otherwise.
--callback-host and --callback-port cannot be combined with --device, since this flow does not start a local callback server.
#14984 9c74538 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260730.1 | ^5.20260731.1 |
| workerd | 1.20260730.1 | 1.20260731.1 |
#15012 0d33cb8 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260731.1 | ^5.20260801.1 |
| workerd | 1.20260731.1 | 1.20260801.1 |
Updated dependencies [9c74538, 0d33cb8, a88d169, a88d169, daf65f2]:
wrangler dev and the Vite plugin now capture request traces and console logs into the Local Explorer's Observability tab out of the box — previously t
#14057 cc63aae Thanks @matingathani! - Add --json flag to wrangler containers info for consistent JSON output with sibling commands list and instances
#14944 a249591 Thanks @nickpatt! - Enable local observability capture by default in dev
wrangler dev and the Vite plugin now capture request traces and console logs into the Local Explorer's Observability tab out of the box — previously this was opt-in behind X_LOCAL_OBSERVABILITY=true. Set X_LOCAL_OBSERVABILITY=false to opt out (for example if the extra per-worker collector/streaming-tail services cause trouble in a multi-process dev-registry setup).
#14919 e0bbf55 Thanks @avenceslau! - Add additional triggers to Workflows
Workers can now declaratively start a locally defined Workflow. Configure event subscriptions under triggers.events; Wrangler validates each target and updates the script's event triggers during deployment.
{
"triggers": {
"events": [
{
"type": "cf.artifacts.repo.pushed",
"filter": {
"namespace": "my-namespace",
"repo_name": "my-repo"
},
"targets": [
{
"type": "workflow",
"workflow_name": "my-workflow"
}
]
}
]
}
}
#14936 f92d1fc Thanks @petebacondarwin! - Fix jsx_fragment being ignored when wrangler dev runs a custom build
If your project uses a custom build and sets both jsx_factory and jsx_fragment, wrangler dev used your jsx_factory value for JSX fragments as well, so fragments compiled incorrectly. Your jsx_fragment value is now used.
#14936 f92d1fc Thanks @petebacondarwin! - Stop wrangler dev starting new work after you stop it or it reloads
Stopping wrangler dev, or having it reload after a configuration change, could still leave it starting work for the state it had just left behind: your custom build command could run once more after dev had stopped, a change to a file in your assets directory could be reported against configuration that had already been replaced, and in some cases the process could stay alive instead of exiting.
That work is now discarded, so stopping or reloading wrangler dev leaves nothing running behind it.
#14936 f92d1fc Thanks @petebacondarwin! - Stop wrangler dev from running custom builds concurrently
When several watched files changed at once — for example during a git pull or a "save all" — wrangler dev started a custom build for every file that changed, so multiple copies of your build command ran at the same time and fought over the same output files.
A burst of file changes now results in a single build, and a build only starts once the previous one has finished.
#13746 cec9d88 Thanks @edmundhung! - Report a clear error for account IDs that can't be used in a Cloudflare API request
Account IDs are substituted straight into Cloudflare API URL paths, so a value containing non-ASCII characters previously failed deep inside the request layer with an opaque Cannot convert argument to a ByteString error that gave no hint about which setting was at fault. Account IDs read from CLOUDFLARE_ACCOUNT_ID and from the account_id configuration field are now validated up front, and an invalid value fails with a message naming both the offending value and where it came from.
/cdn-cgi/mf/scheduled → /cdn-cgi/local/scheduled (Note /cdn-cgi/mf/scheduled is already deprecated)
#14586 5a56dda Thanks @emily-shen! - Remove containerEngine from the worker options returned by unstable_getMiniflareWorkerOptions
unstable_getMiniflareWorkerOptions no longer includes containerEngine in the returned workerOptions, since the container engine is a Miniflare instance-wide setting rather than a per-worker one. Callers that build a Miniflare instance from these options should set containerEngine at the top level instead.
#14586 5a56dda Thanks @emily-shen! - Rewrite local testing paths (/cdn-cgi/*)
Miniflare v5 moved its internal local testing endpoints to /cdn-cgi/local/* (and /__cf_local/* for endpoints that must remain reachable over tunnels) to prevent any potential collision with production routes. wrangler dev and the Vite plugin now transparently rewrite the old paths to the new ones, meaning you can continue to use the old paths without issue.
These are the new paths:
/cdn-cgi/handler/scheduled → /cdn-cgi/local/scheduled/cdn-cgi/handler/email → /cdn-cgi/local/email/cdn-cgi/explorer/* → /cdn-cgi/local/explorer/*/cdn-cgi/mf/scheduled → /cdn-cgi/local/scheduled (Note /cdn-cgi/mf/scheduled is already deprecated)/cdn-cgi/mf/stream/* → /__cf_local/stream/*/cdn-cgi/mf/imagedelivery/* → /__cf_local/imagedelivery/*Updated dependencies [5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda, 5a56dda]:
Wrangler now derives the Worker name from the project and automatically registers the same project-derived workers.dev account subdomain on a first de
#14907 beec0fb Thanks @NuroDev! - Avoid Worker and workers.dev naming prompts in agent-driven deploys
Wrangler now derives the Worker name from the project and automatically registers the same project-derived workers.dev account subdomain on a first deploy when running in a detected agent environment. The deploy output explains how to change both names.
#14905 b21eac2 Thanks @jamesopstad! - The experimental build output directory now includes the Worker's configuration at .cloudflare/output/v0/workers/default/config.json instead of .cloudflare/output/v0/workers/<worker-name>/worker.config.json
#14893 bb09f1b Thanks @apeacock1991! - Graduate wrangler check startup from alpha and show bundle size and a local timing summary
The command no longer prints an alpha warning. It now reports its local profile window, sampled active, garbage collection, and idle time alongside the raw and compressed bundle sizes. The existing measurement warning continues to distinguish these local measurements from startup time measured on Cloudflare.
#14685 01d7020 Thanks @edmundhung! - Add support for dispatching email handlers with createTestHarness
You can now call server.getWorker().email({ from, to, raw }) to dispatch directly to a Worker's email() handler and inspect its outcome, rejection reason, forwarded messages, and replies.
const result = await server.getWorker().email({
from: "sender@example.com",
to: "inbox@example.com",
raw: [
"From: Sender <sender@example.com>",
"To: Inbox <inbox@example.com>",
"Message-ID: <test@example.com>",
"Subject: Test email",
"",
"Hello from the test harness",
].join("\r\n"),
});
expect(result).toMatchObject({
outcome: "ok",
forwards: [{ recipient: "archive@example.com" }],
replies: [
{
sender: "inbox@example.com",
raw: expect.stringContaining("Thanks for your email"),
},
],
});
#14929 48f0c6c Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260722.1 | ^5.20260730.1 |
| workerd | 1.20260722.1 | 1.20260730.1 |
#14838 8049ca4 Thanks @TheSaiEaranti! - Fix ctrl+c not being able to interrupt wrangler while waiting for Cloudflare Access authorization
When a domain is behind Cloudflare Access (for example during remote bindings startup), wrangler runs cloudflared access login, which only returns once the user completes the authorization flow in the browser. This was invoked synchronously, blocking Node's event loop, so wrangler could not react to ctrl+c (or anything else) until the authorization completed — abandoning the browser flow left a hung wrangler process that had to be killed externally. cloudflared is now spawned asynchronously, keeping wrangler responsive while it waits. The remote runtime passes its abort signal through to the spawn, so tearing down the session kills a still-pending cloudflared immediately, with process exit as a last-resort cleanup.
#14871 1394867 Thanks @nickpatt! - Include the local observability query endpoint in the agent-facing Local Explorer hint
The hint wrangler dev prints for AI-agent sessions now lists POST /cdn-cgi/explorer/api/local/observability/query, so agents can discover the read-only SQL endpoint for captured request traces and console logs (the spans and logs tables) alongside the existing binding and storage routes.
#14918 cc54478 Thanks @nickpatt! - Improve the agent-facing Local Explorer hint for the observability query endpoint
When a wrangler dev session is detected as running inside an AI agent, the hint for POST /local/observability/query now explains that the endpoint takes a read-only SQL query (SELECT/WITH only) over the captured spans and logs tables, notes that attributes is JSON (read via json(attributes)), and includes a copy-pasteable curl example. The full OpenAPI schema is demoted to a last-resort footer so agents reach for the small, actionable example first instead of fetching the large schema.
#14897 e31ab0f Thanks @ericclemmons! - Fix wrangler triggers deploy to use Vite-generated redirected configuration
The command now reads .wrangler/deploy/config.json, matching wrangler deploy and wrangler versions upload, so generated Worker names and trigger settings are applied.
Updated dependencies [01d7020, 48f0c6c, d7f38c3, 5c25cfe, 1f61001]:
This option creates a KV namespace within a specific jurisdiction (for example us, eu, or fedramp), backing it with jurisdiction-scoped storage. It is
#14807 4dfb96e Thanks @oOPa! - Add hidden --jurisdiction option to wrangler kv namespace create for internal testing
This option creates a KV namespace within a specific jurisdiction (for example us, eu, or fedramp), backing it with jurisdiction-scoped storage. It is experimental and currently gated to allow-listed accounts, so it is hidden from --help until the feature is generally available.
#14280 465c0fb Thanks @tahmid-23! - Add experimental local_dev.experimental_s3_credentials to r2_buckets config
When set, the R2 bucket is served over a local S3-compatible API at /cdn-cgi/local/r2/s3/<bucket-id> during local development, authenticated with the configured AWS SigV4 credentials. <bucket-id> is the bucket's bucket_name, or the binding name if bucket_name is not set:
{
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-bucket",
"local_dev": {
"experimental_s3_credentials": {
"accessKeyId": "local-access-key-id",
"secretAccessKey": "local-secret-access-key"
}
}
}
]
}
#14877 552bcfc Thanks @jasoncabot! - Respect and surface the Retry-After header on Cloudflare API responses
Previously, if a Wrangler command (e.g. wrangler versions upload, wrangler deploy) hit the Cloudflare API's rate limit, the resulting error gave no indication of how long to wait before trying again, and 429 responses weren't retried at all (only 5xx errors were, with a fixed linear backoff).
Now:
429 Too Many Requests responses are automatically retried, alongside the existing 5xx retry behaviour.Retry-After header, Wrangler waits for that duration instead of the default backoff, and logs a message indicating how long it's waiting. To avoid blocking for an excessive amount of time, waits longer than 60 seconds fail fast instead — the surfaced Retry-After value lets the caller schedule its own retry.Retry-After duration, and the command-failed entry written to the Wrangler output file (WRANGLER_OUTPUT_FILE_PATH/WRANGLER_OUTPUT_FILE_DIRECTORY) gains a retry_after_ms field. This lets scripts and CI/CD pipelines calling Wrangler repeatedly (for example, wrangler versions upload on every commit) read the wait duration directly instead of regex-parsing stderr.APIError.isRetryable() is unchanged (still 5xx only); retryOnAPIFailure() separately retries 429s. retryAfterMs, when present, is honoured for any retried error, not just 429s.
retryAfterMs is also now populated on APIErrors raised from direct R2 object requests, the Browser Rendering API, and errors surfaced from commands using the official cloudflare SDK client.
#14712 6e0bf6e Thanks @mack-erel! - Support connect() on remote VPC Network and VPC Service bindings in local development
Remote VPC Network and VPC Service bindings previously only supported HTTP and JSRPC, so calling binding.connect(address) against a private TCP service (for example a database) failed in local dev with Incoming CONNECT on a worker not supported. Raw TCP connections through remote VPC Network and VPC Service bindings now work in local development.
This feature is experimental. Existing HTTP and JSRPC usage of remote VPC Network and VPC Service bindings is unaffected, and no new configuration is required.
#14833 773ead4 Thanks @DiogoSantoss! - Color Email Routing plan change markers
Wrangler now highlights additions in green, updates in yellow, and deletions and conflicts in red so Email Routing deployment plans are easier to scan before confirmation.
#14833 773ead4 Thanks @DiogoSantoss! - Apply Email Routing changes across independent zones concurrently
Wrangler now limits concurrent zone updates while preserving the Email Routing plan order within each zone. Deployments that configure addresses across multiple zones complete faster without breaking delete-before-add transitions at a zone's rule limit.
#14815 09b8a44 Thanks @chinesepowered! - Fix wrangler cloudchamber curl mangling header values that contain a colon
Header values were split on every colon and only the segment between the first and second was sent, so --header location:https://example.com/x arrived as https. Headers are now split on the first colon only. A header that is not in the documented --header <name>:<value> form previously threw an unhandled TypeError, and now reports a clear error.
#14806 e8b3a9d Thanks @akim136! - Handle and explain authentication failures from remote bindings during local development
Wrangler now recognizes authentication failures from remote preview sessions and reports that bindings which need to run remotely require Cloudflare authentication even when the rest of the Worker is developed locally.
#14801 b737676 Thanks @emily-shen! - Speed up old debug log cleanup by reading each log file's date from its filename instead of stat-ing every file
Wrangler periodically deletes debug log files older than 30 days from its logs directory. Previously it made a filesystem stat call for each file to read its modification time; it now derives the age from the timestamp already encoded in the log filename, avoiding that extra work.
Updated dependencies [1035f74, e426cb9, 3a22ae5, 465c0fb, 6e0bf6e]:
wrangler dev and the Vite plugin now capture a trace for every local Worker invocation - spans, logs, and console.* output, including requests that cr
#14633 3203b5d Thanks @nickpatt! - Add local-dev observability
wrangler dev and the Vite plugin now capture a trace for every local Worker invocation - spans, logs, and console.* output, including requests that cross worker or Durable Object boundaries.
You can explore this data two ways:
/cdn-cgi/explorer/api/local/observability/query, discoverable via the Local Explorer's OpenAPI document, so coding agents and tools can query the same spans and logs tables.While this is in testing it's off by default; set X_LOCAL_OBSERVABILITY=true to turn it on. It will be on by default in the public release.
#14373 246ce92 Thanks @Jacroney! - Improve the D1 database-limit error message
When creating a D1 database fails because the account has hit its database limit, the error now points to the relevant next steps — upgrading on the Workers Free plan or requesting a higher limit on a paid plan — alongside the existing commands to list and delete databases. Previously it only suggested deleting unused databases. This applies both to wrangler d1 create and to the D1 database that is created during resource provisioning on deploy.
#14796 c38a2c3 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260721.1 | ^5.20260722.1 |
| workerd | 1.20260721.1 | 1.20260722.1 |
#14788 8416b33 Thanks @chinesepowered! - Fix grammar in the container image-too-large error
The error thrown when a container image exceeds the available disk size ended with "Your need more disk for this image." It now reads "You need more disk for this image."
#14809 4683ff8 Thanks @jamesopstad! - Ignore the removed legacy_env field when reading a redirected configuration
Older versions of tools such as the Vite plugin can generate a redirected configuration (.wrangler/deploy/config.json) that still includes the removed legacy_env field. Since these files are tool-generated, users could not easily remove the field themselves, and Wrangler would error out. Wrangler now silently strips legacy_env from redirected configurations. User-authored configurations still report an error so that the field can be removed.
#14593 02232f3 Thanks @spk-ai! - Fix dev proxy silently hanging or returning a misleading 503 on network errors for non-root-path requests
During wrangler dev, a transient network error on any request path other than / could be misclassified as the worker being reloaded, even when it wasn't: GET/HEAD requests would silently hang (with nothing logged) until the client timed out, and other methods would receive a misleading Your worker restarted mid-request 503. Such errors are now reported and surfaced immediately when the worker has not actually changed.
#14797 f8a8c2c Thanks @roerohan! - Explain how to provision Flagship bindings if app_id missing in remote development
Wrangler now reports that a Flagship binding without an app_id must first be created with wrangler flagship apps create.
Updated dependencies [c38a2c3, c079ba3, 95b026e, c4bacec, 3203b5d]:
Worker trigger deployment now reconciles the Worker's Email Routing rules with the top-level addresses config. This runs for wrangler deploy, wrangler
#14471 f03b108 Thanks @DiogoSantoss! - Apply Email Routing addresses during Worker trigger deployment
Worker trigger deployment now reconciles the Worker's Email Routing rules with the top-level addresses config. This runs for wrangler deploy, wrangler triggers deploy, and clients of @cloudflare/deploy-helpers. After the Worker uploads, or when wrangler triggers deploy runs after a version promotion, the deploy helper asks the Email Routing API for a plan, renders the changes grouped by zone (+ added, ~ updated, - deleted, ! conflict), prompts once for destructive changes in interactive mode, and applies accepted changes through the per-zone rule endpoints. Purely additive plans apply without a prompt, while non-interactive destructive plans fail without modifying rules.
#14679 deae171 Thanks @dario-piotrowicz! - Add exclude_packages option to dependencies_instrumentation configuration
The dependencies_instrumentation config object now accepts an optional exclude_packages field — an array of package name patterns (with glob-style * wildcards) to exclude from the dependency metadata collected during deploy and version uploads.
// wrangler.json
{
"dependencies_instrumentation": {
"exclude_packages": ["@internal/*", "secret-tool"]
}
}
#14721 4e92e32 Thanks @dmmulroy! - Support Artifacts sources when creating Queue event subscriptions
wrangler queues subscription create now accepts the artifacts and artifacts.repo source types supported by the Cloudflare API.
#13352 d1d6945 Thanks @penalosa! - Expand automatic resource provisioning to Queue, Dispatch Namespace, and Flagship bindings
Deployments can now omit the resource name or ID for these bindings. Wrangler will inherit the existing binding on subsequent deploys, create a deterministically named resource automatically, or offer existing resources during an interactive deploy with automatic creation disabled.
#14688 a0c8bb1 Thanks @NuroDev! - Print Local Explorer API details for headless agent-driven wrangler dev sessions
When wrangler dev is started in a headless AI agent environment, Wrangler now prints the Local Explorer API URL and basic resource routes so agents can inspect local Workers and bindings without relying on the interactive UI.
#14724 a50f73a Thanks @jamesopstad! - Add a settings export to the experimental cloudflare.config.ts config
Account-level settings (accountId, complianceRegion) now live in a dedicated, named settings export authored via defineSettings, rather than on the Worker config. A cloudflare.config.ts can export at most one settings object; the Worker itself is the default export.
// cloudflare.config.ts
import { defineSettings, defineWorker } from "wrangler/experimental-config";
import * as entrypoint from "./src/index.ts" with { type: "cf-worker" };
export const settings = defineSettings({
accountId: "<your-account-id>",
});
export default defineWorker({
name: "my-worker",
entrypoint,
compatibilityDate: "2026-05-18",
});
This is only used behind the experimental new-config path (wrangler --experimental-new-config and the @cloudflare/vite-plugin experimental.newConfig option).
#14595 2b390d7 Thanks @colinhacks! - Recognise nub as a package manager
wrangler now detects nub — from its npm_config_user_agent and an installed nub binary — and autoconfig detects nub projects by their nub.lock, alongside npm, pnpm, yarn, and bun.
#14742 34430b3 Thanks @pombosilva! - Add support for redacting sensitive Workflows step output in local dev.
Steps configured with sensitive: "output" now have their output redacted to [REDACTED] in step logs and step-output responses when running Workflows locally, matching production behavior. The real value is still passed to downstream steps, and step errors are never redacted.
#14715 42af66d Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260714.1 | ^5.20260721.1 |
| workerd | 1.20260714.1 | 1.20260721.1 |
#14744 a0a091b Thanks @penalosa! - Drop the "Experimental:" prefix from the resource provisioning header now that automatic provisioning is generally available. The deploy output now reads The following bindings need to be provisioned:.
#14720 0df3d43 Thanks @penalosa! - Fix remote binding previews for accounts without a workers.dev subdomain
Wrangler now automatically registers a workers.dev subdomain when one is required to start a remote binding preview.
#14773 d83a476 Thanks @chinesepowered! - Fix stray characters in the Workers Sites asset-key-too-long error
The error thrown when an asset path key exceeds the 512-character limit ended with a stray ", copy-paste artifact, so the message printed to users terminated with ...#kv-limits", and the trailing documentation URL was malformed. The message now ends cleanly at the URL.
#14766 4815711 Thanks @gianghungtien! - Report the Worker's error for HEAD requests instead of an internal JSON parse error
A Worker that threw on a HEAD request (for example curl -I) logged SyntaxError: Unexpected end of JSON input from miniflare's internals rather than the actual error, and dispatchFetch() rejected with that same misleading error. workerd drops response bodies for HEAD requests, so the serialised error never reached the code that revives it.
The error is now also carried in a header, which survives HEAD, so the original message and source-mapped stack are reported for every method. When no payload is available the reporting degrades to a plain error rather than surfacing a parse failure.
#14448 c82d96b Thanks @GregBrimble! - Use the new PATCH APIs for versioned secret commands
Wrangler now updates versioned Worker secrets by patching the latest Worker version instead of downloading the latest version contents and uploading a full replacement version. This avoids reconstructing Worker configuration in Wrangler, which should reduce bugs when Workers use less common features. For example, this avoids regressions like the previous placement preservation bug fixed in #13843.
#14617 f75ae5d Thanks @martijnwalraven! - Derive nodejsCompatMode from the effective compatibility inputs in unstable_startWorker()
The CLI computes the node-compat mode from the effective compatibility date and flags (args.* ?? parsedConfig.*), but the programmatic path used input.build.nodejsCompatMode raw — leaving it unset meant a worker's nodejs_compat flag (from its config file or from input-level compatibilityFlags) was silently ignored, so bundling failed to resolve node builtins that wrangler dev handles. startWorker now derives the mode the same way when the caller does not provide one: input-level compatibilityDate/compatibilityFlags first, then the resolved config, with no-bundle taken from the resolved build.bundle semantics. Passing an explicit null still disables it.
Updated dependencies [42af66d, 4815711, 34430b3]:
You can now declare the inbound email addresses handled by your Worker directly in wrangler.json:
#14470 3de70df Thanks @DiogoSantoss! - Add a top-level addresses field to Wrangler configuration for Email Routing
You can now declare the inbound email addresses handled by your Worker directly in wrangler.json:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2026-05-21",
"addresses": ["support@example.com", "*@example.com"]
}
#14706 cb6c3f9 Thanks @edmundhung! - Add Durable Object storage access to createTestHarness()
You can now execute SQL against a SQLite-backed Durable Object to seed or assert the storage state.
const server = createTestHarness({
workers: [{ configPath: "./wrangler.json" }],
});
await server.listen();
const worker = server.getWorker();
const storage = await worker.getDurableObjectStorage("COUNTER", {
name: "user-123",
});
await worker.fetch("/counter/user-123");
const rows = await storage.exec(
"SELECT value FROM counters WHERE id = ?",
"user-123"
);
expect(rows).toEqual([{ value: 1 }]);
#14562 9f04a7e Thanks @martijnwalraven! - Emit a typed runtimeError event on the unstable_startWorker DevEnv for uncaught Worker exceptions
Uncaught Worker exceptions were only source-mapped and printed, so programmatic consumers had to scrape terminal output to observe them. The DevEnv now re-emits a RuntimeErrorEvent (like reloadComplete) carrying the exception text and source-mapped stack — fed from Miniflare's pretty-error seam via the new handleUncaughtError option for exceptions the runtime catches, and from the inspector for those it does not.
#14682 d39ae01 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260710.1 | ^5.20260714.1 |
| workerd | 1.20260710.1 | 1.20260714.1 |
#14725 c79504f Thanks @edmundhung! - Support containers in createTestHarness()
Workers configured with containers can now be tested using createTestHarness(). The harness builds configured images and makes container-backed Durable Objects available during integration tests.
#14696 c7dbe1a Thanks @martijnwalraven! - Type unstable_startWorker, DevEnv.startWorker, and ConfigController.set/patch against WranglerStartDevWorkerInput, so the wrangler-specific dev.structuredLogsHandler field the runtime already honors is expressible through the public API. Previously the public signatures took the base StartDevWorkerInput, and callers passing the handler needed a cast while internal callers (the test harness) routed the wider type around the signature.
#14494 4e1a7a7 Thanks @petebacondarwin! - Register a workers.dev subdomain before uploading a new Worker
Deploying a Worker for the first time on an account that has no workers.dev subdomain failed with an opaque API error raised by the upload request itself (code 10063, "You need a workers.dev subdomain in order to proceed"). Wrangler now checks for a workers.dev subdomain before uploading a brand-new Worker that publishes to workers.dev and prompts you to register one, so you get a clear, actionable message instead of a cryptic API failure. The check is skipped for deploys that don't target workers.dev (routes-only deploys, or workers_dev: false) and for existing Workers, since their account already has a subdomain.
Updated dependencies [34e696d, d39ae01, 9f04a7e, 9f04a7e, cb30df3, cb6c3f9, 3f3afbb, e6fbc4e]:
You can now gracefully evict a running Durable Object by class name or binding name to verify how it recovers after its instance is torn down:
#14602 7692a61 Thanks @edmundhung! - Add Durable Object eviction support to createTestHarness
You can now gracefully evict a running Durable Object by class name or binding name to verify how it recovers after its instance is torn down:
const worker = server.getWorker();
await worker.evictDurableObject("Counter", { name: "user-123" });
#14620 899c297 Thanks @penalosa! - Remove support for service environments and the legacy_env configuration field
Service environments have been removed. Wrangler now always deploys each environment as its own Worker named <name>-<environment>, which matches the behaviour of the previous default (legacy_env = true). The --legacy-env CLI flag has been removed, and the legacy_env configuration field is no longer supported — including it in your configuration file will now raise an error.
Because legacy_env = true was already the default, removing the field will not change how your Worker is deployed. If you were relying on service environments (legacy_env = false), each environment will now be deployed as a standalone Worker instead of as an environment of a single Worker. See https://developers.cloudflare.com/workers/wrangler/environments/ for more information.
#14652 317ce1f Thanks @jamesopstad! - Append Workers runtime types to the generated types under --x-new-config, with a new dev.types.includeRuntime option
When running wrangler dev --x-new-config, the runtime types generated from your compatibility date and flags are now appended to worker-configuration.d.ts, alongside the types inferred from cloudflare.config.ts. This is controlled by a new dev.types.includeRuntime option in wrangler.config.ts, which defaults to true.
This applies to the experimental new config path only and does not change type generation for existing wrangler.jsonc/wrangler.toml projects.
#14627 ed33326 Thanks @tpmmorris! - Add convenient logging for worker emails in the project directory. In addition to the system's temp directory, logs for emails sent by workers are also written to a local temp directory defined by the calling process, e.g for an simple text email sent via Wrangler this is .wrangler/tmp/email/<session>/email-text/<message-uuid>.txt (and related files) in the project root. Callers of Miniflare can control this location via the new defaultProjectTmpPath option, which Wrangler and Vite plugin now set automatically.
#14642 018574b Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| @cloudflare/workers-types | ^5.20260708.1 | ^5.20260710.1 |
| workerd | 1.20260708.1 | 1.20260710.1 |
#14588 eb99ab1 Thanks @emily-shen! - fix: Respect auth profiles when using remote bindings in the Vite plugin
Auth profiles (configured via wrangler auth create and wrangler auth activate) were previously being ignored when using remote bindings with the Vite plugin. This is now fixed.
Note that the profile directory is resolved based on the Vite project root.
#14658 cdf3148 Thanks @ATKasem! - Fix wrangler dev corrupting external hostnames in proxied response headers
When a Worker was run with routes configured, wrangler dev's proxy rewrote the host inside URL-valued headers (such as Location) using a boundary-less substring replace. Any host that merely contained the route host as a substring was corrupted — e.g. with an example.com route, a Location: https://books.example.com/read/ch01 header became https://books.127.0.0.1:8788/read/ch01, and https://myexample.com/path became https://my127.0.0.1:8788/path.
The proxy now only rewrites absolute URLs whose host is exactly the proxied host, swapping the scheme and host together (which also fixes a related case where an https: scheme survived on a plain-HTTP dev address). Unrelated hosts and subdomains pass through untouched.
#14601 3015320 Thanks @MattieTK! - Improve the agent-facing --force guidance for Pages-to-Workers delegation
When an AI agent opts out of the Pages-to-Workers delegation by passing --force to wrangler pages deploy or wrangler pages project create, Wrangler now prints a notice at the end of a successful command explaining that --force only needs to be passed once: the project then exists, so subsequent commands are no longer delegated and do not need the flag.
#14569 9da77ac Thanks @dario-piotrowicz! - Suggest similar commands when a typo is detected
When an unknown command or subcommand is entered, wrangler now suggests the closest matching command if one exists within a reasonable edit distance. For example, running wrangler whoamio will display Did you mean "wrangler whoami"?, and running wrangler kv namespase will display Did you mean "wrangler kv namespace"?.
Updated dependencies [7692a61, ed33326, 018574b, 7692a61]:
This enables dependency analytics and future features like vulnerability alerting.
#14591 0283a1f Thanks @dario-piotrowicz! - Send npm package dependency metadata with worker uploads
Wrangler now collects npm package dependency information from the project's package.json at deploy and version upload time, and includes it in the upload metadata sent to the Cloudflare API. This enables dependency analytics and future features like vulnerability alerting.
The collected data includes the package name, the version constraint from package.json, and the exact installed version from node_modules. Both dependencies and devDependencies are included, while workspace packages, local packages, and unresolvable packages are excluded. The list is capped at 200 entries per upload.
To opt out, set dependencies_instrumentation.enabled to false in your Wrangler configuration file:
{
"dependencies_instrumentation": {
"enabled": false
}
}
#14535 1b965c5 Thanks @Naapperas! - Support dynamic retry delays for Workflow steps in local dev
A step's retries.delay can now be a function that computes the delay per failed attempt, in addition to a static duration. The function receives { ctx, error } and returns a delay (a number of milliseconds or a duration string like "30 seconds"), and its result is fed into the configured backoff.
await step.do(
"call flaky API",
{
retries: {
limit: 5,
backoff: "constant",
delay: ({ ctx }) => ctx.attempt * 1000,
},
},
async () => {
/* ... */
}
);
The function is invoked once per failed attempt with a 5 second timeout. If it throws, times out, or returns an invalid value, the step fails without further retries.
#14589 7b28392 Thanks @jamesopstad! - Fix runtime type caching when wrangler dev auto-regenerates types
When dev.generate_types (or wrangler dev --types) regenerated an out-of-date worker-configuration.d.ts, the written file omitted the // Begin runtime types marker (and the /* eslint-disable */ header) that wrangler types writes. As a result, later runs could not detect the cached runtime types and always regenerated them. The auto-regenerated file now matches wrangler types output, restoring the cache.
Updated dependencies [1b965c5]:
Tests using createTestHarness can now list persisted Durable Object instance IDs for a Durable Object binding. This helps integration tests discover o
#14489 e3f0cd6 Thanks @edmundhung! - Add listDurableObjectIds() to createTestHarness Worker handles
Tests using createTestHarness can now list persisted Durable Object instance IDs for a Durable Object binding. This helps integration tests discover objects created by app behavior without adding test-only endpoints.
#14465 2fedb1f Thanks @vaishnav-mk! - Add rollback support when terminating Workflow instances
WorkflowInstance.terminate({ rollback: true }) now runs registered rollback handlers before marking a local Workflow instance as terminated. Wrangler also supports this via wrangler workflows instances terminate --rollback, including local mode.
The rollback option is only sent for terminate operations and is rejected by the Local Explorer API for pause, resume, and restart actions.
#14511 17d2fc1 Thanks @juleslemee! - Add wrangler turnstile widget commands for managing Turnstile widgets
You can now create, list, inspect, update, and delete Turnstile widgets from the CLI:
wrangler turnstile widget create <name> --domain example.com --mode managed
wrangler turnstile widget list
wrangler turnstile widget get <sitekey>
wrangler turnstile widget update <sitekey> --name "Renamed"
wrangler turnstile widget delete <sitekey>
All five subcommands accept --json for machine-readable output (get prints a formatted view by default; the rest print a short human summary). --domain accepts comma-separated values, e.g. --domain a.com,b.com. delete --json requires --skip-confirmation/-y to keep output pipeable.
create prints the sitekey, the secret, and the canonical challenges.cloudflare.com/turnstile/v0/siteverify endpoint for backend verification. The hint is backend-agnostic; it doesn't assume Workers. The secret is redacted from list and update output but remains available via get for retrieval later. delete prompts for confirmation; pass --skip-confirmation/-y to bypass.
The OAuth flow now requests the challenge-widgets.write scope (the existing Bach-derived scope for Turnstile widget CRUD). Existing OAuth sessions need to run wrangler login again to pick it up. API token users need a token with the Account.Turnstile:Edit permission.
#14596 8511ddf Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260706.1 | 1.20260708.1 |
| @cloudflare/workers-types | ^5.20260706.1 | ^5.20260708.1 |
#14604 9f74a5f Thanks @vaishnav-mk! - Improve the deploy error for cron-triggered Workflows on free plans
Wrangler now explains that Workflow schedules require a paid Workers plan instead of showing only the generic Workflows API request failure.
#14616 c782e2a Thanks @penalosa! - Fix wrangler deploy aborting in CI for autoconfigured projects
A recent change guarded non-interactive deploys against overwriting a same-named Worker whenever there was no config file naming it. This was too broad: a plain wrangler deploy run in CI without a config file (for example an autoconfigured project whose generated config PR has not been merged) would fail with "A Worker named ... already exists in your account", even though re-deploying to that Worker is the intended behaviour.
The guard is now limited to the Pages-to-Workers delegation, where the target name is a Pages project name that must not clobber an unrelated Worker. Plain deploys once again deploy normally.
Updated dependencies [e3f0cd6, 8511ddf, 2fedb1f]:
When wrangler pages deploy or wrangler pages project create is run by an AI coding agent against a brand-new, purely static project, Wrangler now dele
#14312 54f74b8 Thanks @MattieTK! - Delegate agent-driven static Pages deploys to Workers
When wrangler pages deploy or wrangler pages project create is run by an AI coding agent against a brand-new, purely static project, Wrangler now delegates it to Workers static assets (using autoconfig) instead of Cloudflare Pages. Accounts that already have Cloudflare Pages projects, non-agent (human) sessions, and projects using Pages features that can't be carried across to Workers (Pages Functions, a _worker.js, or a _routes.json file) are unaffected and continue to use Pages. Passing --force to either command opts out of the delegation and deploys to Pages directly. Once the Workers deploy starts it is not silently swapped back to Pages: if it fails, the error is surfaced and the --force opt-out is suggested.
#14567 0852346 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler", "create-cloudflare"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260702.1 | 1.20260706.1 |
| @cloudflare/workers-types | 4.20260702.1 | 5.20260706.1 |
#14312 54f74b8 Thanks @MattieTK! - Avoid silently overwriting an existing Worker during non-interactive deploys that cannot prove they own the name
A non-interactive deploy (an agent, CI, or the agent-delegated wrangler pages deploy) has no way to prompt before overwriting a Worker, so it now stops if the target name is already taken and this run cannot show it owns that Worker. This applies when there is no Wrangler configuration file naming the Worker and either the name was generated automatically or the deploy is the Pages-to-Workers delegation (where the name carried across is a Pages project name, not proof of Worker ownership). The check reuses the service metadata the deploy already fetches, so it adds no extra API calls.
Deploys are unaffected when a configuration file names the Worker (so repeat deployments continue to update it), and interactive deploys keep their existing confirmation flow. To update an existing Worker in one of the guarded cases, add a Wrangler configuration file naming it, or deploy under a different name.
Updated dependencies [0852346]:
The following dependency versions have been updated:
#14514 d88555e Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260701.1 | 1.20260702.1 |
#14564 5fd8bee Thanks @jibin7jose! - Fix an issue where wrangler dev would not override config vars with values from .dev.vars during local development when the secrets field was defined in the configuration file.
#14332 5d9990e Thanks @Divkix! - Fix misleading error guidance when deploying a new Worker with secrets.required
When a Worker declares secrets.required and has never been deployed before, the previous error message suggested running wrangler secret put <NAME>, which doesn't work because the Worker doesn't exist yet.
The one path that does work — wrangler deploy --secrets-file <path> — was not mentioned anywhere in the error output.
The pre-deploy error now explains that wrangler secret put cannot be used for a new Worker, and directs users to the --secrets-file flag instead. The post-deploy error for existing Workers now also mentions --secrets-file alongside wrangler secret put.
#14507 bf49a41 Thanks @joey727! - Fix a potential crash when displaying certain CLI output
Previously, some CLI output with no content lines could cause a crash. This is now handled correctly.
#14492 1ac96a1 Thanks @penalosa! - Replace the CommonJS xdg-app-paths dependency with a vendored pure-ESM implementation
xdg-app-paths (and its xdg-portable/os-paths dependencies) are CommonJS only, which caused "Dynamic require of 'path' is not supported" errors when the surrounding code was bundled to ESM. The global config/cache directory resolution is now provided by a small, dependency-free pure-ESM module in @cloudflare/workers-utils that reproduces the previous path resolution exactly (verified against the real package in unit tests), so existing config and credential locations are unchanged. This also drops the transitive fsevents optional dependency that xdg-app-paths pulled in.
Miniflare and create-cloudflare now consume the shared helpers from @cloudflare/workers-utils instead of maintaining their own copies, importing node-only leaf entry points (@cloudflare/workers-utils/fs-helpers, @cloudflare/workers-utils/global-wrangler-config-path) where ESM bundling is required.
#14572 f416dd9 Thanks @petebacondarwin! - Key local rate limit counters by namespace_id instead of binding name
wrangler dev and Miniflare previously tracked each rate limit binding's counter by its binding name, so two bindings that referenced the same namespace_id were treated as separate limiters. Counters are now keyed by namespace_id, matching production: bindings that share a namespace_id share a limit, while distinct namespaces stay isolated. This also re-enables rate limit bindings in multiworker wrangler dev sessions, where they were previously stripped from secondary Workers to avoid a startup crash.
#14570 1ca8d8f Thanks @penalosa! - Upgrade signal-exit from v3 to v4
The bundled signal-exit dependency was CJS-only. Upgrading to v4 (which ships a dual ESM/CJS build) unblocks ESM output. Exit-cleanup behaviour is unchanged, though v4 no longer registers handlers for a few signals that are no longer supported by the OS (SIGUNUSED on Linux; SIGABRT/SIGALRM on Windows).
#14561 b973ed3 Thanks @martijnwalraven! - Emit an error event for watch-mode rebuild failures in unstable_startWorker
Initial build failures already dispatch an error event (surfaced as buildFailed on the DevEnv bus), but watch-mode rebuild failures were only logged from inside the esbuild plugin, so programmatic consumers had no way to observe them while dev kept serving the previous bundle. Rebuild failures now route through the same error path as initial-build failures: terminal output is unchanged and buildFailed fires symmetrically.
Updated dependencies [e7e5780, d88555e, 1ac96a1, f416dd9, 16fbf81]:
You can now set cache options on WorkerEntrypoint exports and configure cross-version cache behavior globally:
#14474 aa5d580 Thanks @WillTaylorDev! - Add cache options for WorkerEntrypoint exports
You can now set cache options on WorkerEntrypoint exports and configure cross-version cache behavior globally:
// wrangler.json
{
"cache": { "enabled": true, "cross_version_cache": true },
"exports": {
"default": {
"type": "worker",
"cache": { "enabled": false }
},
"Admin": {
"type": "worker",
"cache": { "enabled": true }
}
}
}
Wrangler sends the exports config to the deploy and version upload APIs alongside the global cache.enabled and cache.cross_version_cache settings. The platform resolves those global settings plus cache overrides on exports and validates which entrypoint names are cacheable.
#14382 fd92d56 Thanks @petebacondarwin! - Add support for declarative Durable Object exports
wrangler deploy now accepts an exports map in wrangler.json as a declarative alternative to the legacy migrations array.
Each entry in exports is keyed by Durable Object class name. type carries the export kind (currently always "durable-object"); the state field carries the lifecycle and defaults to "created" (live) when omitted:
{
"exports": {
// Provision a new Durable Object class (`MyDO`)
"MyDO": { "type": "durable-object", "storage": "sqlite" },
// Delete Durable Object class (`OldGone`)
"OldGone": { "type": "durable-object", "state": "deleted" },
// Rename a Durable Object class (from `OldName` to `NewName`)
"OldName": {
"type": "durable-object",
"state": "renamed",
"renamed_to": "NewName"
},
"NewName": { "type": "durable-object", "storage": "sqlite" },
// Transfer a Durable Object (`Outgoing`) to a new Worker (`target-worker`)
"Outgoing": {
"type": "durable-object",
"state": "transferred",
"transferred_to": "target-worker"
},
// Prepare to receive the transfer of a Durable Object (`Incoming`) from another Worker (`source-worker`)
"Incoming": {
"type": "durable-object",
"state": "expecting-transfer",
"storage": "sqlite",
"transfer_from": "source-worker"
}
}
}
When a Worker declares Durable Object class bindings but no lifecycle for them (neither a migrations array nor an exports map), wrangler warns and now suggests a declarative exports entry for each class (previously it suggested a legacy migrations block).
The deployment response now surfaces the server's reconciliation result — created namespaces, applied tombstones, structured per-scenario info entries, and a removable_entries hint for stale tombstones that are safe to delete from the config. Blocking errors return the structured per-class detail with scenario tags, suggested remediation, and any referencing-script context.
wrangler versions upload also forwards exports. Declarative exports lifecycle changes are reconciled when the version is deployed (wrangler versions deploy or wrangler deploy), so a versions upload payload can declare new classes in exports without immediately provisioning them. An actor binding (durable_objects.bindings) to a class declared only in exports on the same versions upload is rejected with a clear error (code 100406) — the binding cannot be resolved until the namespace is provisioned. Either stage the new class via ctx.exports.X (no binding required) on versions upload and add the binding at deploy time, or use wrangler deploy to provision and bind in one step (the same constraint applies to the migrations flow).
Multi-version deploys (wrangler versions deploy A@50% B@50%) where the selected versions disagree on declarative exports are rejected server-side with a clear message: deploy the version that changes exports at 100% first, then run the percentage-split deploy. This prevents traffic on one branch routing to code that references unprovisioned or just-deleted DO namespaces. Single-version (100%) deploys are unaffected.
Local development (wrangler dev, vite dev and unstable_startWorker) reads Durable Object SQLite storage settings from the new exports field, so applications using the declarative flow get correct local-dev storage without needing to also declare a migrations block.
@cloudflare/vitest-pool-workers also picks up Durable Object configuration from exports, so tests against an exports-only Worker run with the correct local SQLite storage and can reach unbound Durable Object classes via ctx.exports.X.
wrangler types is also aware of exports. Live entries (including expecting-transfer, the receiving side of a two-phase transfer) are added to Cloudflare.GlobalProps.durableNamespaces, which types ctx.exports.X for unbound Durable Objects declared only via exports.
#14423 be3f792 Thanks @akshitsinha! - Add wrangler flagship commands for managing Flagship apps and feature flags.
The new wrangler flagship apps and wrangler flagship flags command groups let you create, list, get, inspect, update, set, split, rollout, enable, disable, evaluate, and delete Flagship apps and flags from the CLI, including targeting rules, variations, percentage rollouts, evaluation context, and flag changelogs.
#14156 e1532eb Thanks @petebacondarwin! - Add opt-in OS keychain storage for OAuth credentials
By default wrangler stores your OAuth tokens in a plaintext file, and that is unchanged. You can now opt in to encrypting them at rest instead: wrangler login --use-keyring writes the tokens to an AES-256-GCM-encrypted file whose key is held in your OS keyring (macOS Keychain, libsecret on Linux, or Windows Credential Manager). Existing plaintext credentials are migrated automatically on first use.
Toggle it with any of:
wrangler login --use-keyring / --no-use-keyringwrangler auth keyring enable / disable (or wrangler auth keyring to print the current setting) — useful if you only use named profiles and never run the global wrangler loginCLOUDFLARE_AUTH_USE_KEYRING=true|false to override the saved preference for a single commandOpting out deletes the encrypted credentials rather than decrypting them back to disk, so you re-authenticate afterwards. The preference applies to every auth profile, and each named profile gets its own encrypted file and key.
Per-platform requirements: macOS uses the built-in security tool (nothing to install); Linux uses secret-tool from libsecret-tools (wrangler prints an install hint if it is missing); Windows lazily installs @napi-rs/keyring (~1.9 MB) on first opt-in, and errors with instructions in non-interactive/CI contexts.
CLOUDFLARE_API_TOKEN and CLOUDFLARE_API_KEY/CLOUDFLARE_EMAIL continue to take priority over any stored OAuth credentials.
#14502 6b0ce98 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260630.1 | 1.20260701.1 |
#14306 bfe48db Thanks @matingathani! - Remove deprecated --experimental-vm-modules flag and prevent silent exit on unexpected errors
wrangler was silently exiting with code 1 on Node.js v26 with no error message shown. This release fixes two independent issues that caused this behaviour:
A stale Node.js flag that caused unexpected behaviour on Node.js v26 has been removed.
If an error occurs in a situation where the normal error reporting path itself fails, wrangler now always prints the original error to stderr so the cause is visible rather than silently disappearing.
#14481 0277bfa Thanks @dario-piotrowicz! - Improve error message when deploying to a non-existent Pages project in non-interactive mode
Previously, running wrangler pages deploy with a --project-name that doesn't exist in a non-interactive context (e.g. CI, piped input) would fail with a generic "project not found" or "This command cannot be run in a non-interactive context" error. Now it provides a specific error message explaining that the project doesn't exist and suggests how to create it. The error also suggests using wrangler deploy to deploy a Worker instead.
#14305 98793d8 Thanks @jbwcloudflare! - Improve asset upload performance with single-file uploads
Asset uploads now use a more efficient per-file upload path when the platform enables it. This is rolled out server-side and requires no configuration changes. Existing upload behavior is unchanged when the new path is not enabled.
Updated dependencies [6b0ce98]:
You can now list, trigger, inspect, cancel, and read the logs of indexing jobs for an AI Search instance:
#14490 75d8cb0 Thanks @petebacondarwin! - Add wrangler ai-search jobs commands for managing AI Search indexing jobs
You can now list, trigger, inspect, cancel, and read the logs of indexing jobs for an AI Search instance:
wrangler ai-search jobs list <instance>
wrangler ai-search jobs create <instance> --description "manual reindex"
wrangler ai-search jobs get <instance> <job-id>
wrangler ai-search jobs cancel <instance> <job-id>
wrangler ai-search jobs logs <instance> <job-id>
All commands accept --namespace/-n (defaults to default). All commands except cancel also accept --json for clean machine-readable output.
#14490 75d8cb0 Thanks @petebacondarwin! - Add --source-jurisdiction to wrangler ai-search create for R2-backed instances
R2 buckets can live in a specific jurisdiction (for example eu or fedramp). You can now point an AI Search instance at a bucket in one of those jurisdictions:
wrangler ai-search create my-instance --type r2 --source my-bucket --source-jurisdiction eu
When run interactively, the R2 source flow also prompts for a jurisdiction and lists (and can create) buckets within it. The value is a free-form string forwarded to the API as source_params.r2_jurisdiction (server-side validated); omit the flag for no specific jurisdiction. This AI Search command is in open beta.
#14490 75d8cb0 Thanks @petebacondarwin! - Add auth profiles for managing multiple OAuth logins
Auth profiles let you maintain separate OAuth logins and bind them to directories, so you can switch between different accounts for different projects without having to re-login.
For example:
wrangler auth create work
wrangler auth activate work ~/projects/work
wrangler auth create personal
wrangler auth activate personal ~/projects/personal
New commands under wrangler auth:
wrangler auth create <name> — create or re-authenticate a named profile via OAuthwrangler auth delete <name> — delete a profile and all its directory bindingswrangler auth activate <name> [dir] — bind a profile to a directory (defaults to cwd). Sub-directories will inherit this profile.wrangler auth deactivate [dir] — remove a directory bindingwrangler auth list — list all profiles and their corresponding directoriesThere is also a new global --profile flag, which you can use to activate a profile for just that command run. Note that if you have CLOUDFLARE_API_TOKEN set, that will still take precedence over all profiles. Any account id settings (via CLOUDFLARE_ACCOUNT_ID or wrangler config) will also still be respected.
#14490 75d8cb0 Thanks @petebacondarwin! - Add --strict flag to wrangler versions upload and improve pre-upload safety checks
wrangler versions upload now runs the same pre-upload checks as wrangler deploy:
The new --strict flag (already available on wrangler deploy) causes wrangler versions upload to abort in non-interactive/CI environments when any of these conflicts are detected, instead of auto-continuing.
#14490 75d8cb0 Thanks @petebacondarwin! - Add D1 migration setup to createTestHarness() Worker handles
Tests using createTestHarness() can now apply local D1 migrations before running requests:
const worker = server.getWorker();
beforeEach(async () => {
await worker.applyD1Migrations("DATABASE");
});
#14490 75d8cb0 Thanks @petebacondarwin! - Add Workflow introspection to createTestHarness()
Worker handles can now introspect Workflow bindings by name, allowing tests to disable sleeps, mock step results, and wait for Workflow outcomes. Tests can introspect a known Workflow instance by ID or track instances created after introspection starts.
const harness = createTestHarness({
workers: [{ configPath: "./wrangler.json" }],
});
const worker = harness.getWorker();
await using workflow = await worker.introspectWorkflow("MY_WORKFLOW");
await workflow.modifyAll((modifier) =>
modifier.disableSleeps([{ name: "wait-for-approval" }])
);
const response = await worker.fetch("/start-workflow");
const [instance] = await workflow.get();
await instance.waitForStatus("complete");
#14446 e0cc2cb Thanks @edmundhung! - Add bindingOverrides and getExport() to createTestHarness()
Test harness workers loaded from Wrangler config files can now replace a configured binding with a Worker in the same harness. This is useful for replacing platform bindings with test Workers while keeping the source Worker config production-like. You can also call getExport() on a Worker returned by server.getWorker(name) to access JSRPC methods on the default Worker export, including mock Workers used as override targets.
const server = createTestHarness({
workers: [
{
configPath: "./workers/app/wrangler.jsonc",
bindingOverrides: { BROWSER: "mock-browser" },
},
{
// A mock Worker implementing the Browser Rendering binding named "mock-browser".
configPath: "./workers/mock-browser/wrangler.jsonc",
},
],
});
const mockBrowser = await server
.getWorker<WebEnv, typeof import("./workers/mock-browser")>("mock-browser")
.getExport();
await mockBrowser.setScreenshot(stubPng);
const response = await server.fetch("/reports/2026-05-29.png");
expect(await response.bytes()).toEqual(stubPng);
#14490 75d8cb0 Thanks @petebacondarwin! - Improve wrangler tail resilience and shutdown behaviour
wrangler tail previously crashed with a raw stack trace when the keep-alive ping to the Worker timed out, and could exit with an ugly error on Ctrl-C.
wrangler tail now automatically tries to reconnect with exponential back-off (up to 5 retries).#14490 75d8cb0 Thanks @petebacondarwin! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260625.1 | 1.20260629.1 |
#14478 f10d4ad Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260629.1 | 1.20260630.1 |
#14490 75d8cb0 Thanks @petebacondarwin! - Improve the deploy warning shown when a Workflow name already belongs to another Worker
The warning still notes that deploying reassigns the workflow to the current Worker, and now also explains why this happens (workflow names must be unique per account) and how to resolve it (rename the workflow in the Wrangler config).
#14490 75d8cb0 Thanks @petebacondarwin! - use stream instead of deprecated pipeline key in pipelines setup config snippet
The wrangler pipelines setup and wrangler pipelines create commands now output the correct stream property name in the configuration snippet, matching the rename from pipeline to stream that was applied across the rest of the codebase.
#14490 75d8cb0 Thanks @petebacondarwin! - Improve KV error messages to be clearer and more actionable
Error messages for KV namespace and key operations now consistently explain what went wrong, which flags or config fields to use, and what commands to run as alternatives. This covers namespace selection errors (delete, rename), binding resolution errors, config file issues, and preview namespace ambiguity.
#14479 d292046 Thanks @dario-piotrowicz! - Improve R2 error messages to be clearer and more actionable
Error messages for r2 bucket lifecycle, r2 bucket lock, r2 bucket catalog, and r2 sql commands now include the specific flag or argument that is missing or invalid, along with usage examples showing the correct syntax.
#14490 75d8cb0 Thanks @petebacondarwin! - Improve wrangler versions deploy error messages for non-interactive usage
Error messages in wrangler versions deploy are now clearer and more actionable, especially for non-interactive and agent-driven usage. Each error now explains what went wrong, what was expected, and how to fix it (e.g. suggesting the correct flag or command syntax).
#14490 75d8cb0 Thanks @petebacondarwin! - Fix the remote secrets override check during deploy targeting the wrong Worker when --name is passed
The check that warns when a config value would override an existing remote secret was using the Worker name from the config file rather than the resolved name. If you passed --name <other-worker>, the check ran against the config-file Worker name instead of the Worker actually being uploaded.
#14490 75d8cb0 Thanks @petebacondarwin! - Abort in-flight custom builds when wrangler dev exits or restarts a build
Previously, wrangler dev marked in-flight custom builds as stale but did not pass the abort signal to the spawned build command. This meant Ctrl-C could appear to hang while Wrangler waited for a custom build command to finish naturally. Custom build commands are now cancelled when the dev session tears down or a newer watched build supersedes them.
#14490 75d8cb0 Thanks @petebacondarwin! - Replace existing bindings when adding newly created resources to Wrangler configuration
When config updates are authorized interactively or through --update-config or --binding, Wrangler now replaces an existing resource binding with the selected name instead of adding a duplicate entry. This allows template bindings with placeholder resource IDs to be updated in both interactive and non-interactive workflows.
#14490 75d8cb0 Thanks @petebacondarwin! - Verify Docker is installed and running before wrangler containers build
Previously, running wrangler containers build without Docker installed or with the Docker daemon stopped would fail with an unhelpful spawn error. Now the command checks that Docker is reachable upfront and shows a clear, actionable error message with installation and troubleshooting steps.
#14490 75d8cb0 Thanks @petebacondarwin! - Add images as a valid --source for queues subscription create
The Cloudflare Images service can emit events (e.g. image.uploaded) to a Cloudflare Queue via the event subscriptions API, and this is supported by both the REST API and the Cloudflare Dashboard. However, the wrangler CLI was missing images from the hardcoded --source choices list, causing the command to reject it with an "Invalid values" error.
You can now subscribe a queue to Cloudflare Images events via the CLI:
wrangler queues subscription create <queue> --source images --events image.uploaded
Updated dependencies [75d8cb0, f10d4ad, 75d8cb0, 75d8cb0]:
wrangler containers registries configure now recognizes *-docker.pkg.dev (Google Artifact Registry) domains.
#14311 34e0cef Thanks @sherryliu-lsy! - Add Google Artifact Registry support to containers registries configure
wrangler containers registries configure now recognizes *-docker.pkg.dev (Google Artifact Registry) domains.
--gar-email. It must match the client_email in the service account key.--gar-email and stored base64-encoded.<path-to-key>.json | npx wrangler@latest containers registries configure <region>-docker.pkg.dev --gar-email=<service-account-email> --secret-name=Google_Service_Account_JSON_Key
#14424 5f40dd5 Thanks @MattieTK! - Bump am-i-vibing from 0.4.0 to 0.5.0
This updates the agentic environment detection library to the latest version, which adds detection for the Pi coding agent (earendil-works/pi).
#14406 3b743c1 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260623.1 | 1.20260625.1 |
#14343 daa5389 Thanks @th0m! - Use digest-pinned image references for Dockerfile container deploys
Dockerfile-backed container deploys now use the pushed image digest when deploying the container application. This lets snapshot-enabled container apps pass Cloudchamber validation while keeping local, non-pushed builds and registry image URI deploys unchanged.
#14394 8a5cf8c Thanks @Partha-Shankar! - fix(d1): escape migrationsTableName and filenames in SQLite queries
D1 migration commands in both wrangler and @cloudflare/vitest-pool-workers interpolated the migrationsTableName config value and migration filenames directly into SQL strings without any escaping. This meant:
my"table would produce invalid SQL in CREATE TABLE, SELECT, and INSERT statements, andwhat's-new.sql) would break the INSERT INTO ... VALUES ('...') statement appended after each migration in wrangler.Both identifiers are now properly escaped before interpolation: migrationsTableName is wrapped in double-quotes with internal double-quotes doubled (SQL-standard identifier quoting), and migration filenames used as string literals have their single-quotes doubled before insertion.
Updated dependencies [3b743c1]:
Tests can now access the full env object for a Worker with await server.getWorker ().getEnv(), including vars, secrets, and bindings.
#14369 e312dec Thanks @edmundhung! - Add getEnv() to createTestHarness() Worker handles
Tests can now access the full env object for a Worker with await server.getWorker<Env>().getEnv(), including vars, secrets, and bindings.
#14364 a085dec Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260617.1 | 1.20260619.1 |
#14383 9a0de8f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260619.1 | 1.20260621.1 |
#14397 fab565f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260621.1 | 1.20260623.1 |
#14388 3f02864 Thanks @petebacondarwin! - Stop erroring when find_additional_modules discovers a file that only matches a inactive module rule
Module rules assign module types to imported files — they are not include/exclude filters. Also, setting fallthrough: false in a rule will cause subsequent rules to become inactive. Previously, when find_additional_modules walked the filesystem and discovered a file whose only matching rule is inactive, Wrangler would throw an error and fail the build.
This meant that adding a user rule like the one below would break the build for any .txt, .html, .sql, .bin or .wasm file that didn't match the user-supplied globs but lived somewhere under the module root:
// wrangler.json
{
"rules": [
{
"type": "Text",
"globs": ["html/includeme.html"],
"fallthrough": false
}
]
}
Discovered files that only match an inactive rule are now silently skipped (a debug-level log records each skip for troubleshooting), so users can use fallthrough: false to narrow the set of files attached to their Worker without having to delete or move untouched files on disk.
The direct-import path is unchanged: importing a file in code that only matches an inactive rule is still a hard error, because the imported file genuinely needs a defined module type.
Fixes #14257.
#14358 4ef872f Thanks @gabivlj! - Fix container egress interception on arm64 Docker runtimes
Both wrangler dev and the Cloudflare Vite plugin no longer force the proxy-everything sidecar image to pull as linux/amd64, allowing Docker to select the native image from the multi-platform manifest. Set MINIFLARE_CONTAINER_EGRESS_IMAGE_PLATFORM to force a specific platform when needed.
#14362 2a02858 Thanks @sherryliu-lsy! - Don't require the private credential when reusing an existing Secrets Store secret in containers registries configure
wrangler containers registries configure now checks whether the target Secrets Store secret already exists before resolving the private credential. When the secret already exists it is reused by reference, so the private credential no longer needs to be supplied (via stdin in non-interactive mode, or via a prompt interactively). This applies to all external registries.
The new-secret path is unchanged: the credential is still required and stored. The only visible interactive change is that the secret prompt now appears last and only when a new secret is being created.
Updated dependencies [a085dec, 9a0de8f, fab565f]:
The unstable_getWorkerNameFromProject export has been removed from the wrangler package. This function is now available as getWorkerNameFromProject (w
#14295 cfd6205 Thanks @dario-piotrowicz! - Move unstable_getWorkerNameFromProject from wrangler to @cloudflare/workers-utils
The unstable_getWorkerNameFromProject export has been removed from the wrangler package. This function is now available as getWorkerNameFromProject (without the unstable_ prefix) from @cloudflare/workers-utils. If you were importing this function from wrangler, update your import to use @cloudflare/workers-utils instead.
#14295 cfd6205 Thanks @dario-piotrowicz! - Remove experimental autoconfig exports
The experimental autoconfig exports (experimental_getDetailsForAutoConfig, experimental_runAutoConfig, experimental_AutoConfigFramework) have been removed. This logic has been moved to the @cloudflare/autoconfig package (without the experimental_ prefixes since the package itself is pre-v1).
#14366 c6579d3 Thanks @jamesopstad! - Resolve relative cf-worker entrypoint imports relative to the importing module
When loading the experimental cloudflare.config.ts, a relative entrypoint imported with import ... with { type: "cf-worker" } (e.g. ./src/index.ts) is now anchored to the module where the import is written, rather than being passed through verbatim and later resolved against the top-level config file. This fixes incorrect resolution when the import lives in a file other than the entry config — for example a config that re-exports from a nested file.
Bare specifiers (such as @scope/pkg) and virtual modules (such as virtual:foo) are still left unresolved so that consumers can apply their own resolution.
#14316 444b75e Thanks @matingathani! - Prevent wrangler dev crash when source-mapping a truncated error chunk
When a worker logs many errors in quick succession, the stderr chunks received by wrangler dev can be truncated mid-stack-frame, leaving a call site with an invalid column number. The source map library throws in that case, which was crashing the wrangler process entirely. The error is now caught and the original (un-source-mapped) text is returned instead.
#14118 b38823f Thanks @aicayzer! - Fix Uint8Array step outputs in local Workflows being persisted with the full backing ArrayBuffer
A Uint8Array returned from a Workflows step under wrangler dev was serialised together with its full underlying ArrayBuffer, causing a raw SQLITE_TOOBIG error at view sizes well below the documented 1MiB step-output limit. For example, a 200KB view sliced from an 800KB buffer (a common pattern from crypto.getRandomValues or arr.slice(...) on a larger pool) would fail. The view's bytes are now copied to a tight buffer before persistence, bringing local behaviour in line with production. Fixes #14101.
Updated dependencies [b38823f]:
GHSA-96hv-2xvq-fx4p / CVE-2026-48779 (high severity) reports a remote memory-exhaustion DoS in ws@<8.21.0: a peer sending a high volume of tiny fragme…
#14340 f6e49dd Thanks @emily-shen! - Add cf-wrangler build delegate support
The experimental cf-wrangler delegate binary now accepts build and emits the Build Output API directory through Wrangler's new-config build path. This lets parent tools invoke Wrangler's build-output implementation with cf-wrangler build instead of shelling out through the public Wrangler CLI.
#14324 36777db Thanks @jamesopstad! - Add experimental --experimental-cf-build-output flag to wrangler build
When used alongside --experimental-new-config, wrangler build now emits a self-contained Build Output API directory under .cloudflare/output/v0/ instead of delegating to wrangler deploy --dry-run.
#14347 673b09e Thanks @jamesopstad! - Update undici from 7.24.8 to 7.28.0
#14346 e930bd4 Thanks @haidargit! - Bump ws from 8.20.1 to 8.21.0 to address GHSA-96hv-2xvq-fx4p
GHSA-96hv-2xvq-fx4p / CVE-2026-48779 (high severity) reports a remote memory-exhaustion DoS in ws@<8.21.0: a peer sending a high volume of tiny fragments and data chunks over modest network traffic can crash a ws server or client via OOM. The fix shipped in ws@8.21.0 (commit 2b2abd45, released 2026-05-22), which also introduces the maxBufferedChunks and maxFragments options. This change bumps the workspace catalog entry so that miniflare, wrangler, and @cloudflare/vite-plugin all pick up the patched release.
#14314 5c3bb11 Thanks @harryzcy! - Bump esbuild to 0.28.1
This update includes several bug fixes from esbuild versions 0.27.3 through 0.28.1. See the esbuild changelog for details.
#14331 296ad65 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260616.1 | 1.20260617.1 |
#14275 594544d Thanks @alsuren! - Resolve auto-provisioned D1 bindings via the API in remote subcommands
Remote D1 subcommands (d1 execute --remote, d1 export --remote, d1 info, d1 insights, d1 delete, d1 migrations apply --remote, d1 migrations list --remote, d1 time-travel) previously failed with:
Found a database with name or binding DB but it is missing a database_id, which is needed for operations on remote resources.
when the [[d1_databases]] config entry only had binding and database_name (the shape wrangler deploy writes for automatically-provisioned bindings). They now resolve the real database UUID via GET /accounts/:accountId/d1/database/:name?fields=uuid and proceed as if database_id had been set in config.
If the config entry only has a binding (no database_name, no database_id), the lookup uses the same name wrangler deploy would create via auto provisioning (<worker name>-<binding-lowercased-with-dashes>).
Non-404 API failures (auth, rate-limit, server errors) now propagate verbatim instead of being masked as "database not found".
#14315 a79b899 Thanks @matingathani! - Respect find_additional_modules = false when no_bundle is set
When using no_bundle = true, wrangler was always scanning for and attaching additional modules even if find_additional_modules was explicitly set to false in the config. Additional modules are now only collected when find_additional_modules is not false, consistent with the bundled code path.
#14269 5dfb788 Thanks @mattjohnsonpint! - Support dev.plugin on typed services bindings
Wrangler only honored dev.plugin on unsafe.bindings entries, so users authoring a service binding via services[] could not wire it to a local Miniflare plugin during wrangler dev — they had to fall back to unsafe.bindings and accept a "directly supported by wrangler" warning. Typed services bindings now accept the same dev: { plugin, options? } shape, route the binding through Miniflare's external-plugin pathway in wrangler dev, and strip the field at deploy time. Validation rejects malformed dev shapes.
#14328 ca61558 Thanks @edevil! - Mention temporary preview accounts in wrangler whoami output when unauthenticated
When you run wrangler whoami without being logged in, Wrangler now also tells you that you can deploy without logging in by running a command like wrangler deploy --temporary to use a temporary preview account.
Updated dependencies [673b09e, e930bd4, 5c3bb11, 296ad65]:
The --experimental-autoconfig and --x-autoconfig deploy CLI flags have been replaced with --autoconfig.
#14276 32f9307 Thanks @dario-piotrowicz! - Graduate autoconfig from experimental to stable
The --experimental-autoconfig and --x-autoconfig deploy CLI flags have been replaced with --autoconfig.
Note that the --autoconfig flag defaults to true and that it can be used to disable Wrangler's auto-configuration logic by setting it to false via --autoconfig=false or --no-autoconfig
#14287 41f391f Thanks @edmundhung! - Add per-Worker resource accessors to createTestHarness()
createTestHarness() now provides methods for accessing configured KV namespaces, R2 buckets, D1 databases, and Durable Object namespaces. Use server.getWorker(name) to access resources scoped to that specific Worker:
const worker = server.getWorker("api-worker");
const bucket = await worker.getR2Bucket("BUCKET");
const db = await worker.getD1Database("DB");
#14264 21dbc12 Thanks @dario-piotrowicz! - Suggest Cloudflare skills installation after commands instead of before
The automatic prompt to install Cloudflare skills for detected AI coding agents no longer runs before every Wrangler command. Instead, Wrangler now suggests installing skills, when appropriate, after some commands complete successfully. Commands that output JSON suppress the suggestion to keep their output clean. The --install-skills flag remains available on all commands to explicitly run the skills installation flow before the command executes, without prompting.
As before, Wrangler asks the skills installation question at most once. The skills install metadata file is now written before the confirmation prompt is shown, so even if the user interrupts the process (e.g. CTRL+C, closing the terminal) during the prompt, the question is recorded as unanswered and will not reappear on subsequent runs.
#14042 7e63948 Thanks @edevil! - Add a --temporary flag that creates and uses a temporary Cloudflare preview account when you have no credentials, instead of starting the OAuth login flow.
It's registered only on the commands the short-lived account token can serve — Workers (deploy, versions upload, and related commands), KV, D1, Hyperdrive, Queues, and certificate commands — and is for unauthenticated use only: passing it while already authenticated (OAuth, CLOUDFLARE_API_TOKEN, or a global API key) errors rather than silently ignoring the flag. Before provisioning, Wrangler handles Cloudflare's Terms of Service and Privacy Policy (interactive terminals prompt for yes; non-interactive shells print a notice and continue). Wrangler then runs with the short-lived token and prints a claim URL so the account can be claimed before it expires. The cached account is cleared on successful login or logout.
#14299 035917f Thanks @petebacondarwin! - Send the login user telemetry event when wrangler login --scopes ... succeeds
wrangler login was already reporting the login user event when called without --scopes, but the scoped login path returned early before the event could be sent. Both paths now report the event, so successful scoped logins are counted alongside unscoped ones.
#14271 27db82c Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260611.1 | 1.20260612.1 |
#14298 2a6a26b Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260612.1 | 1.20260615.1 |
#14317 9a424ed Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260615.1 | 1.20260616.1 |
#14282 ecfdd5a Thanks @edmundhung! - Fix wrangler dev asset fallback with custom routes
wrangler dev now applies Workers Assets fallback behavior consistently when routes are configured, including SPA fallback and 404-page handling.
#13763 604be26 Thanks @matingathani! - Show a clear error when deploying a service-worker format Worker with Durable Object migrations or bindings instead of an opaque API error
#14240 1fb7ba5 Thanks @ttoino! - Fix wrangler email sending commands
The email sending commands previously failed against the Cloudflare API. They now work as expected:
email sending enable <domain> enables Email Sending for a domainemail sending disable <domain> disables Email Sending for a domainemail sending settings <domain> shows the Email Sending configuration for a domainemail sending dns get <domain> shows the DNS records to set up for a domainemail sending list previously listed zones. It now lists the domains that have Email Sending enabled — every enabled domain across your account by default, or just those under a specific domain when you pass a domain (or --zone-id).#13838 208b3bb Thanks @matingathani! - Fix unhandled promise rejection when the worker entry point is deleted or moved during wrangler dev hot-reload — now logs a warning and skips the update instead of crashing
#14241 8b2ce41 Thanks @dario-piotrowicz! - Improve error messages for CLI flags, type generation, auth scopes, dev server tunnels, and compatibility flags
Error messages across several areas now name the exact flags or values involved and suggest how to fix the problem:
kv key put, kv key get, kv key delete): error messages now include -- prefixes and clear "Missing required option" / "Conflicting options" phrasing instead of the vague "Exactly one of the arguments ... is required".wrangler types --include-env=false --include-runtime=false: the error now names both flags and explains what each does.wrangler login --scopes: invalid scopes are individually identified instead of dumping the entire array.wrangler dev --tunnel --remote: the error now explains why tunnels require local mode and suggests two concrete fixes.nodejs_compat_populate_process_env / nodejs_compat_do_not_populate_process_env, global_navigator / no_global_navigator): errors now name the specific conflicting flags.#14228 3578919 Thanks @dario-piotrowicz! - Improve Hyperdrive error messages for missing required options
Error messages thrown when creating or updating a Hyperdrive config with missing individual parameters (e.g. --origin-host, --origin-port, --database, --origin-user, --origin-password, --origin-scheme, --access-client-id/--access-client-secret) now clearly state which option is missing, provide a usage example, and suggest --connection-string as an alternative where applicable.
#14304 ee82c76 Thanks @emily-shen! - Skip resource provisioning for asset-only deployments
Previously, asset-only deployments would provision resources even when there was no user Worker script. On a subsequent deploy, we would re-attempt provisioning as the previous asset-only upload would/could not be bound to the previously provisioned resource. Provisioning would then error as the resource had already been created, blocking the deploy.
Updated dependencies [0e055d3, 27db82c, 2a6a26b, 9a424ed, 41f391f]:
When running wrangler dev locally, objects in each local R2 binding are now reachable under /cdn-cgi/local/r2/public/ / on the existing dev server, si
#14119 2047a32 Thanks @tahmid-23! - Serve local R2 bucket objects publicly via the dev server
When running wrangler dev locally, objects in each local R2 binding are now reachable under /cdn-cgi/local/r2/public/<bucket-id>/<key> on the existing dev server, simulating a public bucket. The <bucket-id> is the bucket's bucket_name when set, otherwise its binding. Bindings configured with remote: true are not exposed.
#14202 e8561c2 Thanks @jamesopstad! - Add experimental --x-new-config flag for authoring config in TypeScript
This is an experimental, opt-in feature. When enabled, wrangler dev, wrangler build, wrangler deploy, wrangler versions upload, and wrangler versions deploy load the Worker's configuration from a cloudflare.config.ts file instead of wrangler.json / wrangler.jsonc / wrangler.toml. Additionally, an optional wrangler.config.ts file can be provided for Wrangler-specific dev/build configuration.
cloudflare.config.ts (required) — Worker runtime configuration (bindings, triggers, observability, placement, limits, compatibility, routes, etc.). Authored via defineWorker from wrangler/experimental-config.wrangler.config.ts (optional) — Tooling / bundling / dev-server configuration (noBundle, minify, alias, define, rules, tsconfig, build, dev, assetsDirectory, etc.). Authored via defineWranglerConfig from wrangler/experimental-config.Per-environment configuration is via ctx.mode branching inside the function form of either file.
Example cloudflare.config.ts:
import { defineWorker, bindings } from "wrangler/experimental-config";
import * as entrypoint from "./src/index.ts" with { type: "cf-worker" };
export default defineWorker((ctx) => ({
name: "my-worker",
entrypoint,
compatibilityDate: "2026-05-18",
env: {
MY_KV: bindings.kv(),
MY_TEXT: bindings.text(`The mode is ${ctx.mode}`),
},
}));
Example wrangler.config.ts:
import { defineWranglerConfig } from "wrangler/experimental-config";
export default defineWranglerConfig({
minify: true,
assetsDirectory: "./public",
});
Because this is experimental, the flag, the config formats, and the wrangler/experimental-config exports may change in any release.
#14185 98c9afe Thanks @penalosa! - Use the shared env-credential resolver from @cloudflare/workers-auth
No user-facing behaviour change. Credential resolution order (global API key + email → CLOUDFLARE_API_TOKEN → stored OAuth token) is preserved.
#14184 e305126 Thanks @penalosa! - Add an experimental cf-wrangler delegate entrypoint for projects that can't use @cloudflare/vite-plugin (service workers, old compatibility dates, Python, Rust, etc.).
cf-wrangler dev starts the same local dev server as wrangler dev — it sits directly on wrangler's internal dev server, so the bundling and runtime behaviour are identical — but exposes a deliberately narrow CLI surface (--mode, --port, --host, --local) for a parent CLI to delegate to, and other dev server config options are read from the wrangler config file.
This replaces the separate @cloudflare/wrangler-bundler package. This is an internal integration point and is not intended to be run directly by users.
#14246 f3990b2 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260609.1 | 1.20260610.1 |
#14256 4597f08 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260610.1 | 1.20260611.1 |
#14243 25722ac Thanks @com6056! - Fix a memory leak that could make long-running headless wrangler dev sessions unresponsive
Long-running wrangler dev sessions with no DevTools attached (for example using the containers feature under sustained traffic) could gradually consume unbounded memory and eventually stop accepting connections. The inspector proxy now only enables network tracking while a DevTools client is connected, so the buildup no longer happens. Interactive debugging is unaffected. Fixes #14191.
#14230 41f75c0 Thanks @dario-piotrowicz! - Improve D1 error messages for missing or conflicting options
Error messages for d1 execute, d1 export, d1 time-travel restore, and d1 insights now clearly state which option is missing or conflicting, explain why the combination is invalid, and suggest how to fix the issue.
Additionally, duration validation errors in d1 insights are now thrown as UserError instead of plain Error, ensuring they are displayed cleanly to users rather than as unexpected crashes.
#14213 10b5538 Thanks @dario-piotrowicz! - Improve authentication error messages with specific failure reasons
When authentication fails (e.g. during wrangler dev --remote or when using remote bindings), the error message now explains exactly what went wrong -- whether no credentials were found, the token expired, or the environment is non-interactive -- and lists actionable steps to fix it, including a wrangler whoami tip.
Previously, auth failures could produce multiple confusing errors (e.g. "Failed to fetch auth token: 400 Bad Request" followed by "Failed to start the remote proxy session"). Now a single, clear error is shown.
#14233 818c105 Thanks @dario-piotrowicz! - Improve R2 Sippy error messages
Now error messages in wrangler r2 bucket sippy follow a consistent pattern: they describe what is missing, name the exact --flag to use, and provide context (e.g. example values, links to the dashboard). Previously, many errors said only "Error: must provide --flag." with no guidance on what the flag does or how to obtain the value.
#14259 2ae6099 Thanks @emily-shen! - Move worker build step earlier in deploy/upload step, before upload specific config validation
Updated dependencies [f3990b2, 4597f08, 2047a32]:
It runs Workers in a local preview environment using production build output and works with both Wrangler projects and Workers built by the Cloudflare
#14169 0706fbf Thanks @edmundhung! - Introduce createTestHarness() for integration testing Workers
It runs Workers in a local preview environment using production build output and works with both Wrangler projects and Workers built by the Cloudflare Vite plugin.
Use it from any Node.js test runner to send requests to individual Workers, trigger scheduled events, reset the server between tests, and mock outbound requests with libraries that intercept globalThis.fetch(), such as MSW.
You can also capture structured logs from your Workers with getLogs(), or dump out a diagnostic timeline with debug() when tests fail:
import { createTestHarness } from "wrangler";
const server = createTestHarness({
workers: [
{ configPath: "./dist/web_worker/wrangler.json" },
{ configPath: "./dist/api_worker/wrangler.json" },
],
});
await server.listen();
await server.fetch("http://example.com");
const apiWorker = server.getWorker("api-worker");
await apiWorker.fetch("http://example.com/users/123");
await apiWorker.scheduled({ cron: "0 0 * * *" });
server.getLogs();
if (testFailed) {
server.debug();
}
await server.reset();
await server.close();
#14174 8cf8c61 Thanks @oliy! - Surface pipeline status and failure reasons in wrangler pipelines list and wrangler pipelines get
wrangler pipelines list now includes a Status column, and when any pipelines are in a failed state it prints a summary of each failing pipeline along with the reason reported by the API.
wrangler pipelines get now shows the pipeline Status in the general details and, for failed pipelines, highlights the failure with the reason returned by the server so it is clear why a pipeline is not running.
#14211 a61ac29 Thanks @james-elicx! - Add --version-tag support to wrangler versions deploy to deploy a version by its tag
You can now roll out or roll back a version by the tag it was uploaded with (e.g. a commit SHA passed to --tag at upload time) instead of first looking up its Version ID:
wrangler versions deploy --version-tag <sha>@100%
The tag is resolved to a Version ID against the worker's deployable versions, and the <version-tag>@<percentage> shorthand works just like the existing <version-id>@<percentage> notation, including splitting traffic across multiple --version-tag values. If a tag matches no deployable version, or matches more than one, the command errors and asks you to deploy by Version ID directly. Note that tags can only be resolved against recent (deployable) versions — older versions that have aged out of that window must still be deployed by Version ID.
#14163 23aecac Thanks @emily-shen! - Print deploy warnings even in non-interactive contexts when strict mode is off
Currently, wrangler deploy checks whether the incoming deploy configuration has destructive conflicts with the current configuration. Previously, we only performed this check in interactive contexts, or if the --strict flag was passed in. Now this warning is always printed, and it remains non-blocking in non-interactive contexts.
#14173 b932e47 Thanks @gpanders! - Handle API validation errors from wrangler containers ssh
Wrangler now lets the Containers API validate SSH instance IDs and preserves raw API error bodies such as INVALID_INSTANCE_ID when reporting validation failures.
#14192 d076bcc Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260603.1 | 1.20260605.1 |
#14217 24497d0 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260605.1 | 1.20260608.1 |
#14231 4bb572f Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260608.1 | 1.20260609.1 |
#14195 165adb2 Thanks @dario-piotrowicz! - Show actionable error message when authentication fails during remote dev
When wrangler dev with remote bindings encountered an authentication error (expired token, revoked OAuth, or invalid API token), the user saw a generic "A request to the Cloudflare API failed" message with no indication that authentication was the problem.
Now, authentication failures during remote dev display a clear error message with actionable steps.
#14034 776098c Thanks @matingathani! - Fix wrangler types --check reporting types as out of date in multi-worker setups
Previously, running wrangler types --check -c primary/wrangler.jsonc in a multi-worker project would incorrectly report types as out of date, even when they were current. This happened because the secondary worker config paths (passed via additional -c flags during generation) were not stored in the generated types file header, so --check had no way to resolve the secondary workers' service bindings when verifying the hash.
The fix stores secondary config paths in the generated file's header comment so that --check can recover them automatically. Users no longer need to re-pass every -c flag when running --check — only the primary config is required.
#14053 7993711 Thanks @fallintoplace! - Prevent delete-only wrangler secret bulk input from creating a new Worker
Previously, wrangler secret bulk could create a draft Worker when the input only deleted secrets and the target Worker name did not exist. Delete-only bulk secret operations now leave Worker-not-found as an error instead of creating a new Worker.
#14055 8923f97 Thanks @dario-piotrowicz! - Preserve all deployment-affecting CLI flags in the interactive deploy config flow
When running wrangler deploy without a config file and going through the interactive setup flow, CLI flags beyond --compatibility-flags (such as --routes/--route, --domains/--domain, --triggers, --var, --define, --alias, --jsx-factory, --jsx-fragment, --tsconfig, --minify, --upload-source-maps, --no-bundle, --logpush, --keep-vars, --legacy-env, and --dispatch-namespace) were silently dropped. These flags are now persisted to the generated wrangler.jsonc config file (where a config field equivalent exists) and included in the suggested CLI command when the user declines config file generation.
#14196 b205fb7 Thanks @odiak! - Validate JSON stdin values for wrangler secret bulk
JSON input piped through stdin now validates that secret values are strings or null before sending them to the API, matching the existing behavior for file input.
Updated dependencies [d076bcc, 24497d0, 4bb572f, 48c4ff0]:
The --script named option is now hidden and deprecated for both commands. It continues to work for backwards compatibility but only accepts file paths…
#14089 c6c61b5 Thanks @alsuren! - Add migrations_pattern to D1 database bindings
The D1 binding now accepts an optional migrations_pattern field, allowing you to point wrangler d1 migrations apply and wrangler d1 migrations list at migration files in nested layouts (e.g. ORM-generated folders like migrations/0000_init/migration.sql).
migrations_pattern is a glob (relative to the wrangler config file) and defaults to ${migrations_dir}/*.sql, which preserves today's behaviour. Files that do not match the pattern are not executed.
{
"d1_databases": [
{
"binding": "DB",
"database_name": "my-db",
"database_id": "...",
"migrations_dir": "migrations",
"migrations_pattern": "migrations/*/migration.sql"
}
]
}
When no migrations match the configured pattern but files matching the common migrations/*/migration.sql (drizzle-style) layout do exist, Wrangler logs a hint suggesting migrations_pattern as an opt-in.
wrangler d1 migrations create now returns an actionable error if the generated migration filename would not match the configured pattern.
#14153 7a6b1a4 Thanks @dario-piotrowicz! - Generalize wrangler deploy and wrangler versions upload positional argument from [script] to [path]
Both wrangler deploy and wrangler versions upload now accept a generic [path] positional argument that can point to either a Worker entry-point file or a directory of static assets. The type is auto-detected. For example:
wrangler deploy ./src/index.ts deploys a Worker (same as before)wrangler deploy ./public deploys a static assets site (no interactive confirmation prompt)The --script named option is now hidden and deprecated for both commands. It continues to work for backwards compatibility but only accepts file paths. Passing a directory to --script now produces a clear error message suggesting the positional path argument or --assets flag instead.
#13863 3b8b80a Thanks @aslakhellesoy! - getPlatformProxy() now passes through workflow bindings that have a script_name
Workflows without a script_name are still stripped (and warned about) because the engine for an internal workflow can't run inside the empty proxy worker that backs getPlatformProxy(). Workflows with a script_name are handed to miniflare unchanged; miniflare reroutes the engine's USER_WORKFLOW binding through the dev-registry-proxy when the target worker is running in another Miniflare instance — the same mechanism Durable Objects already use.
This means SvelteKit/Remix (and similar split-process setups) can call platform.env.MY_WORKFLOW.create({ ... }) directly from their server-side request handlers in dev, as long as the workflow class is exposed by another worker registered in the dev registry.
Closes #7459.
#14164 b502d54 Thanks @G4brym! - Rename the web_search binding kind to websearch
Pre-launch rename of the public binding type from web_search to websearch so the on-the-wire shape matches the product name (Web Search). The wrangler config key, the binding-type string sent to the Cloudflare API, and the miniflare option key all move from web_search / webSearch to websearch.
Update your wrangler config:
- "web_search": { "binding": "WEBSEARCH" }
+ "websearch": { "binding": "WEBSEARCH" }
The runtime WebSearch type exposed on env.WEBSEARCH is unchanged.
#14089 c6c61b5 Thanks @alsuren! - Restore the D1 executeSql logger level via try/finally
wrangler d1 execute --json and the internal executeSql helper temporarily lower the global logger to "error" to keep human-readable output out of the JSON payload. Previously the level was restored only on the happy path, so any early return or thrown error left the singleton logger muted, silencing later logger.warn/logger.log output (notably from migration helpers that wrap executeSql and are commonly mocked in tests).
The level swap is now wrapped in try/finally so it is always restored.
#14175 a3eea27 Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"
The following dependency versions have been updated:
| Dependency | From | To |
|---|---|---|
| workerd | 1.20260601.1 | 1.20260603.1 |
#14121 7539a9b Thanks @petebacondarwin! - Extract the OAuth 2.0 + PKCE flow into a new @cloudflare/workers-auth package.
The OAuth login / logout / refresh logic, the auth-config TOML file IO, the OAuth token exchange + local callback server, and the Cloudflare Access detection helpers that previously lived in packages/wrangler/src/user/ have moved to the new internal-only @cloudflare/workers-auth package. Wrangler now wires the OAuth flow up via a small glue module that injects its logger, browser opener, interactivity detector, and config cache via a dependency- injection context.
What stays in wrangler:
login / logout / whoami / auth token commandsCLOUDFLARE_API_TOKEN, CLOUDFLARE_API_KEY / CLOUDFLARE_EMAIL, etc.)requireAuth, getOrSelectAccountId)string[])whoami / account fetchingNo behavior change for end users. The on-disk TOML format and location remain identical, and all telemetry message labels are preserved verbatim.
@cloudflare/workers-auth is published with prerelease: true and is not intended for external use — its APIs may change without notice.
#14162 0bb2d55 Thanks @dario-piotrowicz! - In non-interactive mode remove the skills installation message
When Wrangler run in non interactive mode and it detected agents that it could install skills for, it would print a message such as:
Cloudflare agent skills are available for: <DETECTED_AGENTS>. Run wrangler in an interactive terminal to install them, or use '--install-skills' to install without prompting.
This message seems to be confusing and unhelpful so it has now been removed.
#14165 8400fb9 Thanks @NuroDev! - Limit wrangler versions list to the 10 most recent deployable versions
The versions API ignores pagination when filtering to deployable versions, so Wrangler now caps the command output client-side. This keeps the command aligned with its help text and avoids overwhelming terminal output for Workers with many versions.
#14151 7949f81 Thanks @dario-piotrowicz! - Skip stale bundles during dev server reload to avoid redundant restarts
When rapidly saving a wrangler config file with remote bindings, each save would trigger a full reload cycle (remote connection setup, miniflare restart), causing many sequential "Reloading local server... / Establishing remote connection..." messages (while blocking the user). The runtime controllers now check whether a newer bundle has been queued at each expensive async boundary and bail out early if the current bundle is stale. This ensures that only the latest config change triggers a reload, making wrangler dev much more responsive during repeated config edits.
#14072 d462013 Thanks @himanshu-cf! - Update wrangler secret bulk command description to reflect create/update/delete capabilities
The help text for wrangler secret bulk now accurately describes that the command can create, update, or delete multiple secrets in a single request, with up to 100 secrets per command. The file argument description also clarifies that setting a key to null in JSON will delete it, and that deletion is not supported with .env files.
#13979 c2280cd Thanks @matingathani! - Warn when a named environment silently inherits custom_domain routes from the top-level config
When an env.<name> block does not override routes, it inherits the top-level routes array. If that array contains entries with custom_domain: true, every deploy to the named environment will silently reassign the custom domain away from the top-level Worker and towards the env Worker, causing routing drift. Wrangler now emits a warning in this situation and suggests adding "routes": [] to the env block to prevent inheritance.
#14170 ea12b58 Thanks @petebacondarwin! - Tighten on-disk permissions of the OAuth credentials file to 0600
The user auth config file written by wrangler login (typically ~/.config/.wrangler/config/default.toml on Linux/macOS, or <environment>.toml for non-production Cloudflare API environments) is now written with mode 0600 and re-chmod-ed on every save. This prevents other local users on shared hosts from reading the stored OAuth tokens. Existing files with looser permissions written by older Wrangler versions are tightened the next time Wrangler refreshes the token or the user logs in again. The change is a no-op on Windows, which does not honour POSIX mode bits.
#14022 acf7817 Thanks @petebacondarwin! - Show the actual OAuth error instead of hanging when wrangler login is rejected by the OAuth provider (for example with invalid_scope).
Previously, if the OAuth callback returned with an error other than access_denied, Wrangler would never respond to the browser. Because server.close()'s callback only fires once all open connections have ended, the login command would hang until the 120 second OAuth timeout — at which point it would print a generic timeout message rather than the actual OAuth failure. The same gap existed for the case where the OAuth provider redirected back without an authorisation code, and for failures during the auth-code-to-access-token exchange.
The OAuth provider's error_description (RFC 6749 §4.1.2.1) is now also surfaced, so the message includes the specific reason for the failure rather than just the bare error code. For example, a misconfigured staging scope now surfaces as:
OAuth error: invalid_scope
The OAuth 2.0 Client is not allowed to request scope 'browser:write'.
instead of hanging silently.
Updated dependencies [a3eea27, 1fdd8de, b502d54, 3b8b80a]:
Your coding agent can read these notes before it upgrades. Set up the MCP server →
{ "k2": [ { "binding": "ORDERS", "stream": "0123456789abcdef0123456789abcdef" } ] }