---
description: Use one command-line interface for the public Cloudflare API and for Workers projects.
title: Cloudflare CLI
image: https://developers.cloudflare.com/cf/og.png?v=54b5e0417cfb98d9
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Cloudflare CLI

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

The Cloudflare CLI, `cf`, is one command-line interface for the public Cloudflare API and for Workers projects. Use it to manage zones, DNS, storage, and security settings, and to create, develop, and deploy Workers. Coding agents run the same commands you do.

Beta

`cf` is in beta. Commands, configuration, and Build Output can change before the stable release.

Install `cf` globally:

npmyarnpnpmbun

```
npm install --global cf
```

```
yarn global add cf
```

```
pnpm add --global cf
```

```
bun add --global cf
```

To sign in and run your first command, refer to [Install and sign in](https://developers.cloudflare.com/cf/get-started/).

## Choose your path

### [Deploy a Worker](https://developers.cloudflare.com/cf/get-started/first-worker/)

Create a project with cf init, develop it locally, and deploy it.

### [Manage resources](https://developers.cloudflare.com/cf/get-started/resources/)

Find zones and create, list, and delete DNS records from the command line.

### [Coming from Wrangler](https://developers.cloudflare.com/cf/wrangler/)

Learn what changes, and move a project to cf with cf migrate.

### [Coding agents](https://developers.cloudflare.com/cf/agents/)

Set up coding agents to find and run Cloudflare commands with cf.

### [CI and automation](https://developers.cloudflare.com/cf/ci/)

Authenticate with API tokens and run cf in pipelines.

## What `cf` provides

- **Commands for the public API.** More than 2,900 commands, most of them generated from the schemas that describe the Cloudflare API.
- **Typed project configuration.** Workers projects use [`cloudflare.config.ts`](https://developers.cloudflare.com/cf/projects/cloudflare-config/), so editors and agents can autocomplete bindings and triggers.
- **Project commands.** `cf dev`, `cf build`, and `cf deploy` run your framework's own command, the [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/), or Wrangler, depending on the project. To learn more, refer to [How cf runs your project](https://developers.cloudflare.com/cf/projects/#how-cf-runs-your-project).
- **Command search.** `cf cli search` finds commands from a plain-language description of a task.

## `cf` and Wrangler

[Wrangler](https://developers.cloudflare.com/workers/wrangler/) is the CLI for Workers projects configured with `wrangler.jsonc` or `wrangler.toml`. `cf` covers the public Cloudflare API and uses `cloudflare.config.ts` for Workers projects.

You can run `cf` resource commands alongside an existing Wrangler project without changing it. Before you run `cf dev`, `cf build`, or `cf deploy` in a Wrangler project, convert it with `cf migrate`. To compare the two tools and plan a move, refer to [`cf` for Wrangler users](https://developers.cloudflare.com/cf/wrangler/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/cf/#page","headline":"Cloudflare CLI","description":"Use one command-line interface for the public Cloudflare API and for Workers projects.","url":"https://developers.cloudflare.com/cf/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/og.png?v=54b5e0417cfb98d9","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Install the Cloudflare CLI, sign in, and run your first command.
title: Get started
image: https://developers.cloudflare.com/cf/get-started/og.png?v=cd76c898b43a26f7
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Get started

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/get-started/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Every `cf` workflow starts the same way: install the CLI, sign in, and run a command. The reference sections at the end of this page explain how `cf` chooses credentials, accounts, and zones.

## Requirements

- A Cloudflare account. If you do not have one, [sign up ↗︎](https://dash.cloudflare.com/sign-up).
- Node.js 22.18 or later. Bun is not supported. When `cf` runs on Bun, commands that load `cloudflare.config.ts` fail.

## Install `cf`

Install `cf` globally so the command is available in every directory:

npmyarnpnpmbun

```
npm install --global cf
```

```
yarn global add cf
```

```
pnpm add --global cf
```

```
bun add --global cf
```

The package installs two commands that run the same CLI: `cf` and `cloudflare`. Use `cloudflare` if another tool named `cf` is already on your `PATH`.

Confirm the installation:

```sh
cf --version
```

To update `cf` later, install the latest release:

npmyarnpnpmbun

```
npm install --global cf@latest
```

```
yarn global add cf@latest
```

```
pnpm add --global cf@latest
```

```
bun add --global cf@latest
```

A project can also add `cf` as a development dependency. Inside that project, the global `cf` command runs the version installed in the project, so collaborators, coding agents, and continuous integration (CI) use the same release. Projects created with `cf init` already include it.

## Sign in

1. Start the sign-in flow:

   ```sh
   cf auth login
   ```

   `cf` prints a link and a one-time code, and opens the link in your browser. Approve the request to give `cf` access to your Cloudflare account.
2. Confirm that you are signed in:

   ```sh
   cf auth whoami
   ```



On a remote machine, over SSH, or in a container, add `--no-browser`. `cf` prints the link without opening it, and you can approve the request from a browser on another device. To sign in again, add `--force`.

`cf` keeps its own credentials and does not reuse a Wrangler login. Sign in once, even if you already use Wrangler.

## Run your first command

List the zones you can access:

```sh
cf zones list
```

Results are JSON on standard output. Progress and status messages go to standard error, so you can redirect or pipe results without extra flags:

```sh
cf zones list > zones.json
```

### Find commands

To find the command for a task, describe the task to `cf cli search`:

```sh
cf cli search "create a DNS record"
```

`cf cli search` prints up to five matching commands as JSON. It runs locally and does not need credentials. To browse instead, add `--help` to `cf`, to a product such as `cf dns`, or to any command.

For a walkthrough that finds, creates, and deletes a resource, refer to [Manage resources from the command line](https://developers.cloudflare.com/cf/get-started/resources/).

## Set up shell completion

Add completion to your shell profile, then restart your shell:

```sh
cf complete zsh >> ~/.zshrc
```

`cf complete` also supports `bash`, `fish`, and `powershell`. Run `cf complete --help` for the bash and fish equivalents.

## Credential order

`cf` uses the first credential it finds:

1. The `CLOUDFLARE_API_TOKEN` environment variable, including a value loaded from a [`.env` file](#load-credentials-from-a-env-file).
2. The profile selected with `--profile <NAME>`.
3. The profile bound to the current directory, or to its nearest parent, with `cf auth activate`.
4. The default profile, which `cf auth login` signs in to.

`cf` does not support the Global API Key.

## Select an account

When a command needs an account, `cf` selects one in this order:

1. The `CLOUDFLARE_ACCOUNT_ID` environment variable.
2. The `accountId` field in the default export of `cloudflare.config.ts`.
3. The account `cf` saved for this project on an earlier command.
4. The only account your credentials can access. If there are several, `cf` asks you to choose one.

When `cf` selects your only account, or you choose one, it saves that account and uses it on later commands in the same project without asking. It stores the account in `cloudflare-account.json`, or `cloudflare-account-<PROFILE>.json` for a named profile, in `.cache/cloudflare/` inside the nearest `node_modules` directory. It uses `.cloudflare/cache/` in the current directory instead when there is no `node_modules` directory, or when `.cloudflare/cache/` already exists and the `node_modules` cache does not.

To choose again, delete that file. Running `cf auth login --force` or `cf auth logout` from the project directory also clears it, but not while `CLOUDFLARE_API_TOKEN` is set.

In a non-interactive session, such as a script or CI job, a command fails if your credentials can access more than one account and no account is set or saved.

To set a default account for a project, refer to [Set account defaults](https://developers.cloudflare.com/cf/projects/cloudflare-config/#set-account-defaults).

## Select a zone

Zone-scoped commands accept `--zone` or `-z`. The value can be a zone ID or a domain name:

```sh
cf dns records list --zone example.com
```

For a domain name, `cf` looks up the matching zone in the [selected account](#select-an-account). The `--zone` option takes priority over the `CLOUDFLARE_ZONE_ID` environment variable.

## Use named profiles

Profiles keep separate credentials, for example for work and personal accounts. Create a profile:

```sh
cf auth create work
```

`cf auth create` creates the profile and starts a sign-in for it. To use the profile in a project, bind it to the project directory:

```sh
cf auth activate work
```

`cf auth activate` binds the profile to the current directory and its subdirectories. To bind a different directory, pass it after the profile name. To remove the binding, run `cf auth deactivate`. To use a profile for a single command, pass `--profile <NAME>`. To see your profiles, run `cf auth list`.

`cf auth create`, `cf auth activate`, `cf auth deactivate`, and `cf auth delete` do not run while `CLOUDFLARE_API_TOKEN` is set, because the token takes priority over every profile.

## Authenticate automation

In CI and other non-interactive environments, set an API token instead of running `cf auth login`:

```sh
export CLOUDFLARE_API_TOKEN=<API_TOKEN>
export CLOUDFLARE_ACCOUNT_ID=<ACCOUNT_ID>
```

Give the token only the permissions the job needs. To create one, refer to [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). For a complete pipeline setup, refer to [Use `cf` in CI](https://developers.cloudflare.com/cf/ci/).

## Load credentials from a `.env` file

API commands read these variables from a `.env` file in the current directory:

- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
- `CLOUDFLARE_ZONE_ID`
- `CLOUDFLARE_COMPLIANCE_REGION`
- `CLOUDFLARE_ACCESS_CLIENT_ID`
- `CLOUDFLARE_ACCESS_CLIENT_SECRET`

For example:

*.envtxt*

```txt
CLOUDFLARE_API_TOKEN=<API_TOKEN>
CLOUDFLARE_ACCOUNT_ID=<ACCOUNT_ID>
```

`cf` reads only `.env`. It does not read `.env.local` or mode-specific files such as `.env.<MODE>`. Variables already set in your environment override the file.

Commands run with `--local` do not read the file. `cf deploy`, `cf previews deploy`, `cf workers versions create`, and `cf workers triggers deploy` read it only after the build finishes.

Caution

Do not commit API tokens to version control. Check that `.gitignore` excludes `.env`. Projects created with `cf init` ignore `.env*` files.

## Next steps

- To review CLI settings, [see the environment variables](https://developers.cloudflare.com/cf/environment-variables/).
- If you are new to Workers, [deploy your first Worker](https://developers.cloudflare.com/cf/get-started/first-worker/).
- If you manage zones and DNS, [manage resources from the command line](https://developers.cloudflare.com/cf/get-started/resources/).
- If you use Wrangler today, read [`cf` for Wrangler users](https://developers.cloudflare.com/cf/wrangler/).
- If you work with a coding agent, [set up `cf` for agents](https://developers.cloudflare.com/cf/agents/).
- If you deploy from a pipeline, [use `cf` in CI](https://developers.cloudflare.com/cf/ci/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/get-started/#page","headline":"Get started","description":"Install the Cloudflare CLI, sign in, and run your first command.","url":"https://developers.cloudflare.com/cf/get-started/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/get-started/og.png?v=cd76c898b43a26f7","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Create a Workers project with cf init, develop it locally, and deploy it with the Cloudflare CLI.
title: Deploy your first Worker
image: https://developers.cloudflare.com/cf/get-started/first-worker/og.png?v=77bcce5f2775c97f
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Deploy your first Worker

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/get-started/first-worker/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

This guide creates a [Worker](https://developers.cloudflare.com/workers/) with `cf init`, runs it on your machine, and deploys it to your Cloudflare account.

## Before you begin

[Install `cf`](https://developers.cloudflare.com/cf/get-started/) and check the [requirements](https://developers.cloudflare.com/cf/get-started/#requirements). You do not need to sign in until you deploy.

## 1. Create a project

Create a project in a new directory:

```sh
cf init my-worker
```

`cf init` asks which package manager to use, creates the project in `my-worker`, installs its dependencies, and generates types for its bindings. If you leave out the directory, `cf init` asks for one.

Apart from `node_modules` and the lockfile from the install, `cf init` creates these files:

- my-worker/
  - .cloudflare/
    - types/
      - index.d.ts
  - src/
    - index.ts
  - .gitignore
  - cloudflare.config.ts
  - package.json
  - tsconfig.json
  - vite.config.ts

- `src/index.ts` is the Worker.
- `cloudflare.config.ts` describes the Worker in TypeScript.
- `vite.config.ts` adds the [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/), which runs your code in the Workers runtime during development and builds it for deployment.
- `package.json` has `dev`, `build`, and `deploy` scripts that run the matching `cf` commands. It lists `cf` and the Vite plugin 2.0 beta ( `@cloudflare/vite-plugin@beta`), which `cf` uses, but not Wrangler.
- `.cloudflare/types/index.d.ts` holds generated binding and runtime types. The Vite plugin updates it when you run `cf dev` or `cf build`. The generated `.gitignore` excludes `.cloudflare/`.

The Worker reads a `WORLD` binding and returns a greeting:

*src/index.jsjs*

```js
import { env } from "cloudflare:workers";

export default {
	fetch() {
		return new Response(`Hello ${env.WORLD}!`);
	},
};
```

*src/index.tsts*

```ts
import { env } from "cloudflare:workers";

export default {
	fetch() {
		return new Response(`Hello ${env.WORLD}!`);
	},
} satisfies ExportedHandler;
```

`cloudflare.config.ts` names the Worker, points to its entrypoint, and declares the `WORLD` text binding. The annotations explain each field and builder:

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#first-worker-config-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#first-worker-config-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "my-worker", (name reference)</summary>



<code>name</code>Required<a href="#first-worker-config-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#first-worker-config-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#first-worker-config-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#first-worker-config-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>WORLD: bindings.text("World"), (text reference)</summary>



<code>text</code>Builder<a href="#first-worker-config-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

},

},

});

`cf init` sets `compatibilityDate` to a fixed, recent date that ships with your version of `cf`. The `cf-worker` import attribute points the configuration at your Worker module. `cf` reads the module path from it and does not load or run your Worker code.

## 2. Develop locally

Start the development server:

```sh
cd my-worker
cf dev
```

Open the local URL that `cf dev` prints, by default `http://localhost:5173/`. The Worker responds with `Hello World!`.

Change the response in `src/index.ts`, save the file, and refresh the page. The development server picks up the change without a restart.

In this project, `cf dev` does not accept options such as `--port`. To change the port, set `server.port` in `vite.config.ts`.

## 3. Deploy

1. If you have not signed in yet, sign in:

   ```sh
   cf auth login
   ```


2. Deploy the Worker:

   ```sh
   cf deploy
   ```

   `cf deploy` builds the project, uploads the Worker, deploys it to your account, and prints the result. If you can access more than one account, `cf` asks which one to use. To learn how to set a default, refer to [Select an account](https://developers.cloudflare.com/cf/get-started/#select-an-account).

To check the build without deploying, run `cf deploy --dry-run`. A dry run makes no API requests, so it works before you sign in.

## Create a project without prompts

In a script or CI job, `cf init` cannot ask questions, so pass the directory. Choose the package manager with `--package-manager`, which accepts `npm`, `pnpm`, `yarn`, or `bun`. Without it, `cf init` uses npm, unless you ran `cf` through another package manager:

```sh
cf init my-worker --package-manager npm
```

To skip the installation, add `--no-install`. Then run your package manager's install command in the project before you run `cf dev`.

## Start from an existing project

`cf` can also set up an existing app. In the project directory, install its dependencies, then run `cf init .`:

```sh
cf init .
```

`cf` detects the framework and shows the settings it found, including the Worker name, framework, build command, and output directory. After you confirm, `cf` changes the project. For a Vite app, it:

- Installs `cf` and `@cloudflare/vite-plugin` as development dependencies.
- Adds the Cloudflare plugin to `vite.config.ts`, or creates the file.
- Creates `cloudflare.config.ts`, with observability turned on.
- Adds a `deploy` script that runs `cf deploy`.
- Adds `.wrangler`, `.dev.vars*`, and `.env*` entries to `.gitignore`. In a Git repository without a `.gitignore` file, it creates one.

`cf` does not add `.cloudflare/`, where it writes builds and generated types, to `.gitignore`. Add it yourself:

```sh
echo ".cloudflare/" >> .gitignore
```

`cf build` and `cf deploy` run the framework's build command, such as `vite build`, not the `build` script in `package.json`. To keep extra build steps, refer to [How cf runs your project](https://developers.cloudflare.com/cf/projects/#how-cf-runs-your-project).

If you skip `cf init .`, then `cf dev`, `cf build`, and `cf deploy` run the same setup the first time you use them. In CI, they apply the changes without asking, so run `cf init .` locally and commit the result first. For details, refer to [Automatic configuration](https://developers.cloudflare.com/cf/projects/#automatic-configuration).

Plain Vite apps work with this flow. `cf` also detects other frameworks, such as Astro, React Router, and SvelteKit, but detection does not mean the project builds. For example, Astro 6 and later does not build with `cf` during the beta.

Wrangler projects

Do not run `cf init .`, `cf dev`, `cf build`, or `cf deploy` in a project that has a `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml` file. The automatic setup ignores the Wrangler configuration and can produce a Worker that does not match it. To convert a Wrangler project, use `cf migrate` instead. Refer to [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/).

## Next steps

- Add storage, queues, or other resources with [bindings](https://developers.cloudflare.com/cf/projects/cloudflare-config/#declare-bindings).
- Route traffic to your Worker with [triggers](https://developers.cloudflare.com/cf/projects/cloudflare-config/#declare-triggers).
- Learn how `cf` develops, builds, and deploys projects in [Develop, build, and deploy](https://developers.cloudflare.com/cf/projects/).
- Explore every configuration option in the [configuration explorer](https://developers.cloudflare.com/cf/projects/config-explorer/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/get-started/first-worker/#page","headline":"Deploy your first Worker","description":"Create a Workers project with cf init, develop it locally, and deploy it with the Cloudflare CLI.","url":"https://developers.cloudflare.com/cf/get-started/first-worker/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/get-started/first-worker/og.png?v=77bcce5f2775c97f","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Find a zone, list, create, and delete DNS records, and find other commands with the Cloudflare CLI.
title: Manage resources from the command line
image: https://developers.cloudflare.com/cf/get-started/resources/og.png?v=bacce884889204ff
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Manage resources from the command line

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/get-started/resources/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cf` manages Cloudflare resources directly, without a Workers project. This guide uses DNS records to show a pattern that most resource commands follow: find a resource, list what it contains, preview a change, make the change, and clean up.

## Before you begin

- [Install `cf` and sign in](https://developers.cloudflare.com/cf/get-started/#sign-in). If you use an API token, it needs permission to edit DNS records in the zone.
- Add a domain to your Cloudflare account. This guide uses `example.com`.
- (Optional) Install [`jq` ↗︎](https://jqlang.org/) to filter JSON output.

## 1. Find a zone

List the zones you can access:

```sh
cf zones list
```

The result is a JSON array. To look up one domain, filter by name:

```sh
cf zones list --name example.com
```

Note the `id` of the zone. Zone-scoped commands accept the zone ID or the domain name. For details, refer to [Select a zone](https://developers.cloudflare.com/cf/get-started/#select-a-zone).

## 2. List DNS records

List the DNS records in the zone:

```sh
cf dns records list --zone example.com
```

Options narrow the results. For example, list only `A` records:

```sh
cf dns records list --zone example.com --type A
```

`cf dns records list` returns one page of results. To get more, use `--page` and `--per-page`.

## 3. Preview a change

Add `--dry-run` to see the request a command would send. A dry run prints the method, URL, and body as JSON, and exits without sending anything. It does not need credentials.

```sh
cf dns records create --zone <ZONE_ID> --body '{"type":"A","name":"test","content":"192.0.2.1","proxied":true}' --dry-run
```

```json
{
	"command": "cf dns records create",
	"method": "POST",
	"url": "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/dns_records",
	"pathParams": {
		"zone-id": "<ZONE_ID>"
	},
	"query": {},
	"bodyKind": "json",
	"body": {
		"type": "A",
		"name": "test",
		"content": "192.0.2.1",
		"proxied": true
	}
}
```

Use the zone ID in a dry run. A dry run does not look up domain names, so the preview would show the domain name where the ID belongs.

`--body` takes the JSON request body. Some operations, including this one, accept their input only through `--body`. For the fields the body accepts, refer to the [Create DNS Record API reference](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/).

## 4. Create the record

Run the same command without `--dry-run`:

```sh
cf dns records create --zone example.com --body '{"type":"A","name":"test","content":"192.0.2.1","proxied":true}'
```

`cf` prints the new record as JSON, including its `id`.

## 5. Filter the output

Because results are JSON on standard output, you can pipe them to `jq`. Print the name and content of each `A` record:

```sh
cf dns records list --zone example.com --type A | jq -r '.[] | "\(.name) \(.content)"'
```

Get the ID of the record you created:

```sh
cf dns records list --zone example.com --name test.example.com | jq -r '.[0].id'
```

## 6. Delete the record

Delete the record by its ID:

```sh
cf dns records delete <RECORD_ID> --zone example.com
```

`cf` asks you to confirm before it deletes anything. The default answer is no.

In a non-interactive session, such as a script or CI job, `cf` cannot ask. It prints the question and `Aborted.`, makes no change, and exits with status `0`. To delete without confirmation, pass `--force`:

```sh
cf dns records delete <RECORD_ID> --zone example.com --force
```

Caution

Because a skipped deletion exits with status `0`, a script cannot tell from the exit status that nothing was deleted. On some commands, `--force` also changes what the API operation does. Read the `--help` output of a command before you pass `--force` in a script.

## 7. Find other commands

Describe a task to find the command for it:

```sh
cf cli search "purge cached files for a URL"
```

`cf cli search` prints up to five matching commands as JSON, best match first. Each match includes the command and a short summary. It runs locally and does not need credentials.

To see the arguments and options a command accepts, add `--help`:

```sh
cf cache purge --help
```

To see the API request a generated command sends, including its method, path, parameters, and body fields, pass it to `cf schema`:

```sh
cf schema zones create
```

To browse commands by product, add `--help` to `cf`, to a product such as `cf dns`, or to any command.

## Next steps

- Run `cf` from scripts and pipelines with [Use `cf` in CI](https://developers.cloudflare.com/cf/ci/).
- Give a coding agent access to the same commands with [Use `cf` with coding agents](https://developers.cloudflare.com/cf/agents/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/get-started/resources/#page","headline":"Manage resources from the command line","description":"Find a zone, list, create, and delete DNS records, and find other commands with the Cloudflare CLI.","url":"https://developers.cloudflare.com/cf/get-started/resources/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/get-started/resources/og.png?v=bacce884889204ff","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Learn what stays the same and what changes when you move from Wrangler to cf, and decide when to migrate a project.
title: cf for Wrangler users
image: https://developers.cloudflare.com/cf/wrangler/og.png?v=ddbb6038a85893fe
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# cf for Wrangler users

Last updated Sep 30, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/wrangler/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

If you build with [Wrangler](https://developers.cloudflare.com/workers/wrangler/), most of what you know carries over to `cf`. This page explains what changes, how to use `cf` next to an existing Wrangler project, and when to migrate the project itself.

## What stays the same

Workers, bindings, compatibility dates, versions, and deployments work the same way. When you migrate, `cf migrate` keeps your Worker name, bindings, resource IDs, routes, and triggers. Local secrets in `.dev.vars` keep working under `cf dev`.

## What changes

The main differences between the two tools are:

| Area | Wrangler | `cf` |
| --- | --- | --- |
| Coverage | Workers and a subset of Cloudflare products | The public Cloudflare API, with more than 2,900 commands |
| Sign-in | `wrangler login` | `cf auth login`, with its own credentials |
| Project configuration | `wrangler.jsonc` or `wrangler.toml` | `cloudflare.config.ts`, written in TypeScript |
| Environments | `env` blocks selected with `--env` | Modes selected with `--mode` |
| Build | Wrangler's bundler | Wrangler's bundler or the Cloudflare Vite plugin |
| Deployable artifact | Internal to Wrangler | Build Output in `.cloudflare/output/v0/` |
| Output | Tables for many commands, with `--json` on some | JSON for most API commands |
| Resource identifiers | Names for many resources | The IDs that the Cloudflare API expects |
| Local and remote data | Some commands default to local data | Remote. `--local` works only for supported KV, D1, and R2 commands |

For example, Wrangler accepts a D1 database name, while `cf` expects the database ID:

```sh
wrangler d1 execute my-database --remote --command "SELECT 1"
cf d1 query <DATABASE_ID> --sql "SELECT 1"
```

For the full list of equivalents, refer to [Wrangler to cf reference](https://developers.cloudflare.com/cf/wrangler/reference/).

## Use `cf` alongside a Wrangler project

You do not need to migrate a project to start using `cf`. Resource and account commands, such as `cf d1 list` or `cf r2 buckets list`, work in any directory, including an unmigrated Wrangler project. They do not read the Wrangler configuration file, so they do not use its `account_id`. Set `CLOUDFLARE_ACCOUNT_ID` or choose an account when `cf` asks. For details, refer to [Select an account](https://developers.cloudflare.com/cf/get-started/#select-an-account).

Until you migrate the project, keep using Wrangler for development and deployment, such as `wrangler dev` and `wrangler deploy`. Use `cf` for account and resource tasks, including products that Wrangler does not cover.

`cf` does not reuse your Wrangler login. Before you run `cf` for the first time, [install it and sign in](https://developers.cloudflare.com/cf/get-started/). In automation, both tools read `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID`.

## Run project commands only after you migrate

`cf dev`, `cf build`, and `cf deploy` read `cloudflare.config.ts`. They do not read `wrangler.jsonc` or `wrangler.toml`. In a Wrangler project that you have not migrated, the result depends on the project:

| Project | Result |
| --- | --- |
| A Worker without a framework or static assets | The command fails with `cloudflare.config.ts is required when --experimental-new-config is enabled.` and a stack trace. |
| A Worker that uses the Cloudflare Vite plugin | Automatic configuration writes a new `cloudflare.config.ts` for a single-page application, without your entrypoint or bindings. In a project without `index.html`, `cf build` fails with `Cannot resolve entry module index.html`, and `cf dev` returns `404` responses. |
| A Worker with a static assets directory that contains `index.html` | Automatic configuration treats the project as a static site and writes `cloudflare.config.ts` and `wrangler.config.ts`. `cf build` succeeds, but the result is a static assets Worker named after `package.json`, without your Worker code or bindings. |

When automatic configuration runs, it also changes `package.json`, including the `deploy` script. It can also change the lockfile, `.gitignore`, and `vite.config.ts`. Without a terminal, such as in CI, it makes these changes without asking for confirmation.

Caution

Do not run `cf dev`, `cf build`, or `cf deploy` in a Wrangler project, including from CI, until you have run `cf migrate`.

If one of these commands already ran in the project, undo its changes before you migrate:

1. Run `git status` to list the changed and new files.
2. Restore each changed file, for example with `git restore package.json`.
3. Delete each new file that `git status` lists, such as `cloudflare.config.ts`, `wrangler.config.ts`, and the `.cloudflare/` directory.
4. Run `cf migrate`. It does not run while `cloudflare.config.ts` exists.

## When to migrate

Migrate a project when you want to:

- Write configuration in TypeScript, with binding types inferred from it.
- Use one CLI for project, account, and resource tasks.
- Build once and deploy the same Build Output later, for example from CI.

Keep a project on Wrangler for now if it relies on a task listed in [What still needs Wrangler](#what-still-needs-wrangler).

## How migration works

`cf migrate` reads the Wrangler configuration file and writes `cloudflare.config.ts` beside it. It converts bindings, routes, triggers, and environments, and adds `cf` to the project as a development dependency. It keeps Wrangler's bundler unless the project already uses the Cloudflare Vite plugin, so you do not need to adopt Vite to migrate.

Preview the changes, then run the migration:

```sh
cf migrate --dry-run
cf migrate
```

Some settings need manual work afterwards, such as Durable Object migrations, Workflows, Containers, and package scripts. `cf migrate` lists each item and marks it in the generated file. For Workflows and Containers, refer to [Workflows and Containers](https://developers.cloudflare.com/cf/wrangler/migrate/#workflows-and-containers). For the complete procedure, refer to [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/).

## What still needs Wrangler

`cf` is in beta and does not yet cover every Wrangler task:

- **Live logs**: `cf` cannot stream live logs yet. Run `npx wrangler tail <WORKER_NAME>` instead of installing Wrangler.
- **Single secrets**: `cf` cannot set a single secret yet. For options, refer to [Commands not yet supported](https://developers.cloudflare.com/cf/wrangler/reference/#commands-not-yet-supported).

Wrangler does not read `cloudflare.config.ts`. If you still run Wrangler commands in a migrated project, keep the Wrangler configuration file until you no longer need them.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/wrangler/#page","headline":"cf for Wrangler users","description":"Learn what stays the same and what changes when you move from Wrangler to cf, and decide when to migrate a project.","url":"https://developers.cloudflare.com/cf/wrangler/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/wrangler/og.png?v=ddbb6038a85893fe","dateModified":"2026-09-30","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Convert a Wrangler project to cf with cf migrate, resolve the follow-up items, and deploy it with cloudflare.config.ts.
title: Migrate a Wrangler project
image: https://developers.cloudflare.com/cf/wrangler/migrate/og.png?v=28973f624b22bb97
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Migrate a Wrangler project

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/wrangler/migrate/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cf migrate` converts a Wrangler configuration file to `cloudflare.config.ts` and adds `cf` to your project. It handles most of the conversion, then lists the items that you finish by hand. This page covers the whole migration: preview, run, resolve follow-up items, finish the project, validate, and deploy.

Beta

`cf` is in beta. Commands, configuration, and Build Output can change before the stable release.

The examples on this page migrate `orders-api`, a Worker with a D1 database, a queue, a cron trigger, a route, and a Durable Object:

```jsonc
{
	"name": "orders-api",
	"main": "src/index.ts",
	"account_id": "<ACCOUNT_ID>",
	"compatibility_date": "2026-08-24",
	"compatibility_flags": ["nodejs_compat"],
	"vars": {
		"ENVIRONMENT": "production",
	},
	"d1_databases": [
		{
			"binding": "DB",
			"database_name": "orders-db",
			"database_id": "<DATABASE_ID>",
		},
	],
	"queues": {
		"producers": [{ "binding": "JOBS", "queue": "orders-jobs" }],
		"consumers": [{ "queue": "orders-jobs", "max_batch_size": 10 }],
	},
	"routes": [{ "pattern": "api.example.com/*", "zone_name": "example.com" }],
	"triggers": {
		"crons": ["0 * * * *"],
	},
	"durable_objects": {
		"bindings": [{ "name": "COUNTERS", "class_name": "Counter" }],
	},
	"migrations": [{ "tag": "v1", "new_sqlite_classes": ["Counter"] }],
}
```

```toml
name = "orders-api"
main = "src/index.ts"
account_id = "<ACCOUNT_ID>"
compatibility_date = "2026-08-24"
compatibility_flags = [ "nodejs_compat" ]

[vars]
ENVIRONMENT = "production"

[[d1_databases]]
binding = "DB"
database_name = "orders-db"
database_id = "<DATABASE_ID>"

[[queues.producers]]
binding = "JOBS"
queue = "orders-jobs"

[[queues.consumers]]
queue = "orders-jobs"
max_batch_size = 10

[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"

[triggers]
crons = [ "0 * * * *" ]

[[durable_objects.bindings]]
name = "COUNTERS"
class_name = "Counter"

[[migrations]]
tag = "v1"
new_sqlite_classes = [ "Counter" ]
```

## Before you begin

- [Install `cf`](https://developers.cloudflare.com/cf/get-started/) and meet its [requirements](https://developers.cloudflare.com/cf/get-started/#requirements). You do not need to sign in until you deploy.
- Commit or stash every change, including untracked files. `cf migrate` does not write files when `git status` reports changes anywhere in the repository. Files that `.gitignore` excludes do not count.
- Install the project's dependencies. With the Wrangler bundler, the Worker's package needs Wrangler 4.136.0 or later installed. `cf migrate` uses it to write `wrangler.config.ts`, and `cf dev`, `cf build`, and `cf deploy` run it.
- Do not run `cf dev`, `cf build`, or `cf deploy` in the project first. In an unmigrated project they [write their own configuration or fail](https://developers.cloudflare.com/cf/wrangler/#unmigrated-projects).

## Preview the migration

In the directory that contains the Wrangler configuration file, run:

```sh
cf migrate --dry-run
```

Without a path, `cf migrate` looks for exactly one `wrangler.json`, `wrangler.jsonc`, or `wrangler.toml` file in the current directory. For a configuration file elsewhere, such as a package in a monorepo, pass its path:

```sh
cf migrate packages/api/wrangler.jsonc --dry-run
```

`cf migrate` writes its files next to the configuration file.

The dry run lists the files it would change and the follow-up items. It does not show file contents. For `orders-api`, it prints:

```txt
Using the Wrangler bundler because @cloudflare/vite-plugin is not declared. Pass --bundler vite to override.
Would update 4 file(s):
├─ cloudflare.config.ts
├─ wrangler.config.ts
├─ package.json
└─ package-lock.json

Follow-up work:
├─ [required] durable_objects.bindings.0: Durable Object bindings require manual review after migration.
│  └─ https://developers.cloudflare.com/workers/runtime-apis/context/#exports
└─ [required] migrations: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
   └─ https://developers.cloudflare.com/workers/runtime-apis/context/#exports

⚠ Migration requires follow-up work.
```

Like a real run, the dry run exits with status `1` while `[required]` items remain. It does not check whether the Git worktree is clean.

## Choose a bundler

`cf migrate` chooses a bundler for the migrated project from the `package.json` file beside the Wrangler configuration file:

| Bundler | Chosen when | Builds with | Build settings live in |
| --- | --- | --- | --- |
| Vite | `@cloudflare/vite-plugin` is declared | Vite and the Cloudflare Vite plugin | `vite.config.ts` |
| Wrangler | `@cloudflare/vite-plugin` is not declared | Wrangler, installed in the project | `wrangler.config.ts`, which `cf migrate` writes |

When you do not pass `--bundler`, the first line of output explains the choice, as in the `orders-api` preview. To override the choice, pass `--bundler vite` or `--bundler wrangler`.

`cf migrate` does not install Vite or create `vite.config.ts`. To move a project that does not use Vite yet to the Vite bundler, pass `--bundler vite`, then install Vite and the Cloudflare Vite plugin beta that `cf` uses:

npmyarnpnpmbun

```
npm i -D vite @cloudflare/vite-plugin@beta
```

```
yarn add -D vite @cloudflare/vite-plugin@beta
```

```
pnpm add -D vite @cloudflare/vite-plugin@beta
```

```
bun add -d vite @cloudflare/vite-plugin@beta
```

Then create `vite.config.ts`:

*vite.config.tsts*

```ts
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";

export default defineConfig({
	plugins: [cloudflare()],
});
```

If the project already uses the Cloudflare Vite plugin, install `@cloudflare/vite-plugin@beta` in the same way. The beta reads `cloudflare.config.ts` and has no `configPath` option. Remove `configPath` if `vite.config.ts` passes it to `cloudflare()`.

## Run the migration

Run `cf migrate` with the same arguments as the dry run, without `--dry-run`:

```sh
cf migrate
```

`cf migrate` accepts these arguments:

| Argument | Description |
| --- | --- |
| `[path]` | Path to the Wrangler configuration file. Defaults to the only `wrangler.json`, `wrangler.jsonc`, or `wrangler.toml` in the current directory. |
| `--bundler` | `vite` or `wrangler`. Chosen from `package.json` when omitted. |
| `--dry-run` | Lists the files that would change without writing them. |
| `--force` | Runs even if the Git worktree is not clean. It does not bypass any other check. |
| `--no-install` | Skips adding `cf` to the project. |

## Review what changed

Review the changes with `git status` and `git diff`. `cf migrate` changes these files:

| File | Change |
| --- | --- |
| `cloudflare.config.ts` | Created next to the Wrangler configuration file |
| `wrangler.config.ts` | Created with the Wrangler bundler only. It holds Wrangler build settings. |
| `package.json` and the lockfile | Updated to add `cf` as a development dependency |
| The Wrangler configuration file | Unchanged |
| Package scripts, `vite.config.ts`, `.gitignore`, `tsconfig.json`, and source | Unchanged |

The project needs its own `cf` dependency because `cloudflare.config.ts` imports from `cf/config`. `cf migrate` installs it with the package manager that the project uses, based on the `packageManager` field or the lockfile. With npm, the install also rewrites `package.json` with two-space indentation.

If the only `package.json` is in a parent directory, such as a workspace root, `cf migrate` does not change it. Install `cf` in the package that contains the Worker instead.

`cf migrate` never overwrites files. It stops if `cloudflare.config.ts` exists, or if `wrangler.config.ts` exists and you use the Wrangler bundler. `--force` does not change this.

## Read the output

Each follow-up item has one of two levels:

- `[required]`: you must resolve it before the project builds. While any required item remains, `cf migrate` exits with status `1`. This does not mean that the migration failed.
- `[info]`: context that needs no change.

`cf migrate` also writes each required item into `cloudflare.config.ts` as a `TODO(@cloudflare)` comment. When required items remain, it adds a `throw` statement at the top of the file. Until you delete that statement, `cf dev`, `cf build`, and `cf deploy` fail with this error:

```txt
Error: Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.
```

For `orders-api`, `cf migrate` generates this file:

*cloudflare.config.tsts*

```ts
import { bindings, defineConfig, triggers } from "cf/config";

/**
 * This migration needs manual work. Resolve every TODO in this file, then remove the error below.
 */
/**
 * TODO(@cloudflare): cf migrate: durable_objects.bindings.0: Durable Object bindings require manual review after migration.
 * @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
 */
/**
 * TODO(@cloudflare): cf migrate: migrations: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
 * @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
 */
throw new Error("Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.");

export default defineConfig({
	accountId: "<ACCOUNT_ID>",
	worker: {
		name: "orders-api",
		compatibilityDate: "2026-08-24",
		compatibilityFlags: [
			"nodejs_compat",
		],
		entrypoint: "src/index.ts",
		triggers: [
			triggers.fetch({
				pattern: "api.example.com/*",
				zone: "example.com",
			}),
			triggers.scheduled({
				schedule: "0 * * * *",
			}),
			triggers.queue({
				maxBatchSize: 10,
				name: "orders-jobs",
			}),
		],
		env: {
			ENVIRONMENT: bindings.text("production"),
			DB: bindings.d1({
				name: "orders-db",
				id: "<DATABASE_ID>",
			}),
			JOBS: bindings.queue({
				name: "orders-jobs",
			}),
			COUNTERS: bindings.durableObject({
				worker: "orders-api",
				exportName: "Counter",
			}),
		},
		/**
		 * TODO(@cloudflare): cf migrate: Durable Object bindings require manual review after migration.
		 * @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
		 */
		/**
		 * TODO(@cloudflare): cf migrate: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
		 * @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
		 */
	},
});
```

Some items link to Wrangler or Workers runtime documentation. The next section describes how to resolve each item for `cf`. When you have resolved every item, delete the `TODO(@cloudflare)` comments, the comment that starts with `This migration needs manual work`, and the `throw` statement.

## Resolve follow-up items

### Durable Objects

A project with Durable Objects always has required items: one for each Durable Object binding and one for the `migrations` history. `cf migrate` converts each binding, but it does not convert `migrations`.

1. Import `exports` from `cf/config`. Under `worker`, add an `exports` entry for each Durable Object class that is live today. Match the storage that the class already uses: `"sqlite"` for classes created with `new_sqlite_classes`, and `"legacy-kv"` for classes created with `new_classes`.

   ```ts
   exports: {
   	Counter: exports.durableObject({ storage: "sqlite" }),
   },
   ```


2. Review each generated binding. In `bindings.durableObject({ worker, exportName })`, `worker` is the name of the Worker that defines the class and `exportName` is the class name.
3. Delete the TODO comments for these items.

Do not copy renames or deletions that have already been applied. For classes that you still need to rename, delete, or transfer, refer to [Convert Durable Object migrations](https://developers.cloudflare.com/cf/wrangler/reference/#convert-durable-object-migrations).

### Environments

`cf migrate` converts each `env.<NAME>` block into a `case` of a `switch (ctx.mode)` statement. Each case returns a complete configuration. It follows Wrangler's inheritance rules: bindings, `vars`, and secrets from the top level are not copied into environments. An environment without its own `name` gets `<NAME>-<ENVIRONMENT>`. The generated configuration has this shape:

*cloudflare.config.tsts*

```ts
export default defineConfig((ctx) => {
	switch (ctx.mode) {
		case "staging": {
			return {
				worker: {
					name: "orders-api-staging",
					// ...
				},
			};
		}
		default: {
			return {
				worker: {
					name: "orders-api",
					// ...
				},
			};
		}
	}
});
```

Replace `--env <NAME>` with `--mode <NAME>`:

```sh
cf build --mode staging
cf deploy --mode staging
```

A required item that applies to the top-level configuration appears again for each environment that inherits it.

Without `--mode`, the Wrangler bundler uses the `default` branch. The Vite bundler uses the `development` mode for `cf dev` and `production` for `cf build` and `cf deploy`. With the Vite bundler, an environment named `production` or `development` would be selected without `--mode`, so `cf migrate` marks it as required. Rename that `case`, for example to `"prod"`, and pass the new name with `--mode`.

For mode defaults across all commands, refer to [Convert environments to modes](https://developers.cloudflare.com/cf/wrangler/reference/#environments-to-modes).

### Build settings

Wrangler build fields, such as `build`, `minify`, `alias`, and `assets.directory`, do not belong in `cloudflare.config.ts`.

With the Wrangler bundler, `cf migrate` moves them to `wrangler.config.ts` with camelCase keys, and no follow-up item is needed. For example:

*wrangler.config.tsts*

```ts
import { defineWranglerConfig } from "wrangler/experimental-config";

export default defineWranglerConfig({
	alias: {
		lodash: "lodash-es",
	},
	minify: true,
	uploadSourceMaps: true,
	build: {
		command: "npm run build:css",
	},
	dev: {
		port: 8788,
	},
	types: {
		generate: false,
	},
	assetsDirectory: "./public",
});
```

`wrangler.config.ts` is experimental and can change during the beta.

With the Vite bundler, `cf migrate` lists these fields in a required item and does not move them. Move each setting to its Vite equivalent in `vite.config.ts`, such as `alias` to `resolve.alias`. For every field, refer to [Build settings](https://developers.cloudflare.com/cf/wrangler/reference/#build-settings).

A custom `build` command does not carry over to the Vite bundler. `cf build` runs Vite directly, so run the command yourself first, for example `npm run build:css && cf build`.

### Source maps

With the Vite bundler, `cf migrate` lists `upload_source_maps` in its required item for build settings. To keep uploading Worker source maps, turn on `build.sourcemap` for the Worker's Vite environment, then delete the TODO comment. By default, the Cloudflare Vite plugin beta names the Worker's environment `ssr`:

*vite.config.tsts*

```ts
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";

export default defineConfig({
	plugins: [cloudflare()],
	environments: {
		ssr: {
			build: {
				sourcemap: true,
			},
		},
	},
});
```

How `cf migrate` reports source maps can change during the beta.

### D1 migrations

`cf migrate` does not convert the `migrations_dir`, `migrations_pattern`, or `migrations_table` fields of a D1 binding. Pass them to `cf d1 migrations apply` instead:

| Wrangler field | `cf d1 migrations apply` option |
| --- | --- |
| `migrations_dir` | `--dir`, which defaults to `./migrations` |
| `migrations_pattern` | `--pattern` |
| `migrations_table` | `--table`, which defaults to `d1_migrations` |

For example:

```sh
cf d1 migrations apply <DATABASE_ID> --dir db/migrations
```

`cf d1 migrations apply` takes the database ID. Unlike Wrangler, it applies migrations to the remote database unless you add `--local`.

### Other required items

Resolve the remaining items as follows, then delete each TODO comment:

| Item | What to do |
| --- | --- |
| Preview resources: `preview_id`, `preview_bucket_name`, `preview_database_id` | `cloudflare.config.ts` has no preview resource fields. During `cf dev`, bindings use local resources unless you set `dev: { remote: true }` on the binding. |
| A route that uses `zone_id` | `cf migrate` copies the zone ID into the `zone` option of `triggers.fetch()`, which accepts a zone name or a zone ID. Confirm the value. |
| A service binding to a legacy service environment | `cf migrate` rewrites the target to `<SERVICE>-<ENVIRONMENT>`. Confirm that this is the Worker to bind to. |
| Workers Sites (`site`) | Not supported. Move the site to [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/). |
| `previews` | Converted to a branch on `ctx.isPreview`. Review the branch. For more information, refer to [Deploy a preview](https://developers.cloudflare.com/cf/projects/#deploy-a-preview). |
| A missing `name` or `compatibility_date` | Replaced with the placeholders `"TODO"` and `"YYYY-MM-DD"`. Set real values. |
| Unsupported or unknown fields, such as `keep_vars` | Remove them, or find an equivalent in the [configuration reference](https://developers.cloudflare.com/cf/projects/cloudflare-config/). |
| Installing `cf` | Appears with `--no-install`, after a failed install, or when no `package.json` is beside the configuration file. Install `cf` in the Worker's package. |

To install `cf` as a development dependency, run:

npmyarnpnpmbun

```
npm i -D cf
```

```
yarn add -D cf
```

```
pnpm add -D cf
```

```
bun add -d cf
```

### Workflows and Containers

`cf migrate` does not convert Workflow bindings or Containers configuration. It reports both as required items. Add them to `cloudflare.config.ts` by hand:

- For a Workflow, declare the class with `exports.workflow({ name })` in the Worker that defines it. Bind to it with `bindings.workflow({ name, worker, exportName })`. Refer to [Declare exports](https://developers.cloudflare.com/cf/projects/cloudflare-config/#declare-exports).
- For a Container, define it with `defineContainer()`, add it to the top-level `containers` array, and reference it from an `exports.durableObject({ storage: "sqlite", container })` entry. Refer to [Attach a Container](https://developers.cloudflare.com/cf/projects/cloudflare-config/#attach-a-container).

Then delete the TODO comment for each item.

### Secrets

`cf migrate` never reads secret files. It lists any `.dev.vars` or `.env` files that it finds as an `[info]` item. `cf dev` still loads `.dev.vars` for local development.

Entries in `secrets.required` become `bindings.secret()` values. Declare any other secret that the Worker reads the same way:

```ts
env: {
	API_TOKEN: bindings.secret(),
},
```

To upload secrets with a new version, pass `--secrets-file <PATH>` to `cf deploy` or `cf workers versions create`. The file can be JSON or `.env` format.

## Finish the project

`cf migrate` leaves the rest of the project to you:

1. Replace Wrangler commands in the `package.json` scripts. Wrangler commands read the Wrangler configuration file and ignore `cloudflare.config.ts`.

   *package.jsonjson*

   

   ```json
   {
   	"scripts": {
   		"dev": "cf dev",
   		"build": "cf build",
   		"deploy": "cf deploy"
   	}
   }
   ```

   `cf build` runs Vite or Wrangler directly, not your `build` script. To run extra steps, chain them yourself, for example `tsc -b && cf build`.
2. Add `.cloudflare/` to `.gitignore`. The directory holds Build Output, generated types, and other files that `cf` generates.
3. Set `"type": "module"` in `package.json`. Without it, Node.js prints a `MODULE_TYPELESS_PACKAGE_JSON` warning each time `cf` loads `cloudflare.config.ts`.
4. Generate types:
   - With the Vite bundler, `cf dev` and `cf build` write `.cloudflare/types/index.d.ts`.
   - With the Wrangler bundler, `cf migrate` sets `types: { generate: false }` in `wrangler.config.ts`. Change it to `true`, or run `cf workers types`.

   Then add the generated types to `tsconfig.json`:

   *tsconfig.jsonjson*

   

   ```json
   {
   	"include": ["src", "cloudflare.config.ts", ".cloudflare/types"]
   }
   ```


5. (Optional) Replace the string `entrypoint` with an import that uses the `cf-worker` attribute:

   *cloudflare.config.tsts*

   

   ```ts
   import * as entrypoint from "./src/index.ts" with { type: "cf-worker" };
   ```

   Under `worker`, replace `entrypoint: "src/index.ts"` with `entrypoint`. With a string path, `Env` binding types are still inferred, but the types of your Worker module exports are not. To type-check a `.ts` import path, set `allowImportingTsExtensions` in `tsconfig.json`.

For a finished version of `orders-api`, refer to [Complete example](https://developers.cloudflare.com/cf/wrangler/reference/#complete-example).

## Validate the project

Start the project locally with `cf dev` and check that it responds. Then stop the development server, build the project, and run a dry-run deployment:

```sh
cf build
cf deploy --dry-run
```

None of these commands need you to sign in. `cf deploy --dry-run` builds the project, prints the bindings it would deploy, and uploads nothing.

If the project has environments, also validate each mode:

```sh
cf build --mode staging
cf deploy --dry-run --mode staging
```

## Deploy

Sign in, then deploy:

```sh
cf auth login
cf deploy
```

`cf deploy` builds the project, uploads a new Worker Version, and deploys it. For deployment options, refer to [Develop, build, and deploy](https://developers.cloudflare.com/cf/projects/). To deploy from CI, refer to [Use cf in CI](https://developers.cloudflare.com/cf/ci/).

## Remove the Wrangler configuration

Once `cloudflare.config.ts` exists, `cf` ignores the Wrangler configuration file. Delete the Wrangler file after you deploy with `cf` and your scripts and CI use `cf`.

Wrangler does not read `cloudflare.config.ts`. If you still run Wrangler commands in the project, such as `wrangler tail`, keep the Wrangler configuration file until you no longer need them.

## Troubleshooting

### No Wrangler configuration found

```txt
No Wrangler config found in <DIRECTORY>. Pass its path to cf migrate.
```

Run `cf migrate` in the directory that contains the Wrangler configuration file, or pass the file path. If the directory contains more than one Wrangler configuration file, `cf migrate` reports `Multiple Wrangler configs found in <DIRECTORY>`. Pass the exact path.

### Git worktree is not clean

```txt
Git worktree is not clean. Commit or stash your changes before running a codemod, or rerun with `--force` to bypass this safety check.
```

Commit or stash every change, including untracked files, then run the migration again.

### `cloudflare.config.ts` already exists

```txt
Cannot migrate because <PATH>/cloudflare.config.ts already exists. Inspect and finish the existing migration; it will not be overwritten. Automated agents should read its TODOs and ask the user about unresolved choices.
```

If an earlier `cf migrate` run created the file, finish that migration. If `cf dev`, `cf build`, or `cf deploy` created it, undo their changes as described in [Run project commands only after you migrate](https://developers.cloudflare.com/cf/wrangler/#unmigrated-projects), then run `cf migrate`.

### Wrangler is missing or too old

With the Wrangler bundler, `cf migrate` needs a local Wrangler installation, even for a dry run. Without one, it reports:

```txt
Generating wrangler.config.ts requires wrangler 4.100.0 or newer because earlier versions do not export wrangler/experimental-config. No local Wrangler installation was found. Update Wrangler and retry the migration.
```

After the migration, `cf dev`, `cf build`, and `cf deploy` need Wrangler 4.136.0 or later. With an older version, their error includes:

```txt
cf requires wrangler@4.136.0 or newer for cf dev, cf build, cf deploy, and cf previews deploy.
```

Install the project's dependencies or update Wrangler, then run the command again.

### Migration incomplete

```txt
Error: Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.
```

Resolve the [follow-up items](#resolve-follow-up-items), then delete the `throw` statement at the top of `cloudflare.config.ts`.

### `cloudflare.config.ts` is required

```txt
Error: cloudflare.config.ts is required when --experimental-new-config is enabled.
```

`cf dev`, `cf build`, or `cf deploy` ran in a Wrangler project that you have not migrated. Run `cf migrate`.

### Wrangler is not installed

```txt
wrangler is declared in <PATH>/package.json but is not installed.
```

Install the project's dependencies. `cf` looks for Wrangler only in the Worker package's own `node_modules` directory. In a monorepo, a copy hoisted to the workspace root does not count.

If `package.json` declares neither package, for example because you use a global Wrangler installation, the error starts with `No Cloudflare dev-server is installed in this project`. Add Wrangler as a development dependency, or install Vite and the Cloudflare Vite plugin as described in [Choose a bundler](#choose-a-bundler).

### Unknown command: migrate

A global `cf` runs the copy of `cf` installed in the project. If the project pins an older `cf` without `cf migrate`, update the project's `cf` dependency, or run the latest version once with `npx cf@latest migrate`.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/wrangler/migrate/#page","headline":"Migrate a Wrangler project","description":"Convert a Wrangler project to cf with cf migrate, resolve the follow-up items, and deploy it with cloudflare.config.ts.","url":"https://developers.cloudflare.com/cf/wrangler/migrate/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/wrangler/migrate/og.png?v=28973f624b22bb97","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Find cf equivalents for Wrangler commands, and map Wrangler configuration, build settings, and environments to cf.
title: Wrangler to cf reference
image: https://developers.cloudflare.com/cf/wrangler/reference/og.png?v=89a02a5f88f20fa3
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Wrangler to cf reference

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/wrangler/reference/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cf migrate` converts a Wrangler project to `cf` for you. It writes `cloudflare.config.ts` from the Wrangler configuration file, adds `cf` to the project, and lists the items that you finish by hand. Start with [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/), then use this page to understand what `cf migrate` changed or to finish a conversion by hand.

## Commands

Most Wrangler commands have a `cf` equivalent, although the command name and arguments can differ. For example, Worker versions and deployments are under `cf workers versions` and `cf workers deployments`.

To find the `cf` command for a task, use any of the following:

- **Search**: describe the task to `cf cli search`, then inspect the match with `cf schema`:

  ```sh
  cf cli search "create a D1 database"
  cf schema d1 create
  ```


- **Help**: add `--help` to a command group, such as `cf d1 --help`, to list its commands and options.
- **Coding agent**: ask your agent for the `cf` equivalent of a Wrangler command. To set up your agent, refer to [Use cf with coding agents](https://developers.cloudflare.com/cf/agents/).

Resource commands in `cf` take the identifiers that the Cloudflare API expects, such as a D1 database ID rather than its name. They act on remote resources. `--local` works only for a few resources that local development provides, such as KV keys, D1 through `cf d1 raw`, `cf d1 migrations list`, and `cf d1 migrations apply`, and R2 objects. For the full list, refer to [Local resource data](https://developers.cloudflare.com/cf/projects/#local-resource-data). Commands without a local equivalent, such as `cf d1 query`, return an error.

### Commands not yet supported

`cf` is in beta, and some Wrangler commands are not supported yet. Run these with `npx wrangler` instead of installing Wrangler. Wrangler does not read `cloudflare.config.ts`, so pass the Worker name.

- **`wrangler tail`**: `cf` cannot stream live logs yet. Run:

  ```sh
  npx wrangler tail <WORKER_NAME>
  ```


- **`wrangler secret put`**: `cf` cannot set a single secret yet. Run `npx wrangler secret put <SECRET_NAME> --name <WORKER_NAME>`, or upload secrets with a new Worker version by passing `--secrets-file <PATH>` to `cf deploy` or `cf workers versions create`.

## Configuration fields

`cf migrate` converts Wrangler fields as the following table shows. Worker settings go under `worker` in `cloudflare.config.ts`, and bindings go under `worker.env`. A required item is a follow-up that you resolve by hand, as described in [Resolve follow-up items](https://developers.cloudflare.com/cf/wrangler/migrate/#resolve-follow-up-items).

| Wrangler field | `cloudflare.config.ts` | Notes |
| --- | --- | --- |
| `name` | `worker.name` | — |
| `main` | `worker.entrypoint` | Written as a string path. You can replace it with a `cf-worker` import. |
| `compatibility_date` | `worker.compatibilityDate` | — |
| `compatibility_flags` | `worker.compatibilityFlags` | — |
| `account_id` | `accountId` | Top level |
| `compliance_region` | `complianceRegion` | Top level. `fedramp_high` becomes `fedramp-high`. |
| `vars` | `bindings.text()` or `bindings.json()` | Strings use `text()`. Other values use `json()`. |
| `secrets.required` | `bindings.secret()` | — |
| KV, D1, R2, Hyperdrive, and other bindings | The matching `bindings` builder | Preview resource fields are a required item. |
| `services` | `bindings.worker({ worker })` | A legacy service environment is a required item. |
| `queues.producers` | `bindings.queue({ name })` | — |
| `queues.consumers` | `triggers.queue({ name })` | Consumer settings become camelCase options, such as `maxBatchSize`. |
| Hyperdrive `localConnectionString` | `dev: { connectionString }` on `bindings.hyperdrive()` | — |
| `remote: true` on a binding | `dev: { remote: true }` | — |
| `routes` with `zone_name` | `triggers.fetch({ pattern, zone })` | — |
| `routes` with `zone_id` | `triggers.fetch({ pattern, zone })` | Required item. `zone` accepts a zone name or a zone ID. |
| `routes` with `custom_domain: true` | `worker.domains` | — |
| `triggers.crons` | `triggers.scheduled({ schedule })` | — |
| `durable_objects.bindings` | `bindings.durableObject({ worker, exportName })` | Required item. Review each binding. |
| `migrations` | `worker.exports` | Not converted. Refer to [Convert Durable Object migrations](#convert-durable-object-migrations). |
| `workflows` | `bindings.workflow()` and `exports.workflow()` | Required item. Refer to [Workflows](https://developers.cloudflare.com/cf/projects/cloudflare-config/#declare-exports). |
| `containers` | `defineContainer()` in top-level `containers` | Required item. Refer to [Containers](https://developers.cloudflare.com/cf/projects/cloudflare-config/#attach-a-container). |
| `assets.binding` | `bindings.assets()` | — |
| `assets.html_handling`, `not_found_handling`, `run_worker_first` | `worker.assets` | Keys become camelCase, such as `notFoundHandling`. |
| `assets.directory` | Build settings | Refer to [Build settings](#build-settings). |
| `observability` | `worker.observability` | Keys become camelCase, such as `headSamplingRate`. |
| `limits` | `worker.limits` | Keys become camelCase, such as `cpuMs`. |
| `placement` | `worker.placement` | — |
| `tail_consumers` | `worker.tailConsumers` | — |
| `streaming_tail_consumers` | `worker.tailConsumers` | Each entry gets `streaming: true`. |
| `workers_dev` | `worker.workersDev` | — |
| `preview_urls` | `worker.previewUrls` | — |
| `env.<NAME>` | A `case` in `switch (ctx.mode)` | Refer to [Convert environments to modes](#environments-to-modes). |
| `previews` | A branch on `ctx.isPreview` | Required item. Review the branch. |
| `site` | — | Not supported. Move the site to [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/). |
| D1 `migrations_dir`, `migrations_pattern`, `migrations_table` | — | Pass `--dir`, `--pattern`, and `--table` to `cf d1 migrations apply`. |
| `build`, `minify`, `alias`, and other build fields | Build settings | Refer to [Build settings](#build-settings). |

For every field and builder, refer to [Programmatic configuration](https://developers.cloudflare.com/cf/projects/cloudflare-config/) and the [Configuration explorer](https://developers.cloudflare.com/cf/projects/config-explorer/).

## Build settings

Build settings do not go in `cloudflare.config.ts`. Where they go depends on the bundler:

| Wrangler field | Vite bundler: `vite.config.ts` | Wrangler bundler: `wrangler.config.ts` |
| --- | --- | --- |
| `alias` | `resolve.alias` | `alias` |
| `define` | `define` | `define` |
| `minify` | `build.minify` | `minify` |
| `upload_source_maps` | `build.sourcemap` in the Worker's Vite environment | `uploadSourceMaps` |
| `assets.directory` | `publicDir` | `assetsDirectory` |
| `build` | Run the command yourself before `cf build` | `build`, with camelCase keys |
| `dev` | `server` options | `dev`, with camelCase keys |
| `rules`, `tsconfig`, `no_bundle`, `find_additional_modules`, `base_dir`, `preserve_file_names` | Not used. Vite handles module resolution and bundling. | camelCase keys, such as `noBundle` and `baseDir` |

With the Wrangler bundler, `cf migrate` writes these settings to `wrangler.config.ts` for you and adds `types: { generate: false }`. With the Vite bundler, it lists the fields in a required item for you to move. `wrangler.config.ts` is experimental and can change during the beta.

## Convert environments to modes

Wrangler environments inherit some top-level fields. `cloudflare.config.ts` does not merge environments. It returns one complete configuration for each mode instead. `cf migrate` writes a `switch (ctx.mode)` statement with one `case` for each environment. For the generated shape, refer to [Environments](https://developers.cloudflare.com/cf/wrangler/migrate/#environments).

Replace `--env <NAME>` with `--mode <NAME>` on project commands, such as `cf dev`, `cf build`, `cf deploy`, `cf workers versions create`, and `cf workers triggers deploy`.

Without `--mode`, the mode depends on the command and the bundler:

| Command | Vite bundler | Wrangler bundler |
| --- | --- | --- |
| `cf dev` | `development` | `undefined` |
| `cf build` and `cf deploy` | `production` | `undefined` |
| API commands, such as `cf d1 list` | `undefined` | `undefined` |

API commands evaluate `cloudflare.config.ts` only to read `accountId` and `complianceRegion`. If `accountId` depends on the mode, a Vite build and an API command can resolve different accounts. Keep `accountId` independent of the mode, or pass the same `--mode` to every command.

For more information, refer to [Modes](https://developers.cloudflare.com/cf/projects/#modes).

## Convert Durable Object migrations

`worker.exports` replaces the ordered `migrations` history. `cf migrate` does not convert it.

On the first deployment that switches from `migrations` to `worker.exports`, declare every class whose namespace is live today. Use `storage: "sqlite"` or `storage: "legacy-kv"` to match its existing storage.

Do not copy the full migration history. Omit rename and delete operations that have already been applied. If you add them, they become stale tombstones that the deployment reports as safe to remove.

Add a tombstone only for a lifecycle change that has not been applied yet:

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#durable-object-tombstones-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#durable-object-tombstones-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "orders-api", (name reference)</summary>



<code>name</code>Required<a href="#durable-object-tombstones-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#durable-object-tombstones-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "2026-08-24", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#durable-object-tombstones-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#durable-object-tombstones-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#durable-object-tombstones-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#durable-object-tombstones-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

<details>

<summary>OldCounter: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#durable-object-tombstones-exports-durableobject-renamed">Link to durableObject</a>

<code>durableObject(options: DurableObjectRenamedExportOptions): DurableObjectRenamedExport;</code>

Rename a provisioned Durable Object namespace's class.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>state: "renamed"</code></dt>
<dd></dd>

<dt><code>renamedTo: string</code></dt>
<dd>The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.</dd></dl></details>



</details>

<details>

<summary>state: "renamed", (state reference)</summary>



<code>state</code>Required<a href="#durable-object-tombstones-exports-durableobject-renamed-state">Link to state</a>

<code>state: "renamed"</code>

The type definition does not include a description.

</details>

<details>

<summary>renamedTo: "Counter", (renamedTo reference)</summary>



<code>renamedTo</code>Required<a href="#durable-object-tombstones-exports-durableobject-renamed-renamedto">Link to renamedTo</a>

<code>renamedTo: string</code>

The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.

</details>

}),

<details>

<summary>UnusedCounter: exports.durableObject({ state: "deleted" }), (durableObject, state reference)</summary>



<code>durableObject</code>Builder<a href="#durable-object-tombstones-exports-durableobject-deleted">Link to durableObject</a>

<code>durableObject(options: DurableObjectDeletedExportOptions): DurableObjectDeletedExport;</code>

Retire a provisioned Durable Object namespace whose class has been removed from code.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>state: "deleted"</code></dt>
<dd></dd>

</dl></details>



<code>state</code>Required<a href="#durable-object-tombstones-exports-durableobject-deleted">Link to state</a>

<code>state: "deleted"</code>

The type definition does not include a description.

</details>

},

},

});

Keep a tombstone until a deployment response reports that it is stale, then remove it. Use `cf deploy`, rather than a version upload, for a version that creates, deletes, renames, or transfers a Durable Object class. You cannot roll back a Durable Object lifecycle change to a version from before the change.

For transfers between Workers and the full list of states, refer to [Manage Durable Object lifecycle](https://developers.cloudflare.com/cf/projects/cloudflare-config/#manage-durable-object-lifecycle).

## Complete example

This example finishes the migration of `orders-api`, the Worker used in [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/). It has a D1 database, a queue, a cron trigger, a route, and a Durable Object. After `cf migrate` and the follow-up steps, `cloudflare.config.ts` is:

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig, exports, triggers } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

type Job = { orderId: string };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#orders-api-config-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>accountId: "&lt;ACCOUNT_ID&gt;", (accountId reference)</summary>



<code>accountId</code>Optional<a href="#orders-api-config-settings-accountid">Link to accountId</a>

<code>accountId?: string</code>

This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.

</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#orders-api-config-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "orders-api", (name reference)</summary>



<code>name</code>Required<a href="#orders-api-config-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#orders-api-config-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "2026-08-24", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#orders-api-config-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>compatibilityFlags: ["nodejs_compat"], (compatibilityFlags reference)</summary>



<code>compatibilityFlags</code>Optional<a href="#orders-api-config-workerconfig-compatibilityflags">Link to compatibilityFlags</a>

<code>compatibilityFlags?: string[]</code>

A list of flags that enable features from upcoming features of the Workers runtime, usually used together with <code>compatibilityDate</code>. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-flags/">https://developers.cloudflare.com/workers/configuration/compatibility-flags/</a>

Default: <code>[]</code>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#orders-api-config-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>ENVIRONMENT: bindings.text("production"), (text reference)</summary>



<code>text</code>Builder<a href="#orders-api-config-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

<details>

<summary>DB: bindings.d1({ (d1 reference)</summary>



<code>d1</code>Builder<a href="#orders-api-config-bindings-d1-default">Link to d1</a>

<code>d1(options?: D1BindingOptions): D1Binding;</code>

Binding to a D1 database. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases">https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The UUID of this D1 database (not required).</dd>

<dt><code>name?: string</code></dt>
<dd>The name of this D1 database.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>name: "orders-db", (name reference)</summary>



<code>name</code>Optional<a href="#orders-api-config-bindings-d1-default-name">Link to name</a>

<code>name?: string</code>

The name of this D1 database.

</details>

<details>

<summary>id: "&lt;DATABASE_ID&gt;", (id reference)</summary>



<code>id</code>Optional<a href="#orders-api-config-bindings-d1-default-id">Link to id</a>

<code>id?: string</code>

The UUID of this D1 database (not required).

</details>

}),

<details>

<summary>JOBS: bindings.queue&lt;Job&gt;({ name: "orders-jobs" }), (queue, name reference)</summary>



<code>queue</code>Builder<a href="#orders-api-config-bindings-queue-default">Link to queue</a>

<code>queue&lt;TBody = unknown&gt;(options?: QueueBindingOptions): TypedQueueBinding&lt;TBody&gt;;</code>

Producer binding to a Cloudflare Queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this Queue.</dd>

<dt><code>deliveryDelay?: number</code></dt>
<dd>The number of seconds to wait before delivering a message.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



<code>name</code>Optional<a href="#orders-api-config-bindings-queue-default">Link to name</a>

<code>name?: string</code>

The name of this Queue.

</details>

<details>

<summary>COUNTERS: bindings.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#orders-api-config-bindings-durableobject-all">Link to durableObject</a>

<code>durableObject&lt;TWorker$1 extends WorkerReference, TExportName$1 extends DurableObjectExportName&lt;TWorker$1&gt;&gt;(options: DurableObjectBindingOptions&lt;TWorker$1, TExportName$1&gt;): DurableObjectBinding&lt;TWorker$1, TExportName$1&gt;;</code>

Binding to a Durable Object class. <code>worker</code> is the name or config of the Worker that defines the class; <code>exportName</code> is the exported class name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the Worker that defines the Durable Object class.</dd>

<dt><code>exportName: TExportName$1</code></dt>
<dd>The exported class name of the Durable Object.</dd></dl></details>



</details>

<details>

<summary>worker: "orders-api", (worker reference)</summary>



<code>worker</code>Required<a href="#orders-api-config-bindings-durableobject-all-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the Worker that defines the Durable Object class.

</details>

<details>

<summary>exportName: "Counter", (exportName reference)</summary>



<code>exportName</code>Required<a href="#orders-api-config-bindings-durableobject-all-exportname">Link to exportName</a>

<code>exportName: TExportName$1</code>

The exported class name of the Durable Object.

</details>

}),

},

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#orders-api-config-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#orders-api-config-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#orders-api-config-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

},

<details>

<summary>triggers: [ (triggers reference)</summary>



<code>triggers</code>Optional<a href="#orders-api-config-workerconfig-triggers">Link to triggers</a>

<code>triggers?: Trigger[]</code>

Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a>

</details>

<details>

<summary>triggers.fetch({ (fetch reference)</summary>



<code>fetch</code>Builder<a href="#orders-api-config-triggers-fetch-default">Link to fetch</a>

<code>fetch(options: FetchTriggerOptions): FetchTrigger;</code>

Fetch trigger — a route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>pattern: string</code></dt>
<dd>A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a></dd>

<dt><code>zone?: string</code></dt>
<dd>The DNS zone the pattern is attached to. Required when the pattern is ambiguous.</dd></dl></details>



</details>

<details>

<summary>pattern: "api.example.com/*", (pattern reference)</summary>



<code>pattern</code>Required<a href="#orders-api-config-triggers-fetch-default-pattern">Link to pattern</a>

<code>pattern: string</code>

A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

</details>

<details>

<summary>zone: "example.com", (zone reference)</summary>



<code>zone</code>Optional<a href="#orders-api-config-triggers-fetch-default-zone">Link to zone</a>

<code>zone?: string</code>

The DNS zone the pattern is attached to. Required when the pattern is ambiguous.

</details>

}),

<details>

<summary>triggers.queue({ name: "orders-jobs", maxBatchSize: 10 }), (queue, name, maxBatchSize reference)</summary>



<code>queue</code>Builder<a href="#orders-api-config-triggers-queue-default">Link to queue</a>

<code>queue(options: QueueConsumerTriggerOptions): QueueConsumerTrigger;</code>

Queue consumer trigger — invokes this Worker when messages arrive on the named queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (8)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the queue from which this consumer should consume.</dd>

<dt><code>deadLetterQueue?: string</code></dt>
<dd>The queue to send messages that failed to be consumed.</dd>

<dt><code>maxBatchSize?: number</code></dt>
<dd>The maximum number of messages per batch.</dd>

<dt><code>maxBatchTimeout?: number</code></dt>
<dd>The maximum number of seconds to wait to fill a batch with messages.</dd>

<dt><code>maxConcurrency?: number | null</code></dt>
<dd>The maximum number of concurrent consumer Worker invocations. Leaving this unset will allow your consumer to scale to the maximum concurrency needed to keep up with the message backlog.</dd>

<dt><code>maxRetries?: number</code></dt>
<dd>The maximum number of retries for each message.</dd>

<dt><code>retryDelay?: number</code></dt>
<dd>The number of seconds to wait before retrying a message.</dd>

<dt><code>visibilityTimeoutMs?: number</code></dt>
<dd>The number of milliseconds to wait for pulled messages to become visible again.</dd></dl></details>



<code>name</code>Required<a href="#orders-api-config-triggers-queue-default">Link to name</a>

<code>name: string</code>

The name of the queue from which this consumer should consume.

<code>maxBatchSize</code>Optional<a href="#orders-api-config-triggers-queue-default">Link to maxBatchSize</a>

<code>maxBatchSize?: number</code>

The maximum number of messages per batch.

</details>

<details>

<summary>triggers.scheduled({ schedule: "0 * * * *" }), (scheduled, schedule reference)</summary>



<code>scheduled</code>Builder<a href="#orders-api-config-triggers-scheduled-default">Link to scheduled</a>

<code>scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;</code>

Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>schedule: string</code></dt>
<dd>A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a></dd>

</dl></details>



<code>schedule</code>Required<a href="#orders-api-config-triggers-scheduled-default">Link to schedule</a>

<code>schedule: string</code>

A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

</details>

],

},

});

Compared with the file that `cf migrate` generates, the finished file:

- Imports the entrypoint with the `cf-worker` attribute instead of a string path, so the Worker module exports are typed.
- Declares the `Counter` class under `exports`, replacing the `migrations` history.
- Types the queue messages with `bindings.queue<Job>()`.
- Has no `TODO(@cloudflare)` comments or `throw` statement.

To see the generated file, refer to [Read the output](https://developers.cloudflare.com/cf/wrangler/migrate/#read-the-output).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/wrangler/reference/#page","headline":"Wrangler to cf reference","description":"Find cf equivalents for Wrangler commands, and map Wrangler configuration, build settings, and environments to cf.","url":"https://developers.cloudflare.com/cf/wrangler/reference/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/wrangler/reference/og.png?v=89a02a5f88f20fa3","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Run, build, and deploy Workers projects with the Cloudflare CLI, including modes, prebuilt deploys, and previews.
title: Develop, build, and deploy
image: https://developers.cloudflare.com/cf/projects/og.png?v=08ae0671b2972952
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Develop, build, and deploy

Last updated Sep 30, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/projects/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cf` develops, builds, and deploys Workers projects with the same CLI that manages the rest of your Cloudflare account. To create a project, follow [Deploy your first Worker](https://developers.cloudflare.com/cf/get-started/first-worker/).

Configure the project with [`cloudflare.config.ts`](https://developers.cloudflare.com/cf/projects/cloudflare-config/). Builds write Build Output to `.cloudflare/output/v0/`.

## How `cf` runs your project

`cf` does not run a dev server or bundler itself. For `cf dev`, `cf build`, and every other command that builds first, `cf` hands the work to one of these tools:

1. **The framework's own command.** When `cf` detects a supported framework, it runs that framework's dev or build command through your package manager. In a Vite project, including a project created with `cf init`, that is `vite` or `vite build`, for example `npx vite build` with npm.
2. **An installed Cloudflare build tool.** Otherwise, `cf` uses the Cloudflare build tool declared in the project's `package.json`. That is the Cloudflare Vite plugin, or Wrangler 4.136.0 or later when the Vite plugin is not declared.

`cf` uses the Cloudflare Vite plugin 2.0 beta (`@cloudflare/vite-plugin@beta`), which does not depend on Wrangler. Wrangler builds projects that declare it without the Vite plugin, such as projects that `cf migrate` converts with the Wrangler bundler and static sites that [automatic configuration](#automatic-configuration) sets up. These projects keep build settings, such as the static assets directory, in a generated `wrangler.config.ts` file. That file can change during the beta.

`cf` does not run your `package.json` scripts. If your `build` script runs extra steps, such as `tsc -b && vite build`, then `cf build` and `cf deploy` skip them. Chain those steps with `cf build` in your own script instead:

*package.jsonjson*

```json
{
	"scripts": {
		"build": "tsc -b && cf build"
	}
}
```

When `cf` runs a framework command, it forwards `--mode` and rejects other arguments. For example, `cf dev --port 8788` fails in a Vite project. Set the option in the framework's configuration, such as `server.port` in `vite.config.ts`, or run the framework command directly. When `cf` uses an installed build tool instead, `cf dev` forwards extra arguments to it, and the tool rejects arguments it does not support. `cf build` accepts only `--mode`.

## Automatic configuration

When a project has no `cloudflare.config.ts`, `cf` tries to detect its framework and set the project up for Cloudflare before it continues. This automatic configuration runs from these commands:

- `cf dev` and `cf build`
- `cf deploy`, including `cf deploy --dry-run`
- `cf previews deploy`
- `cf workers versions create`, `cf workers triggers deploy`, and `cf workers check`
- `cf init`

A project counts as configured only when `cloudflare.config.ts` exists in the directory where you run the command. Passing `--prebuilt` skips automatic configuration.

In a terminal, `cf` shows the planned changes and asks before it applies them. Without a terminal, or in CI, it applies the changes and installs packages without asking. Run `cf init .` locally before you set up CI. It configures an existing project without building it. Review the changes and commit them. For the list of changes, refer to [Start from an existing project](https://developers.cloudflare.com/cf/get-started/first-worker/#start-from-an-existing-project).

Wrangler projects

Automatic configuration does not read Wrangler configuration files. In a project that has `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml` but no `cloudflare.config.ts`, do not run `cf init .`, `cf dev`, `cf build`, `cf deploy`, or another command that builds.

In a framework or static-assets project, `cf` writes a new `cloudflare.config.ts` that ignores the Wrangler configuration, including its entrypoint and bindings. In a Worker project without a detected framework, the command fails with an error such as `cloudflare.config.ts is required when --experimental-new-config is enabled.` Convert the project with `cf migrate` first. Refer to [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/).

## Start development

Start the project's development server:

```sh
cf dev
```

The dev server prints its local URL.

## Build

Build the project:

```sh
cf build
```

After the build finishes, `cf` reads and validates `.cloudflare/output/v0/`. `cf build` does not upload anything and does not need credentials.

## Deploy

`cf deploy` builds the project, validates Build Output, resolves your credentials and account, uploads a new Worker Version, and deploys it:

```sh
cf deploy
```

Sign in with `cf auth login`, or set `CLOUDFLARE_API_TOKEN`, before you deploy. For details, refer to [Sign in](https://developers.cloudflare.com/cf/get-started/#sign-in).

`cf deploy` can provision missing resources for bindings that omit resource identifiers. It does not write provisioned identifiers back to `cloudflare.config.ts`.

`cf deploy` accepts these options:

| Option | Purpose |
| --- | --- |
| `--dry-run` | Builds and validates the Worker without uploading it |
| `--message <TEXT>` | Records a message on the Worker Version |
| `--tag <TAG>` | Records a tag on the Worker Version |
| `--secrets-file <PATH>` | Uploads secrets from a JSON or `.env` format file with the version |
| `--dispatch-namespace <NAMESPACE>` | Deploys a Workers for Platforms user Worker to that dispatch namespace |
| `--containers-rollout <STRATEGY>` | Sets the Container rollout strategy: `immediate`, `gradual`, or `none` |
| `--worker <NAME>` | Selects a Worker from Build Output instead of the default Worker |
| `--prebuilt` | Deploys existing Build Output without building |

`--dry-run` sends no API requests and needs no credentials, so you can validate a project before you sign in. In a project without `cloudflare.config.ts`, it still runs automatic configuration first, which can install packages and change files.

```sh
cf deploy --dry-run
cf deploy --message "Fix header parsing" --tag v1.2.0
```

## Modes

A mode selects which configuration a function-form `cloudflare.config.ts` returns. Pass it with `--mode` or `-m`:

```sh
cf dev --mode staging
cf build -m staging
cf deploy --mode staging
```

When you omit `--mode`, the Cloudflare Vite plugin uses `development` for `cf dev` and `production` for builds. Builds through Wrangler and API commands leave the mode `undefined`. For the full list, refer to [Select a mode](https://developers.cloudflare.com/cf/projects/cloudflare-config/#select-a-mode).

When `cf` runs a framework's own command, only Vite and Astro accept `--mode`. Other framework commands fail with an error. Refer to [A framework rejects `--mode`](#a-framework-rejects---mode).

This configuration deploys a separate staging Worker with its own API origin:

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig(({ mode }) =&gt; { (defineConfig, mode reference)</summary>



<code>defineConfig</code>Function<a href="#modes-config-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



<code>mode</code>Context value<a href="#modes-config-defineconfig">Link to mode</a>

<code>mode: string | undefined</code>

The mode the config is being evaluated in. Set via the <code>--mode</code> CLI flag. In Vite the mode defaults to <code>development</code> in <code>vite dev</code> and <code>production</code> in <code>vite build</code> (<a href="https://vite.dev/guide/env-and-mode.html#modes">more info</a>). In Wrangler the mode defaults to <code>undefined</code>.

</details>

const isStaging = mode === "staging";

return {

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#modes-config-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: isStaging ? "example-worker-staging" : "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#modes-config-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#modes-config-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#modes-config-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#modes-config-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>API_ORIGIN: bindings.text( (text reference)</summary>



<code>text</code>Builder<a href="#modes-config-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

isStaging

? "https://staging-api.example.com"

: "https://api.example.com",

),

},

},

};

});

Return one complete configuration for each mode. Programmatic configuration does not merge environment blocks the way Wrangler environments do. A mode deploys a separate Worker only when it returns a different `name`.

Build Output records the mode it was built with. When you deploy an existing build, pass the same mode.

## Deploy a prebuilt build

Pass `--prebuilt` to deploy an existing `.cloudflare/output/v0/` directory without building. One CI job can build, and another can deploy the restored directory. `--prebuilt` also skips automatic configuration.

The deploy command must request the mode that Build Output records:

- When Build Output records a mode, pass exactly that mode with `--mode`.
- When Build Output records no mode, do not pass `--mode`.

Vite builds always record a mode. `cf build` without `--mode` records `production`, so deploy that build with `--mode production`:

```sh
cf build
cf deploy --prebuilt --mode production
```

Deploy a staging build with the staging mode:

```sh
cf build --mode staging
cf deploy --prebuilt --mode staging
```

Builds through Wrangler record a mode only when you pass `--mode` to `cf build`. To check the recorded mode, read `buildContext.mode` in `.cloudflare/output/v0/config.json`.

The same rule applies to `--prebuilt` with `cf previews deploy`, `cf workers versions create`, `cf workers triggers deploy`, and `cf workers check`. When the modes do not match, the command stops before it uploads anything and prints the `--mode` value to use.

For a complete pipeline, refer to [Use cf in CI](https://developers.cloudflare.com/cf/ci/).

## Upload a version

Upload a Worker Version without deploying it:

```sh
cf workers versions create
```

This command builds and validates the project the same way as `cf deploy`. It accepts `--prebuilt`, `--mode`, `--message`, `--tag`, `--secrets-file`, `--dry-run`, and `--worker`. Use `--preview-alias <ALIAS>` to give the version a [preview URL](https://developers.cloudflare.com/workers/versions-and-deployments/preview-urls/) alias.

To send traffic to an uploaded version, create a deployment:

```sh
cf workers deployments create --worker example-worker --strategy percentage --versions '[{"version_id":"<VERSION_ID>","percentage":100}]'
```

## Deploy triggers

Apply trigger configuration from Build Output without uploading a new version:

```sh
cf workers triggers deploy
```

This command applies routes, custom domains, the `workers.dev` setting, cron schedules, Queue consumers, and Workflows. It builds the project unless you pass `--prebuilt`. It also accepts `--mode`, `--worker`, and `--dry-run`. A dry run sends no API requests.

## Deploy a preview

Deploy the project as a Worker Preview:

```sh
cf previews deploy
```

The command builds the project with `isPreview` set to `true`, so a function-form `cloudflare.config.ts` can return preview-specific settings. It then uploads the preview and prints the result as JSON. Previews in `cf` can change during the beta.

The preview name defaults to the current branch. `cf` reads the branch from Workers Builds, GitHub Actions, or GitLab CI/CD, and then from Git. On a detached `HEAD` with no CI branch, pass a name:

```sh
cf previews deploy my-feature
```

The command accepts `--mode`, `--worker`, and `--prebuilt`. With `--prebuilt`, Build Output must come from a preview build, and the [mode rule](#deploy-a-prebuilt-build) applies. There is no `--dry-run`, and the command needs credentials.

The JSON result contains `type`, `version`, `preview_id`, `preview_name`, `preview_slug`, `preview_urls`, `deployment_id`, and `deployment_urls`.

Previews do not support Durable Object-managed Containers. `cf deploy`, `cf workers versions create`, and `cf workers triggers deploy` refuse preview Build Output and print the `cf previews deploy` command to use instead.

## Profile Worker startup

Profile the Worker's startup performance locally:

```sh
cf workers check
```

The command builds the project unless you pass `--prebuilt`. It prints the bundle size and startup timings as JSON, and writes a CPU profile to `worker-startup.cpuprofile`. Use `--outfile <PATH>` to choose a different file. The command also accepts `--mode` and `--worker`.

The measurement runs on your machine. Use it to find where startup time goes, not to predict startup time on Cloudflare.

## Generate types

Generate TypeScript types from `cloudflare.config.ts`:

```sh
cf workers types
```

The command writes `.cloudflare/types/index.d.ts`, which contains the `Env` binding types and the Workers runtime types. Pass `--no-include-runtime` to leave out the runtime types, or `--mode` to evaluate the configuration for a named mode.

The Cloudflare Vite plugin writes the same file during development and builds. Run `cf workers types` in projects that build through Wrangler, or before `tsc` in a type-check script. Projects created with `cf init` include a `typecheck` script that runs `cf workers types && tsc`.

## Local resource data

Add `--local` to a supported command to run it against a local simulation instead of the Cloudflare API:

```sh
cf d1 raw <DATABASE_ID> --sql "SELECT 1" --local
cf r2 objects list --bucket-name <BUCKET_NAME> --local
```

`--local` works only for a few resources that local development provides. `cf` starts a short-lived local runtime for each command, so no dev server needs to be running. Local support covers these commands:

- `cf kv keys get`, `cf kv keys list`, `cf kv keys put`, and `cf kv keys delete`
- `cf kv bulk get`, `cf kv bulk put`, and `cf kv bulk delete`
- `cf d1 raw`
- `cf d1 migrations list` and `cf d1 migrations apply`
- `cf r2 objects get`, `cf r2 objects put`, `cf r2 objects list`, and `cf r2 objects bulk-delete`
- `cf d1 list`, `cf kv namespaces list`, and `cf r2 buckets list`

`cf d1 query` has no local equivalent. Use `cf d1 raw` instead. A command without a local equivalent fails with `This command has no local equivalent.` instead of calling the Cloudflare API.

By default, `--local` keeps its data in a `state/v3` directory inside the `cf` configuration directory. That is `~/.config/cloudflare/state/v3` on Linux and `~/Library/Preferences/cloudflare/state/v3` on macOS. Every project on your machine shares this directory. Pass `--persist-to <DIRECTORY>` to use `<DIRECTORY>/v3` instead. `--persist-to` works only with `--local`.

This is not the data your dev server uses. The Cloudflare Vite plugin 2.0 beta keeps development data in the project, under `.cloudflare/state/`.

## Which configuration each command reads

Project commands, such as `cf dev`, `cf build`, and `cf deploy`, run a build tool that loads the whole `cloudflare.config.ts`, including the Worker and Containers.

Ordinary API commands, such as `cf d1 list`, read only `accountId` and `complianceRegion` from the nearest `cloudflare.config.ts` in the current directory or a parent directory. A syntax error, import error, or top-level runtime error in that file still stops them. For details, refer to [Set account defaults](https://developers.cloudflare.com/cf/projects/cloudflare-config/#set-account-defaults).

API credentials, such as `CLOUDFLARE_API_TOKEN`, can also come from a `.env` file in the current directory. Commands that build first, such as `cf deploy`, load those values after the build finishes. For details, refer to [Load credentials from a .env file](https://developers.cloudflare.com/cf/get-started/#load-credentials-from-a-env-file).

## Troubleshooting

### No dev server is installed

```txt
No Cloudflare dev-server is installed in this project.
```

`cf` found no framework that it recognizes and no Cloudflare build tool declared in `package.json`, for example in an empty directory. To create a project, run `cf init`.

### Dependencies are not installed

In a configured project whose dependencies are not installed, Vite reports that it cannot resolve `@cloudflare/vite-plugin`, or `cf` reports that a build tool is declared but not installed. Install dependencies with your package manager, then run the command again.

### Arguments are rejected

```txt
Arguments cannot currently be forwarded to the detected dev command `npx vite`. Run that command directly with the required arguments.
```

`cf` runs the framework's command and forwards only `--mode`. Set the option in the framework's configuration, or run the framework command directly.

### A framework rejects `--mode`

```txt
The detected command `<COMMAND>` does not currently support `--mode`.
```

Only Vite and Astro accept `--mode` when `cf` runs a framework command. Run the command without `--mode`.

### A prebuilt deploy rejects the mode

```txt
The Build Output was created with mode "production", but this command did not specify a mode. Rerun with "--mode production".
```

```txt
The Build Output does not record which mode it was created with, but this command requested mode "staging". Rebuild with "--mode staging" before deploying.
```

Pass exactly the mode that Build Output records, or omit `--mode` when it records none. Refer to [Deploy a prebuilt build](#deploy-a-prebuilt-build).

### Build Output is missing

```txt
Build Output Specification: no root config found at <PATH>/.cloudflare/output/v0/config.json.
```

A `--prebuilt` command found no build. Run `cf build` first, or restore the complete `.cloudflare/output/v0/` directory from your build job.

### Preview output reaches a production deploy

```txt
This build output is for a Preview. Run cf previews deploy --prebuilt --mode production instead.
```

The existing Build Output came from `cf previews deploy`. Run the suggested command to deploy the preview, or run `cf build` to create production output.

### The preview name cannot be determined

```txt
We couldn't determine a Preview name from CI or Git.
```

`cf previews deploy` found no branch name, for example on a detached `HEAD`. Pass a name: `cf previews deploy <PREVIEW_NAME>`.

### A local command has no local equivalent

```txt
This command has no local equivalent. Re-run without --local to use the Cloudflare API.
```

The command does not support `--local`. For D1 queries, use `cf d1 raw` instead of `cf d1 query`. Otherwise, run the command without `--local`.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/projects/#page","headline":"Develop, build, and deploy","description":"Run, build, and deploy Workers projects with the Cloudflare CLI, including modes, prebuilt deploys, and previews.","url":"https://developers.cloudflare.com/cf/projects/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/projects/og.png?v=08ae0671b2972952","dateModified":"2026-09-30","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Configure Workers projects with a typed cloudflare.config.ts file.
title: Programmatic configuration
image: https://developers.cloudflare.com/cf/projects/cloudflare-config/og.png?v=b3958a991af163a7
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Programmatic configuration

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/projects/cloudflare-config/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cloudflare.config.ts` is the typed configuration file for a Workers project. Its default export can define a Worker, Container applications, and account settings. Because the file is a TypeScript module, it can use imports, functions, environment variables, and asynchronous values.

Open beta

Programmatic configuration with `cloudflare.config.ts` is in open beta. The configuration format can change before the stable release.

Loading `cloudflare.config.ts` requires Node.js 22.18 or later. Bun is not supported: when `cf` runs on Bun, loading the file fails with `cloudflare.config.ts loading is not supported on Bun`. Most `cf` commands load the nearest `cloudflare.config.ts`, including commands that only call the Cloudflare API, so this is the practical minimum for any `cf` command you run inside the project.

Set `"type": "module"` in the project's `package.json`. Without it, Node.js prints a warning each time it loads the file. With `"type": "commonjs"`, loading fails with `Cannot use import statement outside a module`.

## Create the minimum configuration

Import the configuration helpers from `cf/config`. Add `cf` as a development dependency so the project can resolve that import. Projects created with [`cf init`](https://developers.cloudflare.com/cf/get-started/first-worker/) already include it.

npmyarnpnpmbun

```
npm i -D cf
```

```
yarn add -D cf
```

```
pnpm add -D cf
```

```
bun add -d cf
```

A Worker requires `name` and `compatibilityDate`. A Worker that runs code also requires `entrypoint`.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-minimum-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-minimum-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-minimum-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-minimum-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-minimum-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

},

});

The `cf-worker` import attribute lets TypeScript infer the Worker module, binding types, and exported classes.

An assets-only Worker can omit `entrypoint`. Its build implementation must provide the asset source. A deployable build must contain a Worker bundle, static assets, or both.

`cloudflare.config.ts` does not have an `assets.directory` field. In Vite projects, the static assets are the output of Vite's client build, which includes Vite's `publicDir` directory (`public` by default). Projects that build with Wrangler set the directory in a generated `wrangler.config.ts` file. For details, refer to [How cf runs your project](https://developers.cloudflare.com/cf/projects/#how-cf-runs-your-project).

## Understand the default export

Use `defineConfig()` for the default export. The helper returns the value you pass to it and preserves literal values for TypeScript inference.

| Field | Required | Purpose |
| --- | --- | --- |
| `accountId` | No | Sets the default account for `cf` commands |
| `complianceRegion` | No | Selects `public` or `fedramp-high` |
| `worker` | Development and builds | Defines the Worker |
| `containers` | No | Defines Container applications |

`cf` API commands can read an account-only default export. The Cloudflare Vite plugin and Wrangler require `worker` for development and builds.

Use the [configuration explorer](https://developers.cloudflare.com/cf/projects/config-explorer/) to inspect the generated fields, builder methods, and nested options.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig, triggers } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig(({ mode }) =&gt; { (defineConfig, mode reference)</summary>



<code>defineConfig</code>Function<a href="#config-default-export-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



<code>mode</code>Context value<a href="#config-default-export-defineconfig">Link to mode</a>

<code>mode: string | undefined</code>

The mode the config is being evaluated in. Set via the <code>--mode</code> CLI flag. In Vite the mode defaults to <code>development</code> in <code>vite dev</code> and <code>production</code> in <code>vite build</code> (<a href="https://vite.dev/guide/env-and-mode.html#modes">more info</a>). In Wrangler the mode defaults to <code>undefined</code>.

</details>

const isStaging = mode === "staging";

return {

<details>

<summary>accountId: "&lt;ACCOUNT_ID&gt;", (accountId reference)</summary>



<code>accountId</code>Optional<a href="#config-default-export-settings-accountid">Link to accountId</a>

<code>accountId?: string</code>

This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.

</details>

<details>

<summary>complianceRegion: "public", (complianceRegion reference)</summary>



<code>complianceRegion</code>Optional<a href="#config-default-export-settings-complianceregion">Link to complianceRegion</a>

<code>complianceRegion?: "public" | "fedramp-high"</code>

The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.

</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-default-export-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: isStaging ? "example-staging" : "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-default-export-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-default-export-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-default-export-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-default-export-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>MESSAGE: bindings.text(isStaging ? "staging" : "production"), (text reference)</summary>



<code>text</code>Builder<a href="#config-default-export-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

},

<details>

<summary>triggers: [triggers.scheduled({ schedule: "0 * * * *" })], (triggers, scheduled, schedule reference)</summary>



<code>triggers</code>Optional<a href="#config-default-export-workerconfig-triggers">Link to triggers</a>

<code>triggers?: Trigger[]</code>

Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a>

<code>scheduled</code>Builder<a href="#config-default-export-workerconfig-triggers">Link to scheduled</a>

<code>scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;</code>

Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>schedule: string</code></dt>
<dd>A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a></dd>

</dl></details>



<code>schedule</code>Required<a href="#config-default-export-workerconfig-triggers">Link to schedule</a>

<code>schedule: string</code>

A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

</details>

},

};

});

## Evaluate configuration

`defineConfig()`, `defineWorker()`, and `defineContainer()` each accept an object, a promise, or a function. A function can return an object or a promise.

Functions receive this context:

| Property | Purpose |
| --- | --- |
| `mode` | Identifies the selected mode, which [depends on the command](#select-a-mode) when you omit `--mode` |
| `isPreview` | Is `true` when the configuration is evaluated for a [Worker Preview](https://developers.cloudflare.com/cf/projects/#deploy-a-preview) |

Return one complete configuration for each mode. Programmatic configuration does not merge environment blocks.

## Reuse definitions

Use `defineWorker()` when another configuration file needs to import a Worker definition. Use `defineContainer()` when a Durable Object export and the `containers` array need to reference the same Container.

These helpers do not replace the default export. The default export must still use `defineConfig()`.

## Configure the Worker

The `worker` object supports these fields:

| Field | Required | Purpose |
| --- | --- | --- |
| `name` | Yes | Sets the Worker name |
| `compatibilityDate` | Yes | Selects a Workers runtime compatibility date |
| `entrypoint` | Conditional | Selects the Worker module |
| `assets` | No | Sets runtime request behavior for built assets |
| `cache` | No | Configures Worker cache behavior |
| `compatibilityFlags` | No | Turns on runtime compatibility flags |
| `domains` | No | Publishes the Worker to custom domains |
| `env` | No | Declares bindings and inline values |
| `exports` | No | Configures named Worker, Durable Object, and Workflow exports |
| `limits` | No | Sets CPU and subrequest limits |
| `logpush` | No | Sends trace events to Workers Logpush |
| `observability` | No | Configures logs, traces, and sampling |
| `placement` | No | Configures smart or targeted placement |
| `previewUrls` | No | Controls [version preview URLs](https://developers.cloudflare.com/workers/versions-and-deployments/preview-urls/) |
| `tailConsumers` | No | Sends events to Tail Workers |
| `triggers` | No | Declares routes, queues, schedules, and sockets |
| `unsafe` | No | Passes unsupported metadata through to deployment |
| `workersDev` | No | Controls the `workers.dev` route |

The `assets` object controls runtime behavior only. It configures HTML handling, not-found handling, and whether matching requests run the Worker first. It does not select the asset source.

Use `domains` for custom domains. Use `triggers.fetch()` for routes.

## Use typed builder values

The `bindings`, `triggers`, and `exports` builders return ordinary configuration objects. Each object has a literal `type` field that identifies its kind.

The `type` field lets TypeScript select the valid options for each kind. For example, a queue trigger accepts batching options, while a scheduled trigger requires a cron expression. The configuration loader uses the same fields for runtime validation.

Use builders instead of writing `type` fields directly. Builders preserve literal values and generic type arguments for Worker type inference.

## Declare bindings

Each key under `worker.env` becomes a binding name in Worker code. The builder method selects the binding's runtime type.

This configuration declares inline values, a D1 database, a Queue, and a secret:

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

type Job = {

id: string;

operation: "index" | "delete";

};

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-bindings-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-bindings-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-bindings-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-bindings-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-bindings-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-bindings-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>API_ORIGIN: bindings.text("https://api.example.com"), (text reference)</summary>



<code>text</code>Builder<a href="#config-bindings-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

<details>

<summary>FEATURES: bindings.json({ search: true }), (json reference)</summary>



<code>json</code>Builder<a href="#config-bindings-bindings-json-default">Link to json</a>

<code>json&lt;T$1 extends Json&gt;(value: T$1): JsonBinding&lt;T$1&gt;;</code>

Inline JSON value made available to the Worker on <code>env</code> under the binding name.

</details>

<details>

<summary>DATABASE: bindings.d1({ name: "application-db" }), (d1, name reference)</summary>



<code>d1</code>Builder<a href="#config-bindings-bindings-d1-default">Link to d1</a>

<code>d1(options?: D1BindingOptions): D1Binding;</code>

Binding to a D1 database. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases">https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The UUID of this D1 database (not required).</dd>

<dt><code>name?: string</code></dt>
<dd>The name of this D1 database.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



<code>name</code>Optional<a href="#config-bindings-bindings-d1-default">Link to name</a>

<code>name?: string</code>

The name of this D1 database.

</details>

<details>

<summary>JOBS: bindings.queue&lt;Job&gt;({ name: "application-jobs" }), (queue, name reference)</summary>



<code>queue</code>Builder<a href="#config-bindings-bindings-queue-default">Link to queue</a>

<code>queue&lt;TBody = unknown&gt;(options?: QueueBindingOptions): TypedQueueBinding&lt;TBody&gt;;</code>

Producer binding to a Cloudflare Queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this Queue.</dd>

<dt><code>deliveryDelay?: number</code></dt>
<dd>The number of seconds to wait before delivering a message.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



<code>name</code>Optional<a href="#config-bindings-bindings-queue-default">Link to name</a>

<code>name?: string</code>

The name of this Queue.

</details>

<details>

<summary>API_KEY: bindings.secret(), (secret reference)</summary>



<code>secret</code>Builder<a href="#config-bindings-bindings-secret-default">Link to secret</a>

<code>secret(): SecretBinding;</code>

Declares a secret that is required by your Worker, exposed on <code>env</code> under the binding name. When defined, this binding: - Replaces .dev.vars/.env/process.env inference for type generation - Enables local dev validation with warnings for missing secrets For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#secrets-configuration-property">https://developers.cloudflare.com/workers/wrangler/configuration/#secrets-configuration-property</a>

</details>

},

},

});

The generated `Env` type contains these runtime types:

| Binding | Inferred runtime type |
| --- | --- |
| `API_ORIGIN` | `"https://api.example.com"` |
| `FEATURES` | `{ search: true }` |
| `DATABASE` | `D1Database` |
| `JOBS` | `Queue<Job>` |
| `API_KEY` | `string` |

Your Worker receives the inferred type through `env`:

*src/index.jsjs*

```js
export default {
	async fetch(_request, env) {
		await env.JOBS.send({
			id: "example-job",
			operation: "index",
		});

		const result = await env.DATABASE.prepare("SELECT 1").first();
		return Response.json({
			origin: env.API_ORIGIN,
			search: env.FEATURES.search,
			result,
		});
	},
};
```

*src/index.tsts*

```ts
export default {
	async fetch(_request, env) {
		await env.JOBS.send({
			id: "example-job",
			operation: "index",
		});

		const result = await env.DATABASE.prepare("SELECT 1").first();
		return Response.json({
			origin: env.API_ORIGIN,
			search: env.FEATURES.search,
			result,
		});
	},
} satisfies ExportedHandler<Env>;
```

The Cloudflare Vite plugin writes `.cloudflare/types/index.d.ts` during development and builds. Outside the Vite workflow, `cf workers types` writes the same file.

TypeScript wildcard patterns skip dot-prefixed directories, so include the generated directory explicitly. The `.ts` extensions in the examples on this page also need `allowImportingTsExtensions`:

*tsconfig.jsonjson*

```json
{
	"compilerOptions": {
		"allowImportingTsExtensions": true,
		"noEmit": true
	},
	"include": ["src", "cloudflare.config.ts", ".cloudflare/types"]
}
```

The builder API includes these methods:

| Area | Builder methods |
| --- | --- |
| Inline values | `text`, `json`, `secret` |
| Storage and data | `d1`, `kv`, `r2`, `hyperdrive`, `analyticsEngineDataset`, `artifacts`, `pipeline` |
| AI and media | `ai`, `aiSearch`, `aiSearchNamespace`, `agentMemory`, `browser`, `images`, `media`, `stream`, `vectorize` |
| Messaging | `queue`, `sendEmail` |
| Worker composition | `assets`, `dispatchNamespace`, `durableObject`, `worker`, `workerLoader`, `workflow` |
| Network and security | `mtlsCertificate`, `rateLimit`, `secretsStoreSecret`, `vpcNetwork`, `vpcService` |
| Platform metadata | `flagship`, `logfwdr`, `versionMetadata` |

Required options differ by binding. TypeScript completion shows the options for each builder.

### Type cross-Worker bindings

`bindings.worker()`, `bindings.durableObject()`, and `bindings.workflow()` accept a Worker name or a Worker definition. Import a Worker definition to validate its export names at compile time.

For example, an API Worker can export its definition:

Select a highlighted line to show its type and description below it.

api/cloudflare.config.ts

Expand allCopy

import { defineConfig, defineWorker, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export const apiWorker = defineWorker({ (defineWorker reference)</summary>



<code>defineWorker</code>Function<a href="#config-cross-worker-api-defineworker">Link to defineWorker</a>

<code>defineWorker&lt;T extends ConfigInput&lt;WorkerConfig&gt;&gt;(config: T): T;</code>

Defines a Worker configuration that you can pass to <code>worker</code> in <code>defineConfig()</code>. Pass a Worker configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (18)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of your Worker.</dd>

<dt><code>compatibilityDate: string</code></dt>
<dd>A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a></dd>

<dt><code>compatibilityFlags?: string[]</code></dt>
<dd>A list of flags that enable features from upcoming features of the Workers runtime, usually used together with <code>compatibilityDate</code>. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-flags/">https://developers.cloudflare.com/workers/configuration/compatibility-flags/</a></dd>

<dt><code>entrypoint?: string | WorkerModule</code></dt>
<dd>The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.</dd>

<dt><code>assets?: { /** How to handle HTML requests. */ htmlHandling?: "auto-trailing-slash" | "drop-trailing-slash" | "force-trailing-slash" | "none"; /** How to handle requests that do not match an asset. */ notFoundHandling?: "single-page-application" | "404-page" | "none"; /** * Matches will be routed to the User Worker, and matches to negative rules will go to the Asset Worker. * * Can also be `true`, indicating that every request should be routed to the User Worker. */ runWorkerFirst?: string[] | boolean; }</code></dt>
<dd>Specify the directory of static assets to deploy/serve. More details at <a href="https://developers.cloudflare.com/workers/frameworks/">https://developers.cloudflare.com/workers/frameworks/</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#assets">https://developers.cloudflare.com/workers/wrangler/configuration/#assets</a></dd>

<dt><code>domains?: string[]</code></dt>
<dd>Custom domains that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a></dd>

<dt><code>triggers?: Trigger[]</code></dt>
<dd>Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a></dd>

<dt><code>tailConsumers?: Array&lt;{ /** The name of the service tail events will be forwarded to. */ worker: string; /** Whether to stream tail events in real time. */ streaming?: boolean; }&gt;</code></dt>
<dd>A list of Tail Workers that are bound to this Worker. <code>@cloudflare/config</code> unifies regular and streaming tail consumers under a single field; pass <code>streaming: true</code> to forward streaming tail events.</dd>

<dt><code>cache?: { /** If cache is enabled for this Worker. */ enabled: boolean; /** Whether cached assets may be reused across Worker versions. */ crossVersionCache?: boolean; }</code></dt>
<dd>Specify the cache behavior of the Worker.</dd>

<dt><code>placement?: { mode: "off" | "smart"; hint?: string; } | { mode?: "targeted"; region: string; } | { mode?: "targeted"; host: string; } | { mode?: "targeted"; hostname: string; }</code></dt>
<dd>Specify how the Worker should be located to minimize round-trip time. More details: <a href="https://developers.cloudflare.com/workers/platform/smart-placement/">https://developers.cloudflare.com/workers/platform/smart-placement/</a></dd>

<dt><code>limits?: { /** Maximum allowed CPU time for a Worker's invocation in milliseconds. */ cpuMs?: number; /** Maximum allowed number of fetch requests that a Worker's invocation can execute. */ subrequests?: number; }</code></dt>
<dd>Specify limits for runtime behavior. Only supported for the "standard" Usage Model. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#limits">https://developers.cloudflare.com/workers/wrangler/configuration/#limits</a></dd>

<dt><code>logpush?: boolean</code></dt>
<dd>Send Trace Events from this Worker to Workers Logpush. This will not configure a corresponding Logpush job automatically. For more information about Workers Logpush, see: <a href="https://blog.cloudflare.com/logpush-for-workers/">https://blog.cloudflare.com/logpush-for-workers/</a></dd>

<dt><code>observability?: { /** If observability is enabled for this Worker. */ enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** * Whether query strings are removed from request URLs in logs and traces. * * @default false */ redactQueryString?: boolean; /** Real-time Issues settings for this Worker. */ issues?: { /** Whether real-time Issues are enabled. */ enabled?: boolean; }; logs?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** Set to false to disable invocation logs. */ invocationLogs?: boolean; /** * If logs should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations logs emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }; traces?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** * If traces should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations traces emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }; }</code></dt>
<dd>Specify the observability behavior of the Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#observability">https://developers.cloudflare.com/workers/wrangler/configuration/#observability</a></dd>

<dt><code>workersDev?: boolean</code></dt>
<dd>Whether we use <code>&lt;name&gt;.&lt;subdomain&gt;.workers.dev</code> to test and deploy your Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#workersdev">https://developers.cloudflare.com/workers/wrangler/configuration/#workersdev</a></dd>

<dt><code>previewUrls?: boolean</code></dt>
<dd>Whether we use <code>&lt;version&gt;-&lt;name&gt;.&lt;subdomain&gt;.workers.dev</code> to serve Preview URLs for your Worker.</dd>

<dt><code>unsafe?: { /** * Arbitrary key/value pairs that will be included in the uploaded metadata. Values specified * here will always be applied to metadata last, so can add new or override existing fields. */ metadata?: Record&lt;string, unknown&gt;; /** * Used for internal capnp uploads for the Workers runtime. */ capnp?: { basePath: string; sourceSchemas: string[]; compiledSchema?: never; } | { basePath?: never; sourceSchemas?: never; compiledSchema: string; }; }</code></dt>
<dd>"Unsafe" tables for runtime features that aren't directly supported by this configuration. Values are forwarded verbatim in the Worker's upload metadata.</dd>

<dt><code>env?: Record&lt;string, Binding&gt;</code></dt>
<dd>Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.</dd>

<dt><code>exports?: Record&lt;string, Export&gt;</code></dt>
<dd>Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.</dd>

</dl></details>



</details>

<details>

<summary>name: "api-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-cross-worker-api-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-cross-worker-api-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-cross-worker-api-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-cross-worker-api-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Admin: exports.worker(), (worker reference)</summary>



<code>worker</code>Builder<a href="#config-cross-worker-api-exports-worker-default">Link to worker</a>

<code>worker(options?: WorkerEntrypointExportOptions): WorkerEntrypointExport;</code>

Declares a WorkerEntrypoint export defined by this Worker.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code></dt>
<dd></dd>

</dl></details>



</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#config-cross-worker-api-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#config-cross-worker-api-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

},

});

<details>

<summary>export default defineConfig({ worker: apiWorker }); (defineConfig, worker reference)</summary>



<code>defineConfig</code>Function<a href="#config-cross-worker-api-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



<code>worker</code>Optional<a href="#config-cross-worker-api-defineconfig">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

A second Worker can import that definition:

Select a highlighted line to show its type and description below it.

web/cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig } from "cf/config";

import { apiWorker } from "../api/cloudflare.config.ts";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-cross-worker-web-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-cross-worker-web-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "web-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-cross-worker-web-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-cross-worker-web-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-cross-worker-web-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-cross-worker-web-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>API: bindings.worker({ (worker reference)</summary>



<code>worker</code>Builder<a href="#config-cross-worker-web-bindings-worker-default">Link to worker</a>

<code>worker&lt;TWorker$1 extends WorkerReference, TExportName$1 extends WorkerEntrypointExportName&lt;TWorker$1&gt; | undefined = undefined&gt;(options: WorkerBindingOptions&lt;TWorker$1, TExportName$1&gt;): WorkerBinding&lt;TWorker$1, NoInfer&lt;TExportName$1&gt;&gt;;</code>

Service binding (Worker-to-Worker). <code>worker</code> is the name or config of the bound Worker; <code>exportName</code> selects a named <code>WorkerEntrypoint</code> export (defaults to the default export). For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings">https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the bound Worker.</dd>

<dt><code>exportName?: TExportName$1</code></dt>
<dd>The named export to bind to (defaults to the default export).</dd>

<dt><code>props?: Record&lt;string, unknown&gt;</code></dt>
<dd>Optional properties that will be made available to the service via <code>ctx.props</code>.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>worker: apiWorker, (worker reference)</summary>



<code>worker</code>Required<a href="#config-cross-worker-web-bindings-worker-default-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the bound Worker.

</details>

<details>

<summary>exportName: "Admin", (exportName reference)</summary>



<code>exportName</code>Optional<a href="#config-cross-worker-web-bindings-worker-default-exportname">Link to exportName</a>

<code>exportName?: TExportName$1</code>

The named export to bind to (defaults to the default export).

</details>

}),

<details>

<summary>COUNTERS: bindings.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-cross-worker-web-bindings-durableobject-all">Link to durableObject</a>

<code>durableObject&lt;TWorker$1 extends WorkerReference, TExportName$1 extends DurableObjectExportName&lt;TWorker$1&gt;&gt;(options: DurableObjectBindingOptions&lt;TWorker$1, TExportName$1&gt;): DurableObjectBinding&lt;TWorker$1, TExportName$1&gt;;</code>

Binding to a Durable Object class. <code>worker</code> is the name or config of the Worker that defines the class; <code>exportName</code> is the exported class name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the Worker that defines the Durable Object class.</dd>

<dt><code>exportName: TExportName$1</code></dt>
<dd>The exported class name of the Durable Object.</dd></dl></details>



</details>

<details>

<summary>worker: apiWorker, (worker reference)</summary>



<code>worker</code>Required<a href="#config-cross-worker-web-bindings-durableobject-all-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the Worker that defines the Durable Object class.

</details>

<details>

<summary>exportName: "Counter", (exportName reference)</summary>



<code>exportName</code>Required<a href="#config-cross-worker-web-bindings-durableobject-all-exportname">Link to exportName</a>

<code>exportName: TExportName$1</code>

The exported class name of the Durable Object.

</details>

}),

},

},

});

Import the other configuration file with its `.ts` extension. Node.js loads `cloudflare.config.ts` with its own module resolution, which does not add extensions. An import without the extension fails with a `Cannot find module` error (`ERR_MODULE_NOT_FOUND`). Because API commands also load the nearest configuration file, the error breaks ordinary API commands in that directory too.

TypeScript rejects unknown export names. It also infers the `API` Remote Procedure Call (RPC) methods and the Durable Object stub type from the imported entrypoint.

Use a Worker name when the target definition cannot be imported. TypeScript can validate the binding shape, but it cannot validate the remote export name.

## Declare triggers

Each `triggers` method returns a typed event declaration. Add these values to the `worker.triggers` array.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig, triggers } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-triggers-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-triggers-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-triggers-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-triggers-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-triggers-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>triggers: [ (triggers reference)</summary>



<code>triggers</code>Optional<a href="#config-triggers-workerconfig-triggers">Link to triggers</a>

<code>triggers?: Trigger[]</code>

Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a>

</details>

<details>

<summary>triggers.fetch({ (fetch reference)</summary>



<code>fetch</code>Builder<a href="#config-triggers-triggers-fetch-default">Link to fetch</a>

<code>fetch(options: FetchTriggerOptions): FetchTrigger;</code>

Fetch trigger — a route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>pattern: string</code></dt>
<dd>A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a></dd>

<dt><code>zone?: string</code></dt>
<dd>The DNS zone the pattern is attached to. Required when the pattern is ambiguous.</dd></dl></details>



</details>

<details>

<summary>pattern: "api.example.com/*", (pattern reference)</summary>



<code>pattern</code>Required<a href="#config-triggers-triggers-fetch-default-pattern">Link to pattern</a>

<code>pattern: string</code>

A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

</details>

<details>

<summary>zone: "example.com", (zone reference)</summary>



<code>zone</code>Optional<a href="#config-triggers-triggers-fetch-default-zone">Link to zone</a>

<code>zone?: string</code>

The DNS zone the pattern is attached to. Required when the pattern is ambiguous.

</details>

}),

<details>

<summary>triggers.queue({ (queue reference)</summary>



<code>queue</code>Builder<a href="#config-triggers-triggers-queue-default">Link to queue</a>

<code>queue(options: QueueConsumerTriggerOptions): QueueConsumerTrigger;</code>

Queue consumer trigger — invokes this Worker when messages arrive on the named queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (8)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the queue from which this consumer should consume.</dd>

<dt><code>deadLetterQueue?: string</code></dt>
<dd>The queue to send messages that failed to be consumed.</dd>

<dt><code>maxBatchSize?: number</code></dt>
<dd>The maximum number of messages per batch.</dd>

<dt><code>maxBatchTimeout?: number</code></dt>
<dd>The maximum number of seconds to wait to fill a batch with messages.</dd>

<dt><code>maxConcurrency?: number | null</code></dt>
<dd>The maximum number of concurrent consumer Worker invocations. Leaving this unset will allow your consumer to scale to the maximum concurrency needed to keep up with the message backlog.</dd>

<dt><code>maxRetries?: number</code></dt>
<dd>The maximum number of retries for each message.</dd>

<dt><code>retryDelay?: number</code></dt>
<dd>The number of seconds to wait before retrying a message.</dd>

<dt><code>visibilityTimeoutMs?: number</code></dt>
<dd>The number of milliseconds to wait for pulled messages to become visible again.</dd></dl></details>



</details>

<details>

<summary>name: "application-jobs", (name reference)</summary>



<code>name</code>Required<a href="#config-triggers-triggers-queue-default-name">Link to name</a>

<code>name: string</code>

The name of the queue from which this consumer should consume.

</details>

<details>

<summary>maxBatchSize: 10, (maxBatchSize reference)</summary>



<code>maxBatchSize</code>Optional<a href="#config-triggers-triggers-queue-default-maxbatchsize">Link to maxBatchSize</a>

<code>maxBatchSize?: number</code>

The maximum number of messages per batch.

</details>

<details>

<summary>maxRetries: 3, (maxRetries reference)</summary>



<code>maxRetries</code>Optional<a href="#config-triggers-triggers-queue-default-maxretries">Link to maxRetries</a>

<code>maxRetries?: number</code>

The maximum number of retries for each message.

</details>

}),

<details>

<summary>triggers.scheduled({ schedule: "0 * * * *" }), (scheduled, schedule reference)</summary>



<code>scheduled</code>Builder<a href="#config-triggers-triggers-scheduled-default">Link to scheduled</a>

<code>scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;</code>

Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>schedule: string</code></dt>
<dd>A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a></dd>

</dl></details>



<code>schedule</code>Required<a href="#config-triggers-triggers-scheduled-default">Link to schedule</a>

<code>schedule: string</code>

A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

</details>

<details>

<summary>triggers.email({ addresses: ["support@example.com"] }), (email, addresses reference)</summary>



<code>email</code>Builder<a href="#config-triggers-triggers-email-default">Link to email</a>

<code>email(options: EmailTriggerOptions): EmailTrigger;</code>

Email trigger — invokes this Worker for the configured Email Routing addresses.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>addresses: string[]</code></dt>
<dd>Inbound Email Routing addresses handled by this Worker. Each entry is a literal recipient address (e.g. <code>"support@example.com"</code>) or a <code>*@domain</code> catch-all (e.g. <code>"*@example.com"</code>).</dd>

</dl></details>



<code>addresses</code>Required<a href="#config-triggers-triggers-email-default">Link to addresses</a>

<code>addresses: string[]</code>

Inbound Email Routing addresses handled by this Worker. Each entry is a literal recipient address (e.g. <code>"support@example.com"</code>) or a <code>*@domain</code> catch-all (e.g. <code>"*@example.com"</code>).

</details>

<details>

<summary>triggers.connect({ protocol: "tcp", port: 5432 }), (connect, protocol, port reference)</summary>



<code>connect</code>Builder<a href="#config-triggers-triggers-connect-default">Link to connect</a>

<code>connect(options: ConnectTriggerOptions): ConnectTrigger;</code>

Connect trigger — invokes this Worker's <code>connect(socket, env, ctx)</code> handler for raw socket connections received on the configured protocol/port.

<details>

<summary>Options (6)</summary>



<dl>

<dt><code>port: number</code></dt>
<dd>The port to listen on.</dd>

<dt><code>address?: string</code></dt>
<dd>The address to bind to. Defaults to <code>127.0.0.1</code>.</dd>

<dt><code>protocol: "tcp"</code></dt>
<dd></dd>

<dt><code>protocol: "udp"</code></dt>
<dd></dd>

<dt><code>idleTimeoutMs?: number</code></dt>
<dd>The idle timeout in milliseconds after which a peer flow is closed.</dd>

<dt><code>maxPendingBytes?: number</code></dt>
<dd>The maximum number of pending datagram bytes per peer flow.</dd></dl></details>



<code>protocol</code>Required<a href="#config-triggers-triggers-connect-default">Link to protocol</a>

<code>protocol: "tcp" | "udp"</code>

The type definition does not include a description.

<code>port</code>Required<a href="#config-triggers-triggers-connect-default">Link to port</a>

<code>port: number</code>

The port to listen on.

</details>

],

},

});

The builder provides these trigger methods:

| Method | Event |
| --- | --- |
| `fetch` | A route receives HTTP traffic |
| `queue` | A queue delivers messages |
| `scheduled` | A cron schedule runs |
| `email` | Email Routing receives matching email |
| `connect` | TCP or UDP traffic reaches the configured port |

Set `protocol` to `"tcp"` or `"udp"` in `triggers.connect()`. UDP triggers also accept `idleTimeoutMs` and `maxPendingBytes`.

Triggers control which events invoke a Worker. They do not create `env` bindings. TypeScript checks the options for each trigger, while Workers runtime types provide the handler signatures.

## Declare exports

The `worker.exports` map describes how the platform manages module exports. Each key must match the `default` export or a named class exported by the entrypoint.

Use `exports.worker()` to configure a `WorkerEntrypoint`. It accepts an optional per-entrypoint cache setting. Use `exports.durableObject()` to declare a Durable Object class and its lifecycle state. Use `exports.workflow()` to declare a class that extends `WorkflowEntrypoint`.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-exports-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-exports-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-exports-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-exports-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-exports-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-exports-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>default: exports.worker({ cache: { enabled: false } }), (worker, cache, enabled reference)</summary>



<code>worker</code>Builder<a href="#config-exports-exports-worker-default">Link to worker</a>

<code>worker(options?: WorkerEntrypointExportOptions): WorkerEntrypointExport;</code>

Declares a WorkerEntrypoint export defined by this Worker.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code></dt>
<dd></dd>

</dl></details>



<code>cache</code>Optional<a href="#config-exports-exports-worker-default">Link to cache</a>

<code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code>

The type definition does not include a description.

<code>enabled</code>Required<a href="#config-exports-exports-worker-default">Link to enabled</a>

<code>enabled: boolean</code>

Whether cache is enabled for this entrypoint.

</details>

<details>

<summary>Admin: exports.worker({ cache: { enabled: true } }), (worker, cache, enabled reference)</summary>



<code>worker</code>Builder<a href="#config-exports-exports-worker-default-2">Link to worker</a>

<code>worker(options?: WorkerEntrypointExportOptions): WorkerEntrypointExport;</code>

Declares a WorkerEntrypoint export defined by this Worker.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code></dt>
<dd></dd>

</dl></details>



<code>cache</code>Optional<a href="#config-exports-exports-worker-default-2">Link to cache</a>

<code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code>

The type definition does not include a description.

<code>enabled</code>Required<a href="#config-exports-exports-worker-default-2">Link to enabled</a>

<code>enabled: boolean</code>

Whether cache is enabled for this entrypoint.

</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#config-exports-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#config-exports-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

<details>

<summary>OrderWorkflow: exports.workflow({ (workflow reference)</summary>



<code>workflow</code>Builder<a href="#config-exports-exports-workflow-default">Link to workflow</a>

<code>workflow(options: WorkflowExportOptions): WorkflowExport;</code>

Declares a Workflow defined by this Worker. The export's key must name a class that extends <code>WorkflowEntrypoint</code>. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>

<details>

<summary>Options (5)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the Workflow. It identifies the Workflow's instances and must be unique within the account.</dd>

<dt><code>limits?: { /** Maximum number of steps a single Workflow instance may run. */ steps?: number; }</code></dt>
<dd></dd>

<dt><code>concurrency?: { /** Maximum number of Workflow instances that can run concurrently. */ limit?: number; }</code></dt>
<dd></dd>

<dt><code>schedules?: string | string[]</code></dt>
<dd>Cron schedule(s) that automatically trigger Workflow instances.</dd>

<dt><code>defaultRetention?: { /** How long to retain instances that completed successfully or were terminated. */ successRetention?: number | string; /** How long to retain errored instances. */ errorRetention?: number | string; }</code></dt>
<dd>Default retention for instances of this Workflow, applied when an instance does not set its own retention. Accepts milliseconds or a duration string such as <code>"3 days"</code>.</dd>

</dl></details>



</details>

<details>

<summary>name: "order-workflow", (name reference)</summary>



<code>name</code>Required<a href="#config-exports-exports-workflow-default-name">Link to name</a>

<code>name: string</code>

The name of the Workflow. It identifies the Workflow's instances and must be unique within the account.

</details>

<details>

<summary>limits: { steps: 100 }, (limits, steps reference)</summary>



<code>limits</code>Optional<a href="#config-exports-exports-workflow-default-limits">Link to limits</a>

<code>limits?: { /** Maximum number of steps a single Workflow instance may run. */ steps?: number; }</code>

The type definition does not include a description.

<code>steps</code>Optional<a href="#config-exports-exports-workflow-default-limits">Link to steps</a>

<code>steps?: number</code>

Maximum number of steps a single Workflow instance may run.

</details>

<details>

<summary>defaultRetention: { (defaultRetention reference)</summary>



<code>defaultRetention</code>Optional<a href="#config-exports-exports-workflow-default-defaultretention">Link to defaultRetention</a>

<code>defaultRetention?: { /** How long to retain instances that completed successfully or were terminated. */ successRetention?: number | string; /** How long to retain errored instances. */ errorRetention?: number | string; }</code>

Default retention for instances of this Workflow, applied when an instance does not set its own retention. Accepts milliseconds or a duration string such as <code>"3 days"</code>.

</details>

<details>

<summary>successRetention: "3 days", (successRetention reference)</summary>



<code>successRetention</code>Optional<a href="#config-exports-exports-workflow-default-defaultretention-successretention">Link to successRetention</a>

<code>successRetention?: number | string</code>

How long to retain instances that completed successfully or were terminated.

</details>

<details>

<summary>errorRetention: "7 days", (errorRetention reference)</summary>



<code>errorRetention</code>Optional<a href="#config-exports-exports-workflow-default-defaultretention-errorretention">Link to errorRetention</a>

<code>errorRetention?: number | string</code>

How long to retain errored instances.

</details>

},

}),

},

},

});

The builders describe exported code. They do not create JavaScript exports. The entrypoint must still export `Admin`, `Counter`, and `OrderWorkflow`.

`exports.workflow()` requires a `name`, which must be unique within the account. It also accepts `limits.steps`, `concurrency.limit`, `schedules` for cron schedules that start instances, and `defaultRetention`. Retention values accept milliseconds or a duration string, such as `"3 days"`.

To bind to a Workflow, from the same Worker or another one, use `bindings.workflow()`. It requires the Workflow's `name`, the `worker` that defines it (a Worker name or a Worker definition), and the `exportName` of its class, such as `bindings.workflow({ name: "order-workflow", worker: "example-worker", exportName: "OrderWorkflow" })`.

### Manage Durable Object lifecycle

The `exports` map replaces an ordered Durable Object migration history. Keep live classes in the map. Add temporary tombstones when a class is deleted, renamed, or transferred.

The key of each entry is the Durable Object class name. The `state` field selects the valid lifecycle options:

| State | Purpose |
| --- | --- |
| `created` or omitted | Declares a live class with `sqlite` or `legacy-kv` storage |
| `deleted` | Retires a namespace after its class is removed |
| `renamed` | Renames the key to the live class named by `renamedTo` |
| `expecting-transfer` | Prepares the destination Worker to receive a namespace from `transferFrom` |
| `transferred` | Transfers ownership to the same-account Worker named by `transferredTo` |

Use `sqlite` for new classes. A live or incoming class that uses `sqlite` can attach a Container definition. You cannot attach a Container to a `legacy-kv` class or a tombstone.

#### Distinguish exports from bindings

Exports and bindings serve different purposes:

| Configuration | Purpose |
| --- | --- |
| `exports.Counter` | Declares the class and manages its namespace lifecycle |
| `env.COUNTERS` | Injects a namespace binding under `env.COUNTERS` |
| `ctx.exports.Counter` | Accesses a class exported by the same Worker without an `env` binding |

Live Durable Object exports become typed properties on `ctx.exports`. A Worker does not need an `env` binding to call its own class.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-ctx-exports-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-ctx-exports-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "counter-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-ctx-exports-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-ctx-exports-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-ctx-exports-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>compatibilityFlags: ["enable_ctx_exports"], (compatibilityFlags reference)</summary>



<code>compatibilityFlags</code>Optional<a href="#config-ctx-exports-workerconfig-compatibilityflags">Link to compatibilityFlags</a>

<code>compatibilityFlags?: string[]</code>

A list of flags that enable features from upcoming features of the Workers runtime, usually used together with <code>compatibilityDate</code>. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-flags/">https://developers.cloudflare.com/workers/configuration/compatibility-flags/</a>

Default: <code>[]</code>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-ctx-exports-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#config-ctx-exports-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#config-ctx-exports-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

},

},

});

*src/index.jsjs*

```js
import { DurableObject } from "cloudflare:workers";

export class Counter extends DurableObject {
	getValue() {
		return this.ctx.storage.get("value");
	}
}

export default {
	async fetch(_request, _env, ctx) {
		const id = ctx.exports.Counter.idFromName("global");
		const stub = ctx.exports.Counter.get(id);
		return Response.json({ value: await stub.getValue() });
	},
};
```

*src/index.tsts*

```ts
import { DurableObject } from "cloudflare:workers";

export class Counter extends DurableObject {
	getValue() {
		return this.ctx.storage.get<number>("value");
	}
}

export default {
	async fetch(_request, _env, ctx) {
		const id = ctx.exports.Counter.idFromName("global");
		const stub = ctx.exports.Counter.get(id);
		return Response.json({ value: await stub.getValue() });
	},
} satisfies ExportedHandler<Env>;
```

The generated types include live and incoming Durable Object exports. Tombstones do not appear on `ctx.exports`.

#### Rename or delete a class

A rename keeps the old name as a tombstone. The destination name must appear as a live entry in the same map. Remove the old class from the Worker code.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-rename-delete-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-rename-delete-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "counter-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-rename-delete-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-rename-delete-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-rename-delete-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-rename-delete-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)</summary>



<code>durableObject</code>Builder<a href="#config-rename-delete-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



<code>storage</code>Required<a href="#config-rename-delete-exports-durableobject-created">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

<details>

<summary>OldCounter: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-rename-delete-exports-durableobject-renamed">Link to durableObject</a>

<code>durableObject(options: DurableObjectRenamedExportOptions): DurableObjectRenamedExport;</code>

Rename a provisioned Durable Object namespace's class.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>state: "renamed"</code></dt>
<dd></dd>

<dt><code>renamedTo: string</code></dt>
<dd>The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.</dd></dl></details>



</details>

<details>

<summary>state: "renamed", (state reference)</summary>



<code>state</code>Required<a href="#config-rename-delete-exports-durableobject-renamed-state">Link to state</a>

<code>state: "renamed"</code>

The type definition does not include a description.

</details>

<details>

<summary>renamedTo: "Counter", (renamedTo reference)</summary>



<code>renamedTo</code>Required<a href="#config-rename-delete-exports-durableobject-renamed-renamedto">Link to renamedTo</a>

<code>renamedTo: string</code>

The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.

</details>

}),

<details>

<summary>UnusedCounter: exports.durableObject({ state: "deleted" }), (durableObject, state reference)</summary>



<code>durableObject</code>Builder<a href="#config-rename-delete-exports-durableobject-deleted">Link to durableObject</a>

<code>durableObject(options: DurableObjectDeletedExportOptions): DurableObjectDeletedExport;</code>

Retire a provisioned Durable Object namespace whose class has been removed from code.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>state: "deleted"</code></dt>
<dd></dd>

</dl></details>



<code>state</code>Required<a href="#config-rename-delete-exports-durableobject-deleted">Link to state</a>

<code>state: "deleted"</code>

The type definition does not include a description.

</details>

},

},

});

Before you delete a namespace, remove every binding to that class. The uploaded Worker must not export a class marked as `deleted`.

Deployment responses identify stale tombstones that are safe to remove. Keep each tombstone until it appears in that response, then remove it from the map. You do not need to retain the complete migration history.

#### Transfer a class between Workers

A namespace transfer uses two deployments. Both Workers must use the same Cloudflare account.

First, deploy the destination Worker with an incoming live entry:

Select a highlighted line to show its type and description below it.

destination/cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-transfer-destination-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-transfer-destination-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "destination-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-transfer-destination-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-transfer-destination-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-transfer-destination-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-transfer-destination-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-transfer-destination-exports-durableobject-expecting-transfer">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectExpectingTransferExportOptions&lt;TContainer&gt;): DurableObjectExpectingTransferExport&lt;TContainer&gt;;</code>

Prepare to receive cross-Worker Durable Object transfer. The source Worker must follow up with a deployment containing a <code>transferred</code> export to commit the transfer.

<details>

<summary>Options (5)</summary>



<dl>

<dt><code>state: "expecting-transfer"</code></dt>
<dd></dd>

<dt><code>transferFrom: string</code></dt>
<dd>The source Worker for the two-phase cross-Worker transfer.</dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



</details>

<details>

<summary>state: "expecting-transfer", (state reference)</summary>



<code>state</code>Required<a href="#config-transfer-destination-exports-durableobject-expecting-transfer-state">Link to state</a>

<code>state: "expecting-transfer"</code>

The type definition does not include a description.

</details>

<details>

<summary>storage: "sqlite", (storage reference)</summary>



<code>storage</code>Required<a href="#config-transfer-destination-exports-durableobject-expecting-transfer-storage">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

<details>

<summary>transferFrom: "source-worker", (transferFrom reference)</summary>



<code>transferFrom</code>Required<a href="#config-transfer-destination-exports-durableobject-expecting-transfer-transferfrom">Link to transferFrom</a>

<code>transferFrom: string</code>

The source Worker for the two-phase cross-Worker transfer.

</details>

}),

},

},

});

Then deploy the source Worker with a transfer tombstone:

Select a highlighted line to show its type and description below it.

source/cloudflare.config.ts

Expand allCopy

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-transfer-source-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-transfer-source-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "source-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-transfer-source-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-transfer-source-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-transfer-source-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-transfer-source-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Counter: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-transfer-source-exports-durableobject-transferred">Link to durableObject</a>

<code>durableObject(options: DurableObjectTransferredExportOptions): DurableObjectTransferredExport;</code>

Transfer ownership of a Durable Object namespace to another Worker in the same account.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>state: "transferred"</code></dt>
<dd></dd>

<dt><code>transferredTo: string</code></dt>
<dd>The destination Worker. Must reference a Worker in the same account.</dd></dl></details>



</details>

<details>

<summary>state: "transferred", (state reference)</summary>



<code>state</code>Required<a href="#config-transfer-source-exports-durableobject-transferred-state">Link to state</a>

<code>state: "transferred"</code>

The type definition does not include a description.

</details>

<details>

<summary>transferredTo: "destination-worker", (transferredTo reference)</summary>



<code>transferredTo</code>Required<a href="#config-transfer-source-exports-durableobject-transferred-transferredto">Link to transferredTo</a>

<code>transferredTo: string</code>

The destination Worker. Must reference a Worker in the same account.

</details>

}),

},

},

});

Lifecycle changes take effect when a version is deployed, not when it is uploaded. Deploy an export-changing version to 100% of traffic before you split traffic with other versions. The platform rejects split deployments whose versions disagree about `exports`.

### Attach a Container

Define a Container once. Reference it from a Durable Object export and add it to the top-level `containers` array.

Select a highlighted line to show its type and description below it.

cloudflare.config.ts

Expand allCopy

import { bindings, defineConfig, defineContainer, exports } from "cf/config";

import \* as entrypoint from "./src/index.ts" with { type: "cf-worker" };

<details>

<summary>const imageProcessor = defineContainer({ (defineContainer reference)</summary>



<code>defineContainer</code>Function<a href="#config-container-definecontainer">Link to defineContainer</a>

<code>defineContainer&lt;T extends ConfigInput&lt;ContainerConfig&gt;&gt;(config: T): T;</code>

Defines a Container application that you can list in <code>containers</code> in <code>defineConfig()</code> or attach to a Durable Object export with its <code>container</code> option.

</details>

name: "image-processor",

image: { dockerfile: "./Dockerfile" },

instanceType: "lite",

maxInstances: 1,

});

<details>

<summary>export default defineConfig({ (defineConfig reference)</summary>



<code>defineConfig</code>Function<a href="#config-container-defineconfig">Link to defineConfig</a>

<code>defineConfig&lt;T extends ConfigInput&lt;CloudflareConfig&gt;&gt;(config: T): T;</code>

Defines the default export of <code>cloudflare.config.ts</code>. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (<code>isPreview</code> and <code>mode</code>) and returns either.

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>accountId?: string</code></dt>
<dd>This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.</dd>

<dt><code>complianceRegion?: "public" | "fedramp-high"</code></dt>
<dd>The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.</dd>

<dt><code>worker?: ConfigInput&lt;WorkerConfig&gt;</code></dt>
<dd>The Worker defined by this configuration.</dd>

<dt><code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code></dt>
<dd>Container applications defined by this configuration.</dd></dl></details>



</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-container-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "image-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-container-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-container-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-container-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-container-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>ImageProcessor: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-container-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



</details>

<details>

<summary>storage: "sqlite", (storage reference)</summary>



<code>storage</code>Required<a href="#config-container-exports-durableobject-created-storage">Link to storage</a>

<code>storage: "sqlite" | "legacy-kv"</code>

Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.

</details>

<details>

<summary>container: imageProcessor, (container reference)</summary>



<code>container</code>Optional<a href="#config-container-exports-durableobject-created-container">Link to container</a>

<code>container?: TContainer</code>

Attach a Container application to this Durable Object by config reference.

</details>

}),

},

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-container-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>IMAGE_PROCESSOR: bindings.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-container-bindings-durableobject-all">Link to durableObject</a>

<code>durableObject&lt;TWorker$1 extends WorkerReference, TExportName$1 extends DurableObjectExportName&lt;TWorker$1&gt;&gt;(options: DurableObjectBindingOptions&lt;TWorker$1, TExportName$1&gt;): DurableObjectBinding&lt;TWorker$1, TExportName$1&gt;;</code>

Binding to a Durable Object class. <code>worker</code> is the name or config of the Worker that defines the class; <code>exportName</code> is the exported class name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the Worker that defines the Durable Object class.</dd>

<dt><code>exportName: TExportName$1</code></dt>
<dd>The exported class name of the Durable Object.</dd></dl></details>



</details>

<details>

<summary>worker: "image-worker", (worker reference)</summary>



<code>worker</code>Required<a href="#config-container-bindings-durableobject-all-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the Worker that defines the Durable Object class.

</details>

<details>

<summary>exportName: "ImageProcessor", (exportName reference)</summary>



<code>exportName</code>Required<a href="#config-container-bindings-durableobject-all-exportname">Link to exportName</a>

<code>exportName: TExportName$1</code>

The exported class name of the Durable Object.

</details>

}),

},

},

<details>

<summary>containers: [imageProcessor], (containers reference)</summary>



<code>containers</code>Optional<a href="#config-container-cloudflareconfig-containers">Link to containers</a>

<code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code>

Container applications defined by this configuration.

</details>

});

Container names must be unique. Each Container can be linked to only one Durable Object export.

`cf deploy` applies supported Container application changes. `cf workers versions create` prepares images for Durable Object-managed Containers, but it does not apply Container applications.

## Set account defaults

Set `accountId` and `complianceRegion` at the top level of the default export. Supported compliance regions are `public` and `fedramp-high`.

`CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_COMPLIANCE_REGION` take priority over these values. When neither the environment nor the configuration sets an account, `cf` uses the account it saved on an earlier command, or resolves one from your credentials. For the full order, refer to [Select an account](https://developers.cloudflare.com/cf/get-started/#select-an-account).

`cf` searches from the current directory toward the filesystem root and uses the nearest `cloudflare.config.ts` file.

When an API command reads account defaults, `cf` executes the module and resolves the default export. If the default export is a function, `cf` calls it with `isPreview: false` and the mode passed with `--mode`. Without `--mode`, the mode is `undefined`, while a Vite build of the same project uses `production`. `cf deploy`, `cf workers versions create`, and `cf workers triggers deploy` resolve the account the same way. Without `--mode`, they evaluate the configuration with an `undefined` mode, even when the Vite build used `production`. If `accountId` depends on the mode, pass `--mode` explicitly to every command.

API commands do not evaluate nested `worker` or `containers` factories, and they do not validate Worker fields. Syntax errors, import errors, and top-level runtime errors in the module still break them.

## Select a mode

Pass `--mode <NAME>`, or `-m <NAME>`, to evaluate function-form configuration for a named mode. Project commands also pass the mode to the build:

```sh
cf build --mode staging
cf deploy --mode staging
```

When you omit `--mode`, the default depends on the tool that evaluates the configuration:

| Command | Default mode |
| --- | --- |
| `cf dev` with the Cloudflare Vite plugin | `development` |
| `cf build`, `cf deploy`, and other commands that build with Vite | `production` |
| Commands that build with Wrangler | `undefined` |
| API commands, such as `cf d1 list` | `undefined` |

When `cf` runs a framework's own command, only Vite and Astro accept `--mode`. For other frameworks, the command stops with an error that says the detected command does not currently support `--mode`.

Build Output records the mode in its root `config.json`. To deploy an existing build with `--prebuilt`, pass the recorded mode. For the rule and examples, refer to [Deploy a prebuilt build](https://developers.cloudflare.com/cf/projects/#deploy-a-prebuilt-build).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/projects/cloudflare-config/#page","headline":"Programmatic configuration","description":"Configure Workers projects with a typed cloudflare.config.ts file.","url":"https://developers.cloudflare.com/cf/projects/cloudflare-config/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/projects/cloudflare-config/og.png?v=b3958a991af163a7","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: See how cloudflare.config.ts describes each part of an application, and what each typed field means.
title: Configuration explorer
image: https://developers.cloudflare.com/cf/projects/config-explorer/og.png?v=8877be631a13b653
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configuration explorer

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/projects/config-explorer/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

`cloudflare.config.ts` is a TypeScript file, so every field has a type and a description. Use the configuration explorer to see how the file describes the main parts of an application: project settings, the Worker, bindings, triggers, and exports.

Select a category, then select a highlighted field to see its type, description, default value, and accepted options. Editors with TypeScript support show the same information in autocomplete and hover text as you write the file, and type checking flags values that do not match.

To learn how to structure a project's configuration, refer to [Programmatic configuration](https://developers.cloudflare.com/cf/projects/cloudflare-config/). To return different configuration for each environment, refer to [Modes](https://developers.cloudflare.com/cf/projects/#modes).

Select a highlighted line to show its type and description below it.

Generated from `@cloudflare/config`0.20.0

defineConfig6 optionsWorker18 optionsBindings35 optionsTriggers5 optionsExports7 options

Expand allCopy

### defineConfig

import { defineConfig } from "cf/config";

import \* as entrypoint from "./src/index" with { type: "cf-worker" };

<details>

<summary>export default defineConfig(({ isPreview, mode }) =&gt; ({ (isPreview, mode reference)</summary>



<code>isPreview</code>Context value<a href="#config-reference-config-configcontext-ispreview">Link to isPreview</a>

<code>isPreview: boolean</code>

Whether the config is being evaluated for a Preview build.

<code>mode</code>Context value<a href="#config-reference-config-configcontext-ispreview">Link to mode</a>

<code>mode: string | undefined</code>

The mode the config is being evaluated in. Set via the <code>--mode</code> CLI flag. In Vite the mode defaults to <code>development</code> in <code>vite dev</code> and <code>production</code> in <code>vite build</code> (<a href="https://vite.dev/guide/env-and-mode.html#modes">more info</a>). In Wrangler the mode defaults to <code>undefined</code>.

</details>

<details>

<summary>accountId: "&lt;ACCOUNT_ID&gt;", (accountId reference)</summary>



<code>accountId</code>Optional<a href="#config-reference-config-settings-accountid">Link to accountId</a>

<code>accountId?: string</code>

This is the ID of the account associated with your zone. It can also be specified through the <code>CLOUDFLARE_ACCOUNT_ID</code> environment variable.

</details>

<details>

<summary>complianceRegion: mode === "fedramp" ? "fedramp-high" : "public", (complianceRegion reference)</summary>



<code>complianceRegion</code>Optional<a href="#config-reference-config-settings-complianceregion">Link to complianceRegion</a>

<code>complianceRegion?: "public" | "fedramp-high"</code>

The compliance boundary in which commands should operate. When omitted, this can be supplied through <code>CLOUDFLARE_COMPLIANCE_REGION</code>.

</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-reference-config-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: isPreview ? "example-preview" : "example-worker", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-config-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-reference-config-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-reference-config-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

},

<details>

<summary>containers: [], (containers reference)</summary>



<code>containers</code>Optional<a href="#config-reference-config-cloudflareconfig-containers">Link to containers</a>

<code>containers?: ConfigInput&lt;ContainerConfig&gt;[]</code>

Container applications defined by this configuration.

</details>

}));

### Worker

import { bindings, defineConfig, exports, triggers } from "cf/config";

import \* as entrypoint from "./src/index" with { type: "cf-worker" };

<details>

<summary>export default defineConfig(({ mode }) =&gt; ({ (mode reference)</summary>



<code>mode</code>Context value<a href="#config-reference-worker-configcontext-mode">Link to mode</a>

<code>mode: string | undefined</code>

The mode the config is being evaluated in. Set via the <code>--mode</code> CLI flag. In Vite the mode defaults to <code>development</code> in <code>vite dev</code> and <code>production</code> in <code>vite build</code> (<a href="https://vite.dev/guide/env-and-mode.html#modes">more info</a>). In Wrangler the mode defaults to <code>undefined</code>.

</details>

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-reference-worker-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: mode === "staging" ? "images-staging" : "images", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-worker-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-reference-worker-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>compatibilityFlags: ["nodejs_compat"], (compatibilityFlags reference)</summary>



<code>compatibilityFlags</code>Optional<a href="#config-reference-worker-workerconfig-compatibilityflags">Link to compatibilityFlags</a>

<code>compatibilityFlags?: string[]</code>

A list of flags that enable features from upcoming features of the Workers runtime, usually used together with <code>compatibilityDate</code>. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-flags/">https://developers.cloudflare.com/workers/configuration/compatibility-flags/</a>

Default: <code>[]</code>

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-reference-worker-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>assets: { (assets reference)</summary>



<code>assets</code>Optional<a href="#config-reference-worker-workerconfig-assets">Link to assets</a>

<code>assets?: { /** How to handle HTML requests. */ htmlHandling?: "auto-trailing-slash" | "drop-trailing-slash" | "force-trailing-slash" | "none"; /** How to handle requests that do not match an asset. */ notFoundHandling?: "single-page-application" | "404-page" | "none"; /** * Matches will be routed to the User Worker, and matches to negative rules will go to the Asset Worker. * * Can also be `true`, indicating that every request should be routed to the User Worker. */ runWorkerFirst?: string[] | boolean; }</code>

Specify the directory of static assets to deploy/serve. More details at <a href="https://developers.cloudflare.com/workers/frameworks/">https://developers.cloudflare.com/workers/frameworks/</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#assets">https://developers.cloudflare.com/workers/wrangler/configuration/#assets</a>

</details>

<details>

<summary>htmlHandling: "auto-trailing-slash", (htmlHandling reference)</summary>



<code>htmlHandling</code>Optional<a href="#config-reference-worker-workerconfig-assets-htmlhandling">Link to htmlHandling</a>

<code>htmlHandling?: "auto-trailing-slash" | "drop-trailing-slash" | "force-trailing-slash" | "none"</code>

How to handle HTML requests.

</details>

},

<details>

<summary>domains: ["images.example.com"], (domains reference)</summary>



<code>domains</code>Optional<a href="#config-reference-worker-workerconfig-domains">Link to domains</a>

<code>domains?: string[]</code>

Custom domains that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

</details>

<details>

<summary>triggers: [ (triggers reference)</summary>



<code>triggers</code>Optional<a href="#config-reference-worker-workerconfig-triggers">Link to triggers</a>

<code>triggers?: Trigger[]</code>

Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a>

</details>

<details>

<summary>triggers.scheduled({ (scheduled reference)</summary>



<code>scheduled</code>Builder<a href="#config-reference-worker-triggers-scheduled-default">Link to scheduled</a>

<code>scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;</code>

Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>schedule: string</code></dt>
<dd>A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a></dd>

</dl></details>



</details>

<details>

<summary>schedule: "0 * * * *", (schedule reference)</summary>



<code>schedule</code>Required<a href="#config-reference-worker-triggers-scheduled-default-schedule">Link to schedule</a>

<code>schedule: string</code>

A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

</details>

}),

],

<details>

<summary>tailConsumers: [ (tailConsumers reference)</summary>



<code>tailConsumers</code>Optional<a href="#config-reference-worker-workerconfig-tailconsumers">Link to tailConsumers</a>

<code>tailConsumers?: Array&lt;{ /** The name of the service tail events will be forwarded to. */ worker: string; /** Whether to stream tail events in real time. */ streaming?: boolean; }&gt;</code>

A list of Tail Workers that are bound to this Worker. <code>@cloudflare/config</code> unifies regular and streaming tail consumers under a single field; pass <code>streaming: true</code> to forward streaming tail events.

Default: <code>[]</code>

</details>

{

<details>

<summary>worker: "log-sink", (worker reference)</summary>



<code>worker</code>Required<a href="#config-reference-worker-workerconfig-tailconsumers-worker">Link to worker</a>

<code>worker: string</code>

The name of the service tail events will be forwarded to.

</details>

<details>

<summary>streaming: true, (streaming reference)</summary>



<code>streaming</code>Optional<a href="#config-reference-worker-workerconfig-tailconsumers-streaming">Link to streaming</a>

<code>streaming?: boolean</code>

Whether to stream tail events in real time.

</details>

},

],

<details>

<summary>cache: { (cache reference)</summary>



<code>cache</code>Optional<a href="#config-reference-worker-workerconfig-cache">Link to cache</a>

<code>cache?: { /** If cache is enabled for this Worker. */ enabled: boolean; /** Whether cached assets may be reused across Worker versions. */ crossVersionCache?: boolean; }</code>

Specify the cache behavior of the Worker.

</details>

<details>

<summary>enabled: true, (enabled reference)</summary>



<code>enabled</code>Required<a href="#config-reference-worker-workerconfig-cache-enabled">Link to enabled</a>

<code>enabled: boolean</code>

If cache is enabled for this Worker.

</details>

<details>

<summary>crossVersionCache: true, (crossVersionCache reference)</summary>



<code>crossVersionCache</code>Optional<a href="#config-reference-worker-workerconfig-cache-crossversioncache">Link to crossVersionCache</a>

<code>crossVersionCache?: boolean</code>

Whether cached assets may be reused across Worker versions.

</details>

},

<details>

<summary>placement: { (placement reference)</summary>



<code>placement</code>Optional<a href="#config-reference-worker-workerconfig-placement">Link to placement</a>

<code>placement?: { mode: "off" | "smart"; hint?: string; } | { mode?: "targeted"; region: string; } | { mode?: "targeted"; host: string; } | { mode?: "targeted"; hostname: string; }</code>

Specify how the Worker should be located to minimize round-trip time. More details: <a href="https://developers.cloudflare.com/workers/platform/smart-placement/">https://developers.cloudflare.com/workers/platform/smart-placement/</a>

</details>

<details>

<summary>mode: "smart", (mode reference)</summary>



<code>mode</code>Required<a href="#config-reference-worker-workerconfig-placement-mode">Link to mode</a>

<code>mode: "off" | "smart"</code>

The type definition does not include a description.

</details>

},

<details>

<summary>limits: { (limits reference)</summary>



<code>limits</code>Optional<a href="#config-reference-worker-workerconfig-limits">Link to limits</a>

<code>limits?: { /** Maximum allowed CPU time for a Worker's invocation in milliseconds. */ cpuMs?: number; /** Maximum allowed number of fetch requests that a Worker's invocation can execute. */ subrequests?: number; }</code>

Specify limits for runtime behavior. Only supported for the "standard" Usage Model. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#limits">https://developers.cloudflare.com/workers/wrangler/configuration/#limits</a>

</details>

<details>

<summary>cpuMs: 50, (cpuMs reference)</summary>



<code>cpuMs</code>Optional<a href="#config-reference-worker-workerconfig-limits-cpums">Link to cpuMs</a>

<code>cpuMs?: number</code>

Maximum allowed CPU time for a Worker's invocation in milliseconds.

</details>

<details>

<summary>subrequests: 100, (subrequests reference)</summary>



<code>subrequests</code>Optional<a href="#config-reference-worker-workerconfig-limits-subrequests">Link to subrequests</a>

<code>subrequests?: number</code>

Maximum allowed number of fetch requests that a Worker's invocation can execute.

</details>

},

<details>

<summary>logpush: true, (logpush reference)</summary>



<code>logpush</code>Optional<a href="#config-reference-worker-workerconfig-logpush">Link to logpush</a>

<code>logpush?: boolean</code>

Send Trace Events from this Worker to Workers Logpush. This will not configure a corresponding Logpush job automatically. For more information about Workers Logpush, see: <a href="https://blog.cloudflare.com/logpush-for-workers/">https://blog.cloudflare.com/logpush-for-workers/</a>

</details>

<details>

<summary>observability: { (observability reference)</summary>



<code>observability</code>Optional<a href="#config-reference-worker-workerconfig-observability">Link to observability</a>

<code>observability?: { /** If observability is enabled for this Worker. */ enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** * Whether query strings are removed from request URLs in logs and traces. * * @default false */ redactQueryString?: boolean; /** Real-time Issues settings for this Worker. */ issues?: { /** Whether real-time Issues are enabled. */ enabled?: boolean; }; logs?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** Set to false to disable invocation logs. */ invocationLogs?: boolean; /** * If logs should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations logs emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }; traces?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** * If traces should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations traces emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }; }</code>

Specify the observability behavior of the Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#observability">https://developers.cloudflare.com/workers/wrangler/configuration/#observability</a>

</details>

<details>

<summary>enabled: true, (enabled reference)</summary>



<code>enabled</code>Optional<a href="#config-reference-worker-workerconfig-observability-enabled">Link to enabled</a>

<code>enabled?: boolean</code>

If observability is enabled for this Worker.

</details>

<details>

<summary>logs: { (logs reference)</summary>



<code>logs</code>Optional<a href="#config-reference-worker-workerconfig-observability-logs">Link to logs</a>

<code>logs?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** Set to false to disable invocation logs. */ invocationLogs?: boolean; /** * If logs should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations logs emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }</code>

The type definition does not include a description.

</details>

<details>

<summary>persist: true, (persist reference)</summary>



<code>persist</code>Optional<a href="#config-reference-worker-workerconfig-observability-logs-persist">Link to persist</a>

<code>persist?: boolean</code>

If logs should be persisted to the Cloudflare observability platform where they can be queried in the dashboard.

Default: <code>true</code>

</details>

},

<details>

<summary>traces: { (traces reference)</summary>



<code>traces</code>Optional<a href="#config-reference-worker-workerconfig-observability-traces">Link to traces</a>

<code>traces?: { enabled?: boolean; /** The sampling rate. */ headSamplingRate?: number; /** * If traces should be persisted to the Cloudflare observability platform where they can be queried in the dashboard. * * @default true */ persist?: boolean; /** * What destinations traces emitted from the Worker should be sent to. * * @default [] */ destinations?: string[]; }</code>

The type definition does not include a description.

</details>

<details>

<summary>persist: true, (persist reference)</summary>



<code>persist</code>Optional<a href="#config-reference-worker-workerconfig-observability-traces-persist">Link to persist</a>

<code>persist?: boolean</code>

If traces should be persisted to the Cloudflare observability platform where they can be queried in the dashboard.

Default: <code>true</code>

</details>

},

},

<details>

<summary>workersDev: false, (workersDev reference)</summary>



<code>workersDev</code>Optional<a href="#config-reference-worker-workerconfig-workersdev">Link to workersDev</a>

<code>workersDev?: boolean</code>

Whether we use <code>&lt;name&gt;.&lt;subdomain&gt;.workers.dev</code> to test and deploy your Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#workersdev">https://developers.cloudflare.com/workers/wrangler/configuration/#workersdev</a>

Default: <code>true</code>

</details>

<details>

<summary>previewUrls: true, (previewUrls reference)</summary>



<code>previewUrls</code>Optional<a href="#config-reference-worker-workerconfig-previewurls">Link to previewUrls</a>

<code>previewUrls?: boolean</code>

Whether we use <code>&lt;version&gt;-&lt;name&gt;.&lt;subdomain&gt;.workers.dev</code> to serve Preview URLs for your Worker.

Default: <code>false</code>

</details>

<details>

<summary>unsafe: { (unsafe reference)</summary>



<code>unsafe</code>Optional<a href="#config-reference-worker-workerconfig-unsafe">Link to unsafe</a>

<code>unsafe?: { /** * Arbitrary key/value pairs that will be included in the uploaded metadata. Values specified * here will always be applied to metadata last, so can add new or override existing fields. */ metadata?: Record&lt;string, unknown&gt;; /** * Used for internal capnp uploads for the Workers runtime. */ capnp?: { basePath: string; sourceSchemas: string[]; compiledSchema?: never; } | { basePath?: never; sourceSchemas?: never; compiledSchema: string; }; }</code>

"Unsafe" tables for runtime features that aren't directly supported by this configuration. Values are forwarded verbatim in the Worker's upload metadata.

Default: <code>{}</code>

</details>

<details>

<summary>metadata: { build: "docs-example" }, (metadata reference)</summary>



<code>metadata</code>Optional<a href="#config-reference-worker-workerconfig-unsafe-metadata">Link to metadata</a>

<code>metadata?: Record&lt;string, unknown&gt;</code>

Arbitrary key/value pairs that will be included in the uploaded metadata. Values specified here will always be applied to metadata last, so can add new or override existing fields.

</details>

},

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-reference-worker-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>API_ORIGIN: bindings.text("https://api.example.com"), (text reference)</summary>



<code>text</code>Builder<a href="#config-reference-worker-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

<details>

<summary>DATABASE: bindings.d1({ (d1 reference)</summary>



<code>d1</code>Builder<a href="#config-reference-worker-bindings-d1-default">Link to d1</a>

<code>d1(options?: D1BindingOptions): D1Binding;</code>

Binding to a D1 database. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases">https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The UUID of this D1 database (not required).</dd>

<dt><code>name?: string</code></dt>
<dd>The name of this D1 database.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>name: "images-db", (name reference)</summary>



<code>name</code>Optional<a href="#config-reference-worker-bindings-d1-default-name">Link to name</a>

<code>name?: string</code>

The name of this D1 database.

</details>

}),

<details>

<summary>IMAGES: bindings.r2({ (r2 reference)</summary>



<code>r2</code>Builder<a href="#config-reference-worker-bindings-r2-default">Link to r2</a>

<code>r2(options?: R2BindingOptions): R2Binding;</code>

Binding to an R2 bucket. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets">https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this R2 bucket at the edge.</dd>

<dt><code>jurisdiction?: string</code></dt>
<dd>The jurisdiction that the bucket exists in. Default if not present.</dd>

<dt><code>dev?: BindingDevOptions &amp; { /** EXPERIMENTAL: credentials for the local S3-compatible endpoint. */ experimentalS3Credentials?: { accessKeyId: string; secretAccessKey: string; }; }</code></dt>
<dd>Settings that only apply to local development.</dd></dl></details>



</details>

<details>

<summary>name: "source-images", (name reference)</summary>



<code>name</code>Optional<a href="#config-reference-worker-bindings-r2-default-name">Link to name</a>

<code>name?: string</code>

The name of this R2 bucket at the edge.

</details>

}),

},

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-reference-worker-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>Admin: exports.worker({ (worker reference)</summary>



<code>worker</code>Builder<a href="#config-reference-worker-exports-worker-default">Link to worker</a>

<code>worker(options?: WorkerEntrypointExportOptions): WorkerEntrypointExport;</code>

Declares a WorkerEntrypoint export defined by this Worker.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code></dt>
<dd></dd>

</dl></details>



</details>

<details>

<summary>cache: { (cache reference)</summary>



<code>cache</code>Optional<a href="#config-reference-worker-exports-worker-default-cache">Link to cache</a>

<code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code>

The type definition does not include a description.

</details>

<details>

<summary>enabled: true, (enabled reference)</summary>



<code>enabled</code>Required<a href="#config-reference-worker-exports-worker-default-cache-enabled">Link to enabled</a>

<code>enabled: boolean</code>

Whether cache is enabled for this entrypoint.

</details>

},

}),

<details>

<summary>Counter: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-worker-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



</details>

<details>

<summary>storage: "sqlite", (storage reference)</summary>



<code>storage</code>Required<a href="#config-reference-worker-exports-durableobject-created-storage">Link to storage</a>

<code>storage: "sqlite"</code>

Selects the SQLite-backed storage engine (recommended for new classes).

</details>

}),

},

},

}));

### Bindings

import { bindings, defineConfig } from "cf/config";

import \* as entrypoint from "./src/index" with { type: "cf-worker" };

export default defineConfig({

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-reference-bindings-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "binding-showcase", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-bindings-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-reference-bindings-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-reference-bindings-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>env: { (env reference)</summary>



<code>env</code>Optional<a href="#config-reference-bindings-workerconfig-env">Link to env</a>

<code>env?: Record&lt;string, Binding&gt;</code>

Bindings exposed on the Worker's <code>env</code> object. Construct entries with <code>bindings.kv(...)</code>, <code>bindings.r2(...)</code>, etc.

</details>

<details>

<summary>MY_AGENT_MEMORY: bindings.agentMemory({ (agentMemory reference)</summary>



<code>agentMemory</code>Builder<a href="#config-reference-bindings-bindings-agentmemory-default">Link to agentMemory</a>

<code>agentMemory(options: AgentMemoryBindingOptions): AgentMemoryBinding;</code>

Agent Memory namespace binding. Each binding is scoped to a namespace and allows agents to persist and recall memory.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>namespace: string</code></dt>
<dd>The user-chosen namespace name. Must exist in Cloudflare at deploy time.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>namespace: "my-namespace", (namespace reference)</summary>



<code>namespace</code>Required<a href="#config-reference-bindings-bindings-agentmemory-default-namespace">Link to namespace</a>

<code>namespace: string</code>

The user-chosen namespace name. Must exist in Cloudflare at deploy time.

</details>

}),

<details>

<summary>MY_AI: bindings.ai(), (ai reference)</summary>



<code>ai</code>Builder<a href="#config-reference-bindings-bindings-ai-default">Link to ai</a>

<code>ai&lt;TAiModelList extends AiModelListType = AiModels&gt;(options?: AiBindingOptions): TypedAiBinding&lt;TAiModelList&gt;;</code>

Binding to the Workers AI project. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai">https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_AI_SEARCH: bindings.aiSearch({ (aiSearch reference)</summary>



<code>aiSearch</code>Builder<a href="#config-reference-bindings-bindings-aisearch-default">Link to aiSearch</a>

<code>aiSearch(options: AiSearchBindingOptions): AiSearchBinding;</code>

AI Search instance binding. Each binding is bound directly to a single pre-existing instance within the "default" namespace.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The user-chosen instance name. Must exist in Cloudflare at deploy time.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>name: "my-resource", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-bindings-bindings-aisearch-default-name">Link to name</a>

<code>name: string</code>

The user-chosen instance name. Must exist in Cloudflare at deploy time.

</details>

}),

<details>

<summary>MY_AI_SEARCH_NAMESPACE: bindings.aiSearchNamespace({ (aiSearchNamespace reference)</summary>



<code>aiSearchNamespace</code>Builder<a href="#config-reference-bindings-bindings-aisearchnamespace-default">Link to aiSearchNamespace</a>

<code>aiSearchNamespace(options: AiSearchNamespaceBindingOptions): AiSearchNamespaceBinding;</code>

AI Search namespace binding. Each binding is scoped to a namespace and allows dynamic instance CRUD within it.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>namespace: string</code></dt>
<dd>The user-chosen namespace name. Must exist in Cloudflare at deploy time.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>namespace: "my-namespace", (namespace reference)</summary>



<code>namespace</code>Required<a href="#config-reference-bindings-bindings-aisearchnamespace-default-namespace">Link to namespace</a>

<code>namespace: string</code>

The user-chosen namespace name. Must exist in Cloudflare at deploy time.

</details>

}),

<details>

<summary>MY_ANALYTICS_ENGINE_DATASET: bindings.analyticsEngineDataset(), (analyticsEngineDataset reference)</summary>



<code>analyticsEngineDataset</code>Builder<a href="#config-reference-bindings-bindings-analyticsenginedataset-default">Link to analyticsEngineDataset</a>

<code>analyticsEngineDataset(options?: AnalyticsEngineDatasetBindingOptions): AnalyticsEngineDatasetBinding;</code>

Binding to an Analytics Engine dataset. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets">https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this dataset to write to.</dd></dl></details>



</details>

<details>

<summary>MY_ARTIFACTS: bindings.artifacts({ (artifacts reference)</summary>



<code>artifacts</code>Builder<a href="#config-reference-bindings-bindings-artifacts-default">Link to artifacts</a>

<code>artifacts(options: ArtifactsBindingOptions): ArtifactsBinding;</code>

Binding to an Artifacts instance. Artifacts provides git-compatible file storage on Cloudflare Workers.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>namespace: string</code></dt>
<dd>The namespace to use.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>namespace: "my-namespace", (namespace reference)</summary>



<code>namespace</code>Required<a href="#config-reference-bindings-bindings-artifacts-default-namespace">Link to namespace</a>

<code>namespace: string</code>

The namespace to use.

</details>

}),

<details>

<summary>MY_ASSETS: bindings.assets(), (assets reference)</summary>



<code>assets</code>Builder<a href="#config-reference-bindings-bindings-assets-default">Link to assets</a>

<code>assets(): AssetsBinding;</code>

Binding to the Worker's static assets. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#assets">https://developers.cloudflare.com/workers/wrangler/configuration/#assets</a>

</details>

<details>

<summary>MY_BROWSER: bindings.browser(), (browser reference)</summary>



<code>browser</code>Builder<a href="#config-reference-bindings-bindings-browser-default">Link to browser</a>

<code>browser(options?: BrowserBindingOptions): BrowserBinding;</code>

Binding to a headless browser usable from the Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering">https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_D1: bindings.d1(), (d1 reference)</summary>



<code>d1</code>Builder<a href="#config-reference-bindings-bindings-d1-default">Link to d1</a>

<code>d1(options?: D1BindingOptions): D1Binding;</code>

Binding to a D1 database. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases">https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The UUID of this D1 database (not required).</dd>

<dt><code>name?: string</code></dt>
<dd>The name of this D1 database.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_DISPATCH_NAMESPACE: bindings.dispatchNamespace(), (dispatchNamespace reference)</summary>



<code>dispatchNamespace</code>Builder<a href="#config-reference-bindings-bindings-dispatchnamespace-default">Link to dispatchNamespace</a>

<code>dispatchNamespace(options?: DispatchNamespaceBindingOptions): DispatchNamespaceBinding;</code>

Binding to a Workers for Platforms dispatch namespace. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms">https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>namespace?: string</code></dt>
<dd>The namespace to bind to.</dd>

<dt><code>outbound?: { /** Name of the Worker handling the outbound requests. */ worker: string; /** (Optional) List of parameter names, for sending context from your dispatch Worker to the outbound handler. */ parameters?: string[]; }</code></dt>
<dd>Details about the outbound Worker which will handle outbound requests from your namespace.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_DURABLE_OBJECT: bindings.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-bindings-bindings-durableobject-all">Link to durableObject</a>

<code>durableObject&lt;TWorker$1 extends WorkerReference, TExportName$1 extends DurableObjectExportName&lt;TWorker$1&gt;&gt;(options: DurableObjectBindingOptions&lt;TWorker$1, TExportName$1&gt;): DurableObjectBinding&lt;TWorker$1, TExportName$1&gt;;</code>

Binding to a Durable Object class. <code>worker</code> is the name or config of the Worker that defines the class; <code>exportName</code> is the exported class name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the Worker that defines the Durable Object class.</dd>

<dt><code>exportName: TExportName$1</code></dt>
<dd>The exported class name of the Durable Object.</dd></dl></details>



</details>

<details>

<summary>worker: "my-worker", (worker reference)</summary>



<code>worker</code>Required<a href="#config-reference-bindings-bindings-durableobject-all-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the Worker that defines the Durable Object class.

</details>

<details>

<summary>exportName: "MyDurableObject", (exportName reference)</summary>



<code>exportName</code>Required<a href="#config-reference-bindings-bindings-durableobject-all-exportname">Link to exportName</a>

<code>exportName: TExportName$1</code>

The exported class name of the Durable Object.

</details>

}),

<details>

<summary>MY_FLAGSHIP: bindings.flagship(), (flagship reference)</summary>



<code>flagship</code>Builder<a href="#config-reference-bindings-bindings-flagship-default">Link to flagship</a>

<code>flagship(options?: FlagshipBindingOptions): FlagshipBinding;</code>

Binding to a Flagship feature-flag service.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The Flagship app ID to bind to.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_HYPERDRIVE: bindings.hyperdrive({ (hyperdrive reference)</summary>



<code>hyperdrive</code>Builder<a href="#config-reference-bindings-bindings-hyperdrive-default">Link to hyperdrive</a>

<code>hyperdrive(options: HyperdriveBindingOptions): HyperdriveBinding;</code>

Binding to a Hyperdrive configuration. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive">https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>id: string</code></dt>
<dd>The ID of the Hyperdrive configuration.</dd>

<dt><code>dev?: { /** The database connection string used during local development. */ connectionString?: string; }</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>id: "resource-id", (id reference)</summary>



<code>id</code>Required<a href="#config-reference-bindings-bindings-hyperdrive-default-id">Link to id</a>

<code>id: string</code>

The ID of the Hyperdrive configuration.

</details>

}),

<details>

<summary>MY_IMAGES: bindings.images(), (images reference)</summary>



<code>images</code>Builder<a href="#config-reference-bindings-bindings-images-default">Link to images</a>

<code>images(options?: ImagesBindingOptions): ImagesBinding$1;</code>

Binding to Cloudflare Images. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#images">https://developers.cloudflare.com/workers/wrangler/configuration/#images</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_JSON: bindings.json({ feature: true }), (json reference)</summary>



<code>json</code>Builder<a href="#config-reference-bindings-bindings-json-default">Link to json</a>

<code>json&lt;T$1 extends Json&gt;(value: T$1): JsonBinding&lt;T$1&gt;;</code>

Inline JSON value made available to the Worker on <code>env</code> under the binding name.

</details>

<details>

<summary>MY_KV: bindings.kv(), (kv reference)</summary>



<code>kv</code>Builder<a href="#config-reference-bindings-bindings-kv-default">Link to kv</a>

<code>kv&lt;TKey extends string = string&gt;(options?: KvBindingOptions): TypedKvBinding&lt;TKey&gt;;</code>

Binding to a Workers KV namespace. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces">https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>id?: string</code></dt>
<dd>The ID of the KV namespace.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_LOGFWDR: bindings.logfwdr({ (logfwdr reference)</summary>



<code>logfwdr</code>Builder<a href="#config-reference-bindings-bindings-logfwdr-default">Link to logfwdr</a>

<code>logfwdr(options: LogfwdrBindingOptions): LogfwdrBinding;</code>

Binding for forwarding logs to logfwdr.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>destination: string</code></dt>
<dd>The destination for this logged message.</dd></dl></details>



</details>

<details>

<summary>destination: "my-destination", (destination reference)</summary>



<code>destination</code>Required<a href="#config-reference-bindings-bindings-logfwdr-default-destination">Link to destination</a>

<code>destination: string</code>

The destination for this logged message.

</details>

}),

<details>

<summary>MY_MEDIA: bindings.media(), (media reference)</summary>



<code>media</code>Builder<a href="#config-reference-bindings-bindings-media-default">Link to media</a>

<code>media(options?: MediaBindingOptions): MediaBinding$1;</code>

Binding to Cloudflare Media Transformations.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_MTLS_CERTIFICATE: bindings.mtlsCertificate({ (mtlsCertificate reference)</summary>



<code>mtlsCertificate</code>Builder<a href="#config-reference-bindings-bindings-mtlscertificate-default">Link to mtlsCertificate</a>

<code>mtlsCertificate(options: MtlsCertificateBindingOptions): MtlsCertificateBinding;</code>

Binding to an uploaded mTLS certificate. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates">https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>id: string</code></dt>
<dd>The UUID of the uploaded mTLS certificate.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>id: "resource-id", (id reference)</summary>



<code>id</code>Required<a href="#config-reference-bindings-bindings-mtlscertificate-default-id">Link to id</a>

<code>id: string</code>

The UUID of the uploaded mTLS certificate.

</details>

}),

<details>

<summary>MY_PIPELINE: bindings.pipeline({ (pipeline reference)</summary>



<code>pipeline</code>Builder<a href="#config-reference-bindings-bindings-pipeline-default">Link to pipeline</a>

<code>pipeline&lt;TRecord extends PipelineRecord = PipelineRecord&gt;(options: PipelineBindingOptions): TypedPipelineBinding&lt;TRecord&gt;;</code>

Binding to a Cloudflare Pipeline.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>Name of the Pipeline to bind.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>name: "my-resource", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-bindings-bindings-pipeline-default-name">Link to name</a>

<code>name: string</code>

Name of the Pipeline to bind.

</details>

}),

<details>

<summary>MY_QUEUE: bindings.queue(), (queue reference)</summary>



<code>queue</code>Builder<a href="#config-reference-bindings-bindings-queue-default">Link to queue</a>

<code>queue&lt;TBody = unknown&gt;(options?: QueueBindingOptions): TypedQueueBinding&lt;TBody&gt;;</code>

Producer binding to a Cloudflare Queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this Queue.</dd>

<dt><code>deliveryDelay?: number</code></dt>
<dd>The number of seconds to wait before delivering a message.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_R2: bindings.r2(), (r2 reference)</summary>



<code>r2</code>Builder<a href="#config-reference-bindings-bindings-r2-default">Link to r2</a>

<code>r2(options?: R2BindingOptions): R2Binding;</code>

Binding to an R2 bucket. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets">https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets</a>

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name?: string</code></dt>
<dd>The name of this R2 bucket at the edge.</dd>

<dt><code>jurisdiction?: string</code></dt>
<dd>The jurisdiction that the bucket exists in. Default if not present.</dd>

<dt><code>dev?: BindingDevOptions &amp; { /** EXPERIMENTAL: credentials for the local S3-compatible endpoint. */ experimentalS3Credentials?: { accessKeyId: string; secretAccessKey: string; }; }</code></dt>
<dd>Settings that only apply to local development.</dd></dl></details>



</details>

<details>

<summary>MY_RATE_LIMIT: bindings.rateLimit({ (rateLimit reference)</summary>



<code>rateLimit</code>Builder<a href="#config-reference-bindings-bindings-ratelimit-default">Link to rateLimit</a>

<code>rateLimit(options: RateLimitBindingOptions): RateLimitBinding;</code>

Binding to a rate limiter.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>namespace: string</code></dt>
<dd>The namespace ID for this rate limiter.</dd>

<dt><code>simple: { /** The maximum number of requests allowed in the time period. */ limit: number; /** The time period in seconds (10 for ten seconds, 60 for one minute). */ period: 10 | 60; }</code></dt>
<dd>Simple rate limiting configuration.</dd></dl></details>



</details>

<details>

<summary>namespace: "my-namespace", (namespace reference)</summary>



<code>namespace</code>Required<a href="#config-reference-bindings-bindings-ratelimit-default-namespace">Link to namespace</a>

<code>namespace: string</code>

The namespace ID for this rate limiter.

</details>

<details>

<summary>simple: { (simple reference)</summary>



<code>simple</code>Required<a href="#config-reference-bindings-bindings-ratelimit-default-simple">Link to simple</a>

<code>simple: { /** The maximum number of requests allowed in the time period. */ limit: number; /** The time period in seconds (10 for ten seconds, 60 for one minute). */ period: 10 | 60; }</code>

Simple rate limiting configuration.

</details>

<details>

<summary>limit: 1, (limit reference)</summary>



<code>limit</code>Required<a href="#config-reference-bindings-bindings-ratelimit-default-simple-limit">Link to limit</a>

<code>limit: number</code>

The maximum number of requests allowed in the time period.

</details>

<details>

<summary>period: 10, (period reference)</summary>



<code>period</code>Required<a href="#config-reference-bindings-bindings-ratelimit-default-simple-period">Link to period</a>

<code>period: 10 | 60</code>

The time period in seconds (10 for ten seconds, 60 for one minute).

</details>

},

}),

<details>

<summary>MY_SECRET: bindings.secret(), (secret reference)</summary>



<code>secret</code>Builder<a href="#config-reference-bindings-bindings-secret-default">Link to secret</a>

<code>secret(): SecretBinding;</code>

Declares a secret that is required by your Worker, exposed on <code>env</code> under the binding name. When defined, this binding: - Replaces .dev.vars/.env/process.env inference for type generation - Enables local dev validation with warnings for missing secrets For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#secrets-configuration-property">https://developers.cloudflare.com/workers/wrangler/configuration/#secrets-configuration-property</a>

</details>

<details>

<summary>MY_SECRETS_STORE_SECRET: bindings.secretsStoreSecret({ (secretsStoreSecret reference)</summary>



<code>secretsStoreSecret</code>Builder<a href="#config-reference-bindings-bindings-secretsstoresecret-default">Link to secretsStoreSecret</a>

<code>secretsStoreSecret(options: SecretsStoreSecretBindingOptions): SecretsStoreSecretBinding;</code>

Binding to a Secrets Store secret.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>storeId: string</code></dt>
<dd>ID of the secret store.</dd>

<dt><code>secretName: string</code></dt>
<dd>Name of the secret.</dd></dl></details>



</details>

<details>

<summary>storeId: "store-id", (storeId reference)</summary>



<code>storeId</code>Required<a href="#config-reference-bindings-bindings-secretsstoresecret-default-storeid">Link to storeId</a>

<code>storeId: string</code>

ID of the secret store.

</details>

<details>

<summary>secretName: "my-secret", (secretName reference)</summary>



<code>secretName</code>Required<a href="#config-reference-bindings-bindings-secretsstoresecret-default-secretname">Link to secretName</a>

<code>secretName: string</code>

Name of the secret.

</details>

}),

<details>

<summary>MY_SEND_EMAIL: bindings.sendEmail({ (sendEmail reference)</summary>



<code>sendEmail</code>Builder<a href="#config-reference-bindings-bindings-sendemail-default">Link to sendEmail</a>

<code>sendEmail(options?: SendEmailBindingOptions): SendEmailBinding;</code>

Binding for sending email from inside the Worker. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#email-bindings">https://developers.cloudflare.com/workers/wrangler/configuration/#email-bindings</a>

<details>

<summary>Options (6)</summary>



<dl>

<dt><code>destinationAddress: string</code></dt>
<dd>If this binding should be restricted to a specific verified address.</dd>

<dt><code>allowedDestinationAddresses?: never</code></dt>
<dd></dd>

<dt><code>destinationAddress?: never</code></dt>
<dd></dd>

<dt><code>allowedDestinationAddresses: string[]</code></dt>
<dd>If this binding should be restricted to a set of verified addresses.</dd>

<dt><code>allowedSenderAddresses?: string[]</code></dt>
<dd>If this binding should be restricted to a set of sender addresses.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>destinationAddress: "value", (destinationAddress reference)</summary>



<code>destinationAddress</code>Required<a href="#config-reference-bindings-bindings-sendemail-default-destinationaddress">Link to destinationAddress</a>

<code>destinationAddress: string</code>

If this binding should be restricted to a specific verified address.

</details>

}),

<details>

<summary>MY_STREAM: bindings.stream(), (stream reference)</summary>



<code>stream</code>Builder<a href="#config-reference-bindings-bindings-stream-default">Link to stream</a>

<code>stream(options?: StreamBindingOptions): StreamBinding$1;</code>

Binding to Cloudflare Stream.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>MY_TEXT: bindings.text("production"), (text reference)</summary>



<code>text</code>Builder<a href="#config-reference-bindings-bindings-text-default">Link to text</a>

<code>text&lt;T$1 extends string&gt;(value: T$1): TextBinding&lt;T$1&gt;;</code>

Inline string value made available to the Worker on <code>env</code> under the binding name. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables">https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables</a>

</details>

<details>

<summary>MY_VECTORIZE: bindings.vectorize({ (vectorize reference)</summary>



<code>vectorize</code>Builder<a href="#config-reference-bindings-bindings-vectorize-default">Link to vectorize</a>

<code>vectorize(options: VectorizeBindingOptions): VectorizeBinding;</code>

Binding to a Vectorize index. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes">https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the Vectorize index.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>name: "my-resource", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-bindings-bindings-vectorize-default-name">Link to name</a>

<code>name: string</code>

The name of the Vectorize index.

</details>

}),

<details>

<summary>MY_VERSION_METADATA: bindings.versionMetadata(), (versionMetadata reference)</summary>



<code>versionMetadata</code>Builder<a href="#config-reference-bindings-bindings-versionmetadata-default">Link to versionMetadata</a>

<code>versionMetadata(): VersionMetadataBinding;</code>

Binding to the Worker version's metadata.

</details>

<details>

<summary>MY_VPC_NETWORK: bindings.vpcNetwork({ (vpcNetwork reference)</summary>



<code>vpcNetwork</code>Builder<a href="#config-reference-bindings-bindings-vpcnetwork-default">Link to vpcNetwork</a>

<code>vpcNetwork(options: VpcNetworkBindingOptions): VpcNetworkBinding;</code>

Binding to a VPC network.

<details>

<summary>Options (5)</summary>



<dl>

<dt><code>tunnelId: string</code></dt>
<dd>The tunnel ID of the Cloudflare Tunnel to route traffic through. Mutually exclusive with <code>networkId</code>.</dd>

<dt><code>networkId?: never</code></dt>
<dd></dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd>

<dt><code>tunnelId?: never</code></dt>
<dd></dd>

<dt><code>networkId: string</code></dt>
<dd>The network ID to route traffic through. Mutually exclusive with <code>tunnelId</code>.</dd>

</dl></details>



</details>

<details>

<summary>tunnelId: "tunnel-id", (tunnelId reference)</summary>



<code>tunnelId</code>Required<a href="#config-reference-bindings-bindings-vpcnetwork-default-tunnelid">Link to tunnelId</a>

<code>tunnelId: string</code>

The tunnel ID of the Cloudflare Tunnel to route traffic through. Mutually exclusive with <code>networkId</code>.

</details>

}),

<details>

<summary>MY_VPC_SERVICE: bindings.vpcService({ (vpcService reference)</summary>



<code>vpcService</code>Builder<a href="#config-reference-bindings-bindings-vpcservice-default">Link to vpcService</a>

<code>vpcService(options: VpcServiceBindingOptions): VpcServiceBinding;</code>

Binding to a VPC service.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>id: string</code></dt>
<dd>The service ID of the VPC connectivity service.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>id: "resource-id", (id reference)</summary>



<code>id</code>Required<a href="#config-reference-bindings-bindings-vpcservice-default-id">Link to id</a>

<code>id: string</code>

The service ID of the VPC connectivity service.

</details>

}),

<details>

<summary>MY_WORKER: bindings.worker({ (worker reference)</summary>



<code>worker</code>Builder<a href="#config-reference-bindings-bindings-worker-default">Link to worker</a>

<code>worker&lt;TWorker$1 extends WorkerReference, TExportName$1 extends WorkerEntrypointExportName&lt;TWorker$1&gt; | undefined = undefined&gt;(options: WorkerBindingOptions&lt;TWorker$1, TExportName$1&gt;): WorkerBinding&lt;TWorker$1, NoInfer&lt;TExportName$1&gt;&gt;;</code>

Service binding (Worker-to-Worker). <code>worker</code> is the name or config of the bound Worker; <code>exportName</code> selects a named <code>WorkerEntrypoint</code> export (defaults to the default export). For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings">https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the bound Worker.</dd>

<dt><code>exportName?: TExportName$1</code></dt>
<dd>The named export to bind to (defaults to the default export).</dd>

<dt><code>props?: Record&lt;string, unknown&gt;</code></dt>
<dd>Optional properties that will be made available to the service via <code>ctx.props</code>.</dd>

<dt><code>dev?: BindingDevOptions</code></dt>
<dd>Options that only apply during local development.</dd></dl></details>



</details>

<details>

<summary>worker: "my-worker", (worker reference)</summary>



<code>worker</code>Required<a href="#config-reference-bindings-bindings-worker-default-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the bound Worker.

</details>

}),

<details>

<summary>MY_WORKER_LOADER: bindings.workerLoader(), (workerLoader reference)</summary>



<code>workerLoader</code>Builder<a href="#config-reference-bindings-bindings-workerloader-default">Link to workerLoader</a>

<code>workerLoader(): WorkerLoaderBinding;</code>

Binding to a Worker Loader.

</details>

<details>

<summary>MY_WORKFLOW: bindings.workflow({ (workflow reference)</summary>



<code>workflow</code>Builder<a href="#config-reference-bindings-bindings-workflow-default">Link to workflow</a>

<code>workflow&lt;TWorker$1 extends WorkerReference, TExportName$1 extends WorkflowExportName&lt;TWorker$1&gt;&gt;(options: WorkflowBindingOptions&lt;TWorker$1, TExportName$1&gt;): WorkflowBinding&lt;TWorker$1, NoInfer&lt;TExportName$1&gt;&gt;;</code>

Create a Workflow binding. <code>worker</code> may be a Worker config reference or a Worker name. <code>exportName</code> must be a valid <code>WorkflowEntrypoint</code> export for the given Worker.

<details>

<summary>Options (3)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the Workflow.</dd>

<dt><code>worker: TWorker$1</code></dt>
<dd>The name or config of the Worker that defines the Workflow.</dd>

<dt><code>exportName: TExportName$1</code></dt>
<dd>The exported class name of the Workflow.</dd></dl></details>



</details>

<details>

<summary>name: "my-resource", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-bindings-bindings-workflow-default-name">Link to name</a>

<code>name: string</code>

The name of the Workflow.

</details>

<details>

<summary>worker: "my-worker", (worker reference)</summary>



<code>worker</code>Required<a href="#config-reference-bindings-bindings-workflow-default-worker">Link to worker</a>

<code>worker: TWorker$1</code>

The name or config of the Worker that defines the Workflow.

</details>

<details>

<summary>exportName: "MyWorkflow", (exportName reference)</summary>



<code>exportName</code>Required<a href="#config-reference-bindings-bindings-workflow-default-exportname">Link to exportName</a>

<code>exportName: TExportName$1</code>

The exported class name of the Workflow.

</details>

}),

},

},

});

### Triggers

import { defineConfig, triggers } from "cf/config";

import \* as entrypoint from "./src/index" with { type: "cf-worker" };

export default defineConfig({

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-reference-triggers-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "trigger-showcase", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-triggers-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-reference-triggers-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-reference-triggers-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>triggers: [ (triggers reference)</summary>



<code>triggers</code>Optional<a href="#config-reference-triggers-workerconfig-triggers">Link to triggers</a>

<code>triggers?: Trigger[]</code>

Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with <code>triggers.fetch(...)</code>, <code>triggers.queue(...)</code>, <code>triggers.scheduled(...)</code>, <code>triggers.email(...)</code>, or <code>triggers.connect(...)</code>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#triggers">https://developers.cloudflare.com/workers/wrangler/configuration/#triggers</a>

</details>

<details>

<summary>triggers.fetch({ (fetch reference)</summary>



<code>fetch</code>Builder<a href="#config-reference-triggers-triggers-fetch-default">Link to fetch</a>

<code>fetch(options: FetchTriggerOptions): FetchTrigger;</code>

Fetch trigger — a route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>pattern: string</code></dt>
<dd>A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a></dd>

<dt><code>zone?: string</code></dt>
<dd>The DNS zone the pattern is attached to. Required when the pattern is ambiguous.</dd></dl></details>



</details>

<details>

<summary>pattern: "example.com/*", (pattern reference)</summary>



<code>pattern</code>Required<a href="#config-reference-triggers-triggers-fetch-default-pattern">Link to pattern</a>

<code>pattern: string</code>

A route that your Worker should be published to. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes">https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes</a>

</details>

<details>

<summary>zone: "example.com", (zone reference)</summary>



<code>zone</code>Optional<a href="#config-reference-triggers-triggers-fetch-default-zone">Link to zone</a>

<code>zone?: string</code>

The DNS zone the pattern is attached to. Required when the pattern is ambiguous.

</details>

}),

<details>

<summary>triggers.queue({ (queue reference)</summary>



<code>queue</code>Builder<a href="#config-reference-triggers-triggers-queue-default">Link to queue</a>

<code>queue(options: QueueConsumerTriggerOptions): QueueConsumerTrigger;</code>

Queue consumer trigger — invokes this Worker when messages arrive on the named queue. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#queues">https://developers.cloudflare.com/workers/wrangler/configuration/#queues</a>

<details>

<summary>Options (8)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the queue from which this consumer should consume.</dd>

<dt><code>deadLetterQueue?: string</code></dt>
<dd>The queue to send messages that failed to be consumed.</dd>

<dt><code>maxBatchSize?: number</code></dt>
<dd>The maximum number of messages per batch.</dd>

<dt><code>maxBatchTimeout?: number</code></dt>
<dd>The maximum number of seconds to wait to fill a batch with messages.</dd>

<dt><code>maxConcurrency?: number | null</code></dt>
<dd>The maximum number of concurrent consumer Worker invocations. Leaving this unset will allow your consumer to scale to the maximum concurrency needed to keep up with the message backlog.</dd>

<dt><code>maxRetries?: number</code></dt>
<dd>The maximum number of retries for each message.</dd>

<dt><code>retryDelay?: number</code></dt>
<dd>The number of seconds to wait before retrying a message.</dd>

<dt><code>visibilityTimeoutMs?: number</code></dt>
<dd>The number of milliseconds to wait for pulled messages to become visible again.</dd></dl></details>



</details>

<details>

<summary>name: "jobs", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-triggers-triggers-queue-default-name">Link to name</a>

<code>name: string</code>

The name of the queue from which this consumer should consume.

</details>

<details>

<summary>maxBatchSize: 20, (maxBatchSize reference)</summary>



<code>maxBatchSize</code>Optional<a href="#config-reference-triggers-triggers-queue-default-maxbatchsize">Link to maxBatchSize</a>

<code>maxBatchSize?: number</code>

The maximum number of messages per batch.

</details>

}),

<details>

<summary>triggers.scheduled({ (scheduled reference)</summary>



<code>scheduled</code>Builder<a href="#config-reference-triggers-triggers-scheduled-default">Link to scheduled</a>

<code>scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;</code>

Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>schedule: string</code></dt>
<dd>A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a></dd>

</dl></details>



</details>

<details>

<summary>schedule: "0 * * * *", (schedule reference)</summary>



<code>schedule</code>Required<a href="#config-reference-triggers-triggers-scheduled-default-schedule">Link to schedule</a>

<code>schedule: string</code>

A "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here <a href="https://developers.cloudflare.com/workers/platform/cron-triggers">https://developers.cloudflare.com/workers/platform/cron-triggers</a>

</details>

}),

<details>

<summary>triggers.email({ (email reference)</summary>



<code>email</code>Builder<a href="#config-reference-triggers-triggers-email-default">Link to email</a>

<code>email(options: EmailTriggerOptions): EmailTrigger;</code>

Email trigger — invokes this Worker for the configured Email Routing addresses.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>addresses: string[]</code></dt>
<dd>Inbound Email Routing addresses handled by this Worker. Each entry is a literal recipient address (e.g. <code>"support@example.com"</code>) or a <code>*@domain</code> catch-all (e.g. <code>"*@example.com"</code>).</dd>

</dl></details>



</details>

<details>

<summary>addresses: ["support@example.com"], (addresses reference)</summary>



<code>addresses</code>Required<a href="#config-reference-triggers-triggers-email-default-addresses">Link to addresses</a>

<code>addresses: string[]</code>

Inbound Email Routing addresses handled by this Worker. Each entry is a literal recipient address (e.g. <code>"support@example.com"</code>) or a <code>*@domain</code> catch-all (e.g. <code>"*@example.com"</code>).

</details>

}),

<details>

<summary>triggers.connect({ (connect reference)</summary>



<code>connect</code>Builder<a href="#config-reference-triggers-triggers-connect-default">Link to connect</a>

<code>connect(options: ConnectTriggerOptions): ConnectTrigger;</code>

Connect trigger — invokes this Worker's <code>connect(socket, env, ctx)</code> handler for raw socket connections received on the configured protocol/port.

<details>

<summary>Options (6)</summary>



<dl>

<dt><code>port: number</code></dt>
<dd>The port to listen on.</dd>

<dt><code>address?: string</code></dt>
<dd>The address to bind to. Defaults to <code>127.0.0.1</code>.</dd>

<dt><code>protocol: "tcp"</code></dt>
<dd></dd>

<dt><code>protocol: "udp"</code></dt>
<dd></dd>

<dt><code>idleTimeoutMs?: number</code></dt>
<dd>The idle timeout in milliseconds after which a peer flow is closed.</dd>

<dt><code>maxPendingBytes?: number</code></dt>
<dd>The maximum number of pending datagram bytes per peer flow.</dd></dl></details>



</details>

<details>

<summary>protocol: "tcp", (protocol reference)</summary>



<code>protocol</code>Required<a href="#config-reference-triggers-triggers-connect-default-protocol">Link to protocol</a>

<code>protocol: "tcp"</code>

The type definition does not include a description.

</details>

<details>

<summary>port: 5432, (port reference)</summary>



<code>port</code>Required<a href="#config-reference-triggers-triggers-connect-default-port">Link to port</a>

<code>port: number</code>

The port to listen on.

</details>

}),

],

},

});

### Exports

import { defineConfig, exports } from "cf/config";

import \* as entrypoint from "./src/index" with { type: "cf-worker" };

export default defineConfig({

<details>

<summary>worker: { (worker reference)</summary>



<code>worker</code>Optional<a href="#config-reference-exports-cloudflareconfig-worker">Link to worker</a>

<code>worker?: ConfigInput&lt;WorkerConfig&gt;</code>

The Worker defined by this configuration.

</details>

<details>

<summary>name: "export-showcase", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-exports-workerconfig-name">Link to name</a>

<code>name: string</code>

The name of your Worker.

</details>

<details>

<summary>entrypoint, (entrypoint reference)</summary>



<code>entrypoint</code>Optional<a href="#config-reference-exports-workerconfig-entrypoint">Link to entrypoint</a>

<code>entrypoint?: string | WorkerModule</code>

The entrypoint module that will be executed. May be either a path string (e.g. <code>"./src/index.ts"</code>) or a module namespace imported with the <code>cf-worker</code> import attribute.

</details>

<details>

<summary>compatibilityDate: "&lt;COMPATIBILITY_DATE&gt;", (compatibilityDate reference)</summary>



<code>compatibilityDate</code>Required<a href="#config-reference-exports-workerconfig-compatibilitydate">Link to compatibilityDate</a>

<code>compatibilityDate: string</code>

A date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates">https://developers.cloudflare.com/workers/configuration/compatibility-dates</a>

</details>

<details>

<summary>exports: { (exports reference)</summary>



<code>exports</code>Optional<a href="#config-reference-exports-workerconfig-exports">Link to exports</a>

<code>exports?: Record&lt;string, Export&gt;</code>

Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with <code>exports.durableObject(...)</code>. - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a>. For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>. - Construct entries with <code>exports.workflow(...)</code>. - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>.

</details>

<details>

<summary>LiveClass: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-exports-exports-durableobject-created">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectCreatedExportOptions&lt;TContainer&gt;): DurableObjectCreatedExport&lt;TContainer&gt;;</code>

Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at <a href="https://developers.cloudflare.com/workers/learning/using-durable-objects">https://developers.cloudflare.com/workers/learning/using-durable-objects</a> For reference, see <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects">https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects</a>

<details>

<summary>Options (4)</summary>



<dl>

<dt><code>state?: "created"</code></dt>
<dd></dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



</details>

<details>

<summary>storage: "sqlite", (storage reference)</summary>



<code>storage</code>Required<a href="#config-reference-exports-exports-durableobject-created-storage">Link to storage</a>

<code>storage: "sqlite"</code>

Selects the SQLite-backed storage engine (recommended for new classes).

</details>

}),

<details>

<summary>RemovedClass: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-exports-exports-durableobject-deleted">Link to durableObject</a>

<code>durableObject(options: DurableObjectDeletedExportOptions): DurableObjectDeletedExport;</code>

Retire a provisioned Durable Object namespace whose class has been removed from code.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>state: "deleted"</code></dt>
<dd></dd>

</dl></details>



</details>

<details>

<summary>state: "deleted", (state reference)</summary>



<code>state</code>Required<a href="#config-reference-exports-exports-durableobject-deleted-state">Link to state</a>

<code>state: "deleted"</code>

The type definition does not include a description.

</details>

}),

<details>

<summary>OldClass: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-exports-exports-durableobject-renamed">Link to durableObject</a>

<code>durableObject(options: DurableObjectRenamedExportOptions): DurableObjectRenamedExport;</code>

Rename a provisioned Durable Object namespace's class.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>state: "renamed"</code></dt>
<dd></dd>

<dt><code>renamedTo: string</code></dt>
<dd>The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.</dd></dl></details>



</details>

<details>

<summary>state: "renamed", (state reference)</summary>



<code>state</code>Required<a href="#config-reference-exports-exports-durableobject-renamed-state">Link to state</a>

<code>state: "renamed"</code>

The type definition does not include a description.

</details>

<details>

<summary>renamedTo: "NewClass", (renamedTo reference)</summary>



<code>renamedTo</code>Required<a href="#config-reference-exports-exports-durableobject-renamed-renamedto">Link to renamedTo</a>

<code>renamedTo: string</code>

The destination class name. Must be a valid JavaScript identifier and must appear as a live (<code>state: "created"</code>) <code>durableObject</code> entry in the same <code>exports</code> map.

</details>

}),

<details>

<summary>OutgoingClass: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-exports-exports-durableobject-transferred">Link to durableObject</a>

<code>durableObject(options: DurableObjectTransferredExportOptions): DurableObjectTransferredExport;</code>

Transfer ownership of a Durable Object namespace to another Worker in the same account.

<details>

<summary>Options (2)</summary>



<dl>

<dt><code>state: "transferred"</code></dt>
<dd></dd>

<dt><code>transferredTo: string</code></dt>
<dd>The destination Worker. Must reference a Worker in the same account.</dd></dl></details>



</details>

<details>

<summary>state: "transferred", (state reference)</summary>



<code>state</code>Required<a href="#config-reference-exports-exports-durableobject-transferred-state">Link to state</a>

<code>state: "transferred"</code>

The type definition does not include a description.

</details>

<details>

<summary>transferredTo: "target-worker", (transferredTo reference)</summary>



<code>transferredTo</code>Required<a href="#config-reference-exports-exports-durableobject-transferred-transferredto">Link to transferredTo</a>

<code>transferredTo: string</code>

The destination Worker. Must reference a Worker in the same account.

</details>

}),

<details>

<summary>IncomingClass: exports.durableObject({ (durableObject reference)</summary>



<code>durableObject</code>Builder<a href="#config-reference-exports-exports-durableobject-expecting-transfer">Link to durableObject</a>

<code>durableObject&lt;TContainer extends ContainerDefinition | undefined = undefined&gt;(options: DurableObjectExpectingTransferExportOptions&lt;TContainer&gt;): DurableObjectExpectingTransferExport&lt;TContainer&gt;;</code>

Prepare to receive cross-Worker Durable Object transfer. The source Worker must follow up with a deployment containing a <code>transferred</code> export to commit the transfer.

<details>

<summary>Options (5)</summary>



<dl>

<dt><code>state: "expecting-transfer"</code></dt>
<dd></dd>

<dt><code>transferFrom: string</code></dt>
<dd>The source Worker for the two-phase cross-Worker transfer.</dd>

<dt><code>storage: "sqlite"</code></dt>
<dd>Selects the SQLite-backed storage engine (recommended for new classes).</dd>

<dt><code>container?: TContainer</code></dt>
<dd>Attach a Container application to this Durable Object by config reference.</dd>

<dt><code>storage: "legacy-kv"</code></dt>
<dd>Selects the legacy key-value storage engine.</dd></dl></details>



</details>

<details>

<summary>state: "expecting-transfer", (state reference)</summary>



<code>state</code>Required<a href="#config-reference-exports-exports-durableobject-expecting-transfer-state">Link to state</a>

<code>state: "expecting-transfer"</code>

The type definition does not include a description.

</details>

<details>

<summary>storage: "sqlite", (storage reference)</summary>



<code>storage</code>Required<a href="#config-reference-exports-exports-durableobject-expecting-transfer-storage">Link to storage</a>

<code>storage: "sqlite"</code>

Selects the SQLite-backed storage engine (recommended for new classes).

</details>

<details>

<summary>transferFrom: "source-worker", (transferFrom reference)</summary>



<code>transferFrom</code>Required<a href="#config-reference-exports-exports-durableobject-expecting-transfer-transferfrom">Link to transferFrom</a>

<code>transferFrom: string</code>

The source Worker for the two-phase cross-Worker transfer.

</details>

}),

<details>

<summary>ApiEntrypoint: exports.worker({ (worker reference)</summary>



<code>worker</code>Builder<a href="#config-reference-exports-exports-worker-default">Link to worker</a>

<code>worker(options?: WorkerEntrypointExportOptions): WorkerEntrypointExport;</code>

Declares a WorkerEntrypoint export defined by this Worker.

<details>

<summary>Options (1)</summary>



<dl>

<dt><code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code></dt>
<dd></dd>

</dl></details>



</details>

<details>

<summary>cache: { (cache reference)</summary>



<code>cache</code>Optional<a href="#config-reference-exports-exports-worker-default-cache">Link to cache</a>

<code>cache?: { /** Whether cache is enabled for this entrypoint. */ enabled: boolean; }</code>

The type definition does not include a description.

</details>

<details>

<summary>enabled: true, (enabled reference)</summary>



<code>enabled</code>Required<a href="#config-reference-exports-exports-worker-default-cache-enabled">Link to enabled</a>

<code>enabled: boolean</code>

Whether cache is enabled for this entrypoint.

</details>

},

}),

<details>

<summary>CheckoutWorkflow: exports.workflow({ (workflow reference)</summary>



<code>workflow</code>Builder<a href="#config-reference-exports-exports-workflow-default">Link to workflow</a>

<code>workflow(options: WorkflowExportOptions): WorkflowExport;</code>

Declares a Workflow defined by this Worker. The export's key must name a class that extends <code>WorkflowEntrypoint</code>. For more information about Workflows, see the documentation at <a href="https://developers.cloudflare.com/workflows/">https://developers.cloudflare.com/workflows/</a>

<details>

<summary>Options (5)</summary>



<dl>

<dt><code>name: string</code></dt>
<dd>The name of the Workflow. It identifies the Workflow's instances and must be unique within the account.</dd>

<dt><code>limits?: { /** Maximum number of steps a single Workflow instance may run. */ steps?: number; }</code></dt>
<dd></dd>

<dt><code>concurrency?: { /** Maximum number of Workflow instances that can run concurrently. */ limit?: number; }</code></dt>
<dd></dd>

<dt><code>schedules?: string | string[]</code></dt>
<dd>Cron schedule(s) that automatically trigger Workflow instances.</dd>

<dt><code>defaultRetention?: { /** How long to retain instances that completed successfully or were terminated. */ successRetention?: number | string; /** How long to retain errored instances. */ errorRetention?: number | string; }</code></dt>
<dd>Default retention for instances of this Workflow, applied when an instance does not set its own retention. Accepts milliseconds or a duration string such as <code>"3 days"</code>.</dd>

</dl></details>



</details>

<details>

<summary>name: "checkout-workflow", (name reference)</summary>



<code>name</code>Required<a href="#config-reference-exports-exports-workflow-default-name">Link to name</a>

<code>name: string</code>

The name of the Workflow. It identifies the Workflow's instances and must be unique within the account.

</details>

<details>

<summary>limits: { (limits reference)</summary>



<code>limits</code>Optional<a href="#config-reference-exports-exports-workflow-default-limits">Link to limits</a>

<code>limits?: { /** Maximum number of steps a single Workflow instance may run. */ steps?: number; }</code>

The type definition does not include a description.

</details>

<details>

<summary>steps: 100, (steps reference)</summary>



<code>steps</code>Optional<a href="#config-reference-exports-exports-workflow-default-limits-steps">Link to steps</a>

<code>steps?: number</code>

Maximum number of steps a single Workflow instance may run.

</details>

},

}),

},

},

});

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/projects/config-explorer/#page","headline":"Configuration explorer","description":"See how cloudflare.config.ts describes each part of an application, and what each typed field means.","url":"https://developers.cloudflare.com/cf/projects/config-explorer/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/projects/config-explorer/og.png?v=8877be631a13b653","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Set up the Cloudflare CLI for coding agents, and help agents find, inspect, and safely run the right commands.
title: Use cf with coding agents
image: https://developers.cloudflare.com/cf/agents/og.png?v=99988aee6616b803
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Use cf with coding agents

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/agents/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Coding agents can use `cf` to work with your Cloudflare account. Commands return JSON and describe their own inputs, so an agent can find and run the right command without prior knowledge of `cf`.

## Set up `cf` for your agent

1. Install `cf` globally so every agent session can run it:npmyarnpnpmbun

   ```
   npm install --global cf
   ```

   ```
   yarn global add cf
   ```

   ```
   pnpm add --global cf
   ```

   ```
   bun add --global cf
   ```

   Inside a project that installs `cf` as a dependency, the global command runs the project's copy.
2. Sign in:

   ```sh
   cf auth login
   ```

   Sign-in opens a browser page where you approve access, so complete this step yourself. For agents that run without a person present, refer to [Authenticate unattended agents](#authenticate-unattended-agents).
3. Tell your agent to prefer `cf`. Add this instruction to your user-level `AGENTS.md`, `CLAUDE.md`, or equivalent instructions file:

   *AGENTS.mdmd*

   

   ```md
   When interacting with Cloudflare, use the `cf` CLI unless the project has a
   Wrangler configuration file.
   ```

   Projects that still use `wrangler.jsonc` or `wrangler.toml` keep working with Wrangler, while every other Cloudflare task goes through `cf`.

You can also ask your agent to do this setup for you:

```txt
Install the Cloudflare CLI with `npm install -g cf`. Then add this line to my
user-level AGENTS.md or CLAUDE.md file: "When interacting with Cloudflare, use
the cf CLI unless the project has a Wrangler configuration file."
```

## Help your agent find commands

`cf` has more than 2,900 commands. Instead of reading help for every product, an agent can describe the task, inspect the best match, and then run it.

1. Search for a command by describing the task:

   ```sh
   cf cli search "create D1 database"
   ```

   The search runs locally and needs no credentials. Put the task in quotes. `cf cli search` takes the whole task as one argument, and unquoted words after the first fail as unknown commands. It returns up to five matches as a JSON array, best match first. Each match has the command and a short summary. These are the first two matches for this search:

   ```json
   [
     {
       "command": "cf d1 create",
       "summary": "Create D1 Database"
     },
     {
       "command": "cf d1 update",
       "summary": "Update D1 Database"
     }
   ]
   ```


2. Inspect the API request of the chosen command:

   ```sh
   cf schema d1 create
   ```

   The JSON result describes the API request that the command sends: `operationId`, `httpMethod`, `path`, `pathParams`, `queryParams`, `hasRequestBody`, and `requestBodyFields`. Each parameter and body field lists its name, its type, and whether it is required. Body fields also include a description. `cf schema` covers generated API commands. For a command's arguments and options, or for a command such as `cf deploy`, run the command with `--help`.

   Path and query parameters use their API names, such as `account_id`. `requestBodyFields` lists the body fields that the command also accepts as options, under the option names. A field inside an object gets a combined name, such as `read-replication-mode` for `read_replication.mode`, and array fields show the type `string`. For some bodies, the list is incomplete or empty. For these commands, pass the complete body with `--body`, and check the API reference for its shape.
3. Preview the request with `--dry-run`, then run the command without it:

   ```sh
   cf d1 create --name my-database --dry-run
   ```



Root and group `--help` output starts with a reminder for agents to use `cf cli search` first. A command's own `--help` shows its usage as plain text. If an agent types a command that does not exist, `cf` lists the closest matches.

## Read command output

Results go to standard output as JSON. Messages, such as the selected zone, and errors go to standard error. When standard output is not a terminal, it contains only the result, so an agent can parse it or filter it with `jq` without extra flags.

- **Lists** print a JSON array and return one page. Paging options differ between commands, so check the command's `--help` output.
- **Changes that return no data** print nothing to standard output.
- **Raw content**, such as an R2 object or an image from a Workers AI model, goes to standard output unchanged. Redirect it to a file.
- **JSON output** is indented, whether or not standard output is a terminal. Colors are added only in a terminal.

A failed command exits with a non-zero status and prints the error to standard error.

## Run commands safely

- **Preview changes.** Add `--dry-run` to print the request as JSON without sending it. Dry runs need no credentials.
- **Check for aborted deletes.** In a non-interactive session, a destructive command without `--force` prints `Aborted.` to standard error and exits with status `0`. A successful exit does not mean the resource was deleted.
- **Review `--force` before you allow it.** On some commands, `--force` is also an API parameter. For example, `cf workers delete --force` also deletes a Worker that other Workers still reference.
- **Use local data where supported.** `--local` works only for a few resources that local development provides, mainly KV keys, D1 databases through `cf d1 raw`, `cf d1 migrations list`, and `cf d1 migrations apply`, and R2 objects. Commands without a local equivalent, including `cf d1 query`, return an error instead of calling the Cloudflare API.

For local state, refer to [Local resource data](https://developers.cloudflare.com/cf/projects/#local-resource-data).

## Work in Wrangler projects

Caution

Do not let an agent run `cf dev`, `cf build`, or `cf deploy` in a project that has a Wrangler configuration file but no `cloudflare.config.ts`. These commands can generate a new configuration that ignores `wrangler.jsonc`, or fail. Migrate the project first.

To migrate a project with an agent, ask it to:

1. Preview the migration without writing files:

   ```sh
   cf migrate --dry-run
   ```


2. Run the migration:

   ```sh
   cf migrate
   ```


3. Resolve the `TODO(@cloudflare)` comments in the generated `cloudflare.config.ts`, and ask you about any choice it cannot make on its own. The build fails until every required item is resolved.

For the full process, refer to [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/).

## Authenticate unattended agents

Agents that run without a person present, such as in continuous integration (CI), cannot complete `cf auth login`. Set `CLOUDFLARE_API_TOKEN` instead. The token takes priority over any stored login. For the variables, token permissions, and non-interactive behavior, refer to [Use cf in CI](https://developers.cloudflare.com/cf/ci/).

To give an agent separate credentials for one project on your own machine, bind a named profile to the project directory. Refer to [Use named profiles](https://developers.cloudflare.com/cf/get-started/#use-named-profiles).

## Inspect local resources

When `cf dev` runs inside a supported coding agent, the development server also prints the URL and main routes of the [Local Explorer API](https://developers.cloudflare.com/workers/local-development/local-explorer/#use-with-ai-agents). The agent can use this API to read and change the data in your Worker's local bindings, and to query local traces and logs.

## Related resources

- [Agent setup](https://developers.cloudflare.com/agent-setup/) configures Cloudflare Skills and MCP servers for popular coding agents.
- [Use cf in CI](https://developers.cloudflare.com/cf/ci/) covers API tokens and non-interactive behavior.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/agents/#page","headline":"Use cf with coding agents","description":"Set up the Cloudflare CLI for coding agents, and help agents find, inspect, and safely run the right commands.","url":"https://developers.cloudflare.com/cf/agents/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/agents/og.png?v=99988aee6616b803","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Run the Cloudflare CLI in continuous integration with an API token, predictable non-interactive behavior, and a build that you deploy once.
title: Use cf in CI
image: https://developers.cloudflare.com/cf/ci/og.png?v=2b4a9b1c37269f15
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Use cf in CI

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/ci/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Beta

`cf` is in beta. Commands, configuration, and Build Output can change before the stable release.

Run `cf` in continuous integration (CI) to check every pull request and deploy your Worker without a person present. In CI, `cf` authenticates with an API token and does not wait for input.

## Deploy from GitHub Actions

This workflow builds the project once for every pull request and every push to `main`. It checks the build with a dry run, and deploys the same build only on pushes to `main`.

1. Add `cf` as a development dependency, so every run uses the same release:npmyarnpnpmbun

   ```
   npm i -D cf
   ```

   ```
   yarn add -D cf
   ```

   ```
   pnpm add -D cf
   ```

   ```
   bun add -d cf
   ```

   Projects created with `cf init` or migrated with `cf migrate` already include it.
2. Commit `cloudflare.config.ts`. If the project does not have one yet, refer to [Commit the project configuration](#commit-the-project-configuration).
3. Add `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` as repository secrets. Grant the token only the permissions the workflow needs. To create a token, refer to [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/).
4. Add the workflow file:

   *.github/workflows/deploy.ymlyaml*

   

   ```yaml
   name: Deploy

   on:
     pull_request:
     push:
       branches: [main]

   jobs:
     deploy:
       runs-on: ubuntu-latest
       env:
         CF_SEND_TELEMETRY: "false"
       steps:
         - uses: actions/checkout@v6
         - uses: actions/setup-node@v6
           with:
             node-version: 22
             cache: npm
         - run: npm ci
         - run: npx cf build
         - run: npx cf deploy --prebuilt --mode production --dry-run
         - if: github.event_name == 'push'
           run: npx cf deploy --prebuilt --mode production
           env:
             CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
             CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
   ```



The workflow assumes a project created with `cf init`, with `package-lock.json` committed. Only the final deploy step receives secrets, so the pull request steps also work for pull requests from forks. If you pass another `--mode` to `cf build`, use the same mode in both deploy steps. The following sections explain each part.

## Provide credentials

`cf auth login` needs a person to approve access in a browser. In CI, set these environment variables instead:

| Variable | Purpose |
| --- | --- |
| `CLOUDFLARE_API_TOKEN` | Authenticates API requests. Takes priority over any stored login. |
| `CLOUDFLARE_ACCOUNT_ID` | Selects the account. Without it, `cf` uses `accountId` from `cloudflare.config.ts`, then an account saved by an earlier run in the same checkout, then the only account available. |
| `CLOUDFLARE_ZONE_ID` | Selects a zone for zone-level commands when you do not pass `--zone`. |

If the token can access more than one account and no account is set or saved, the command fails instead of prompting:

```txt
More than one account available but unable to select one in non-interactive mode.
Please set the appropriate `account_id` in your cf config file or assign it to the `CLOUDFLARE_ACCOUNT_ID` environment variable.
Available accounts are (`<name>`: `<account_id>`):
  `(redacted)`: `<ACCOUNT_ID>`
```

In CI, `cf` replaces account names with `(redacted)`. To fix the error, set `CLOUDFLARE_ACCOUNT_ID`, or add `accountId` to the default export in `cloudflare.config.ts`.

### Use a `.env` file for local automation

For scripts on your own machine, `cf` commands that call the Cloudflare API can also read these variables from a `.env` file in the current directory. They do not read `.env.local`. Variables already set in the environment take priority. For details, refer to [Load credentials from a .env file](https://developers.cloudflare.com/cf/get-started/#load-credentials-from-a-env-file).

Caution

Do not commit a `.env` file that contains API tokens. Add it to `.gitignore`.

## Pin the `cf` version

With `cf` installed as a development dependency, `npx cf <COMMAND>` runs the project's copy. On a developer's machine, a globally installed `cf` also hands each command to the project's copy. Collaborators, coding agents, and CI then run the same version. One-off runs such as `npx cf@<VERSION>` are not handed off.

Use Node.js 22.18 or later. For details, refer to [Requirements](https://developers.cloudflare.com/cf/get-started/#requirements).

## Understand non-interactive behavior

`cf` treats a run as non-interactive when it has no terminal, or when it detects a CI environment, for example through the `CI` environment variable. In a non-interactive run:

- **Prompts** use their default answer. Prompts without a default fail, so pass the value as an option instead.
- **Destructive commands** abort without `--force`. They print `Aborted.` to standard error, make no change, and exit with status `0`.
- **`cf init`** needs a directory, such as `cf init my-worker` or `cf init .`. A new project uses the package manager that started `cf`, or npm. Pass `--package-manager` to choose another.

Before you pass `--force` in a job, read the command's `--help` output. On some commands, `--force` is also an API parameter.

### Commit the project configuration

In a project without `cloudflare.config.ts`, every command that builds runs automatic configuration first. In CI, automatic configuration accepts the detected settings, installs packages, and edits project files without asking.

To avoid unreviewed changes, run `cf init .` on your own machine. Review the result, and commit `cloudflare.config.ts` with the other changes. For what automatic configuration changes, refer to [Automatic configuration](https://developers.cloudflare.com/cf/projects/#automatic-configuration).

Caution

Automatic configuration does not read Wrangler configuration files. In a Wrangler project, run `cf migrate` before you use `cf` in CI. Refer to [Migrate a Wrangler project](https://developers.cloudflare.com/cf/wrangler/migrate/).

## Build once, then deploy the build

To deploy exactly what an earlier step built, build the project once:

npmyarnpnpm

```
npx cf build
```

```
yarn cf build
```

```
pnpm cf build
```

Then deploy that build with `--prebuilt` and the mode it recorded:

npmyarnpnpm

```
npx cf deploy --prebuilt --mode production
```

```
yarn cf deploy --prebuilt --mode production
```

```
pnpm cf deploy --prebuilt --mode production
```

`--prebuilt` skips the build and automatic configuration, and uses the Build Output in `.cloudflare/output`. Vite builds record `production` unless you pass `--mode`. If you build with `--mode staging`, deploy with `--mode staging`. When the modes do not match, the deploy stops before it uploads anything and prints the mode to use.

If the Build Output contains more than one Worker, `cf` deploys the default Worker unless you pass `--worker <NAME>`. For the full rules, refer to [Deploy a prebuilt build](https://developers.cloudflare.com/cf/projects/#deploy-a-prebuilt-build).

## Check pull requests with a dry run

`cf deploy --dry-run` builds the project and validates the result without uploading it or sending API requests. It needs no credentials, so it also works for pull requests from forks, where CI secrets are not available.

npmyarnpnpm

```
npx cf deploy --dry-run
```

```
yarn cf deploy --dry-run
```

```
pnpm cf deploy --dry-run
```

To check a build from an earlier step instead, add `--prebuilt` and the recorded `--mode`, as the example workflow does.

## Deploy previews from CI

`cf previews deploy` builds the project and deploys a Worker Preview. It needs credentials and has no `--dry-run` option.

npmyarnpnpm

```
npx cf previews deploy
```

```
yarn cf previews deploy
```

```
pnpm cf previews deploy
```

The preview name defaults to the current branch. In GitHub Actions, `cf` reads `GITHUB_HEAD_REF` or `GITHUB_REF_NAME`. In GitLab CI/CD, it reads `CI_COMMIT_REF_NAME`. Otherwise, it uses the current Git branch. On a detached checkout without these variables, pass the preview name as an argument. For the output and options, refer to [Deploy a preview](https://developers.cloudflare.com/cf/projects/#deploy-a-preview).

## Turn off telemetry

`cf` sends anonymous usage telemetry, which records whether it runs in CI. To turn it off for a job, set `CF_SEND_TELEMETRY=false` or `DO_NOT_TRACK=1` in the job environment. `cf` does not check npm for updates in CI.

## Related resources

- [Develop, build, and deploy](https://developers.cloudflare.com/cf/projects/) describes the project commands.
- [Use cf with coding agents](https://developers.cloudflare.com/cf/agents/) covers command discovery and safe operation.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/ci/#page","headline":"Use cf in CI","description":"Run the Cloudflare CLI in continuous integration with an API token, predictable non-interactive behavior, and a build that you deploy once.","url":"https://developers.cloudflare.com/cf/ci/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/ci/og.png?v=2b4a9b1c37269f15","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Reference the environment variables that control Cloudflare CLI authentication, targeting, output, and telemetry.
title: Environment variables
image: https://developers.cloudflare.com/cf/environment-variables/og.png?v=c831fa19535da6e6
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cf/llms.txt  
> Use this file to discover all available pages before exploring further.

# Environment variables

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cf/environment-variables/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Set these variables in the environment that runs `cf`. They configure the CLI, not the environment variables or secrets available to a deployed Worker. If a variable is unset, `cf` uses the behavior in the Default column.

## Supported variables

The following variables control `cf` behavior:

| Variable | Default | Effect |
| --- | --- | --- |
| `CF_FORCE_OSC_PROGRESS` | Unset; only recognized terminals show progress outside the terminal buffer. | Set to `1` to enable terminal progress in an unrecognized compatible terminal. Requires a terminal on standard error. |
| `CF_NO_OSC_PROGRESS` | Unset; supported terminals show progress. | Set to `1` to turn off progress in the terminal tab title or taskbar. |
| `CF_QUIET` | Unset; interactive progress is shown. | Set to `1` to suppress animated API progress and terminal progress. It does not suppress command results. |
| `CF_SEND_TELEMETRY` | Unset; a saved preference or the default applies. | Set to `true` or `1` to enable anonymous CLI usage telemetry, or `false` or `0` to disable it. Takes precedence over `WRANGLER_SEND_METRICS`, but not `DO_NOT_TRACK`. |
| `CI` | Unset; `cf` also detects CI providers and the absence of a terminal. | Set to `true` in CI to avoid interactive prompts. Prompts use defaults or fail when an answer is required. |
| `CLOUDFLARE_ACCESS_CLIENT_ID` | Unset; no Access service-token client ID is supplied. | Identifies the service token used to connect to Access-protected Workers. Set it with `CLOUDFLARE_ACCESS_CLIENT_SECRET`. |
| `CLOUDFLARE_ACCESS_CLIENT_SECRET` | Unset; no Access service-token secret is supplied. | Supplies the secret for the Access service token. Set it with `CLOUDFLARE_ACCESS_CLIENT_ID`. |
| `CLOUDFLARE_ACCOUNT_ID` | Unset; `cf` uses project configuration, a saved selection, or an accessible account. | Selects the account for account-scoped commands. Overrides `accountId` in `cloudflare.config.ts`. |
| `CLOUDFLARE_API_BASE_URL` | The Cloudflare API endpoint for the selected compliance region. | Overrides the API endpoint. Only point it at an endpoint you trust because API requests carry credentials. |
| `CLOUDFLARE_API_TOKEN` | Unset; `cf` uses the selected OAuth profile. | Authenticates API commands with this token instead of a saved profile. Use it for CI and other automation. |
| `CLOUDFLARE_COMPLIANCE_REGION` | `public`, unless set in `cloudflare.config.ts`. | Selects the API compliance region and overrides the project configuration. Accepts `public`, `fedramp_high`, or `fedramp-high`. |
| `CLOUDFLARE_REGISTRY_PATH` | The `registry` directory in the `cf` configuration directory. | Sets the local development registry path shared with Wrangler and Miniflare processes started by `cf`. |
| `CLOUDFLARE_ZONE_ID` | Unset; zone-scoped commands need a zone. | Supplies a default zone ID or domain name. The `--zone` or `-z` option takes precedence. |
| `DEBUG` | Unset; normal diagnostics are shown. | Set to a nonempty value to show additional diagnostics, including error stack traces and delegated command details. |
| `DO_NOT_TRACK` | Unset; telemetry follows the other settings. | Set to `1` to disable CLI telemetry, even if `CF_SEND_TELEMETRY` enables it. |
| `FORCE_COLOR` | Unset; color is used when standard output is a terminal. | Set to a value other than `0` to enable styled output without a terminal. `NO_COLOR` takes precedence. |
| `NO_COLOR` | Unset; color is used when standard output is a terminal. | Set to any value to disable styled output and animated API progress. |
| `TUNNEL_MANAGEMENT_TOKEN` | Unset; `cf tunnels tail` requests a token for the specified tunnel ID. | Supplies an existing management token to `cf tunnels tail`. Do not pass a tunnel ID when this is set. |
| `WRANGLER_SEND_METRICS` | Unset; `cf` uses its saved telemetry preference or enables telemetry. | Sets CLI telemetry when `CF_SEND_TELEMETRY` is not set. Accepts `true`, `false`, `1`, or `0`. |

`cf` loads only selected authentication and context variables from a project `.env` file. Other variables in this table must be set in the process environment. For the supported file variables, precedence, and security guidance, refer to [Load credentials from a .env file](https://developers.cloudflare.com/cf/get-started/#load-credentials-from-a-env-file).

For more on API tokens and account selection, refer to [Install and sign in](https://developers.cloudflare.com/cf/get-started/). For telemetry settings in CI, refer to [Use cf in CI](https://developers.cloudflare.com/cf/ci/#turn-off-telemetry).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cf/environment-variables/#page","headline":"Environment variables","description":"Reference the environment variables that control Cloudflare CLI authentication, targeting, output, and telemetry.","url":"https://developers.cloudflare.com/cf/environment-variables/","inLanguage":"en","image":"https://developers.cloudflare.com/cf/environment-variables/og.png?v=c831fa19535da6e6","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
