Cloudflare 新命令行 cf:为 Agent 重做的一套工具
Cloudflare 把整个 API 的 3000 多个操作搬进命令行,输出默认 JSON、配置改用 TypeScript,第一用户从人换成 Agent。
Cloudflare 的命令行工具 Wrangler,用户正在变成 Agent。Cloudflare 自己给的数字:今年早些时候,Agent 已占 Wrangler 使用量的四分之一,一年前还只是个位数百分比;上周这个比例到了 48%。
而且 Agent 比人用得更狠:每天用到的不同命令数差不多是人的两倍,一次用到六个以上命令的概率接近人的四倍。
整个网络的流量也在往同一个方向走。下面是 Cloudflare Radar(Cloudflare 公开的网络流量统计页面)的截图:网页(HTML)请求里,机器发出的占 57.5%,人只占 42.5%;再看所有响应的内容类型,JSON 占 33.1%,比 HTML 的 12% 高出不少。这里的“机器”指所有自动化程序,AI Agent 只是其中一部分,所以它不能直接当成 Agent 的占比,但能说明机器读的数据格式已经比网页还常见。
回到 Cloudflare 自己的工具:Wrangler 只覆盖大约 280 个操作,而 Cloudflare 一共有几千个操作。Agent 能调用的 Cloudflare 功能,因此被 Wrangler 的命令清单卡住了。所以 Cloudflare 做了一个新的命令行工具 cf,目标是把整个 Cloudflare API 都搬进命令行,并且整套设计都以 Agent 为第一用户。目前是开放测试版,用 npm i -g cf 安装。
下面按 Agent 用起来会卡在哪,讲 cf 的四个改动。
一个工具,能做 Cloudflare 上的所有事
先看 Wrangler 为什么停在 280 个。它是各个产品团队各自手写的:同样是查看一个资源的信息,有的叫 d1 info,有的叫 hyperdrive get,有的叫 workflows describe;有些团队写了几千行定制体验,结果几乎没人用。团队多了,命令风格很难统一。
cf 换了一种做法:不再手写命令,而是从 API 的 OpenAPI 规范(描述每个接口有哪些参数的标准文档)直接生成。Cloudflare 每个 API 本来就有这份规范,用来生成 API 文档和各语言 SDK;在规范里多标注一点信息,一条叫 Forge 的统一生成流水线就能顺带产出命令行命令。结果是命令从大约 280 个扩到覆盖 3000 多个 API 操作。
对使用者最直接的变化是:你可以让 Agent 用同一个工具,连着做完“建一个 Worker(Cloudflare 上跑的一小段服务端代码)、部署、监控、用 Cloudflare Access 保护起来、买一个域名、前面再挂 WAF(网站防火墙)”这一串事,中间不用换工具,也不用你去控制台点。
输出默认是 JSON,不是给人看的表格
Agent 用 Wrangler 时,几乎每条命令都会自己加上 --json,再用 jq(命令行里筛选 JSON 字段的小工具)只取需要的几项。但 Wrangler 只有一部分命令支持 --json,其余命令输出的是为人排版的表格。Agent 也能读懂表格,只是比用一条 jq 更费时间、更费 token。
--json 报“未知参数”,去掉后输出给人看的表格;再是 cf,默认输出 JSON,接一条 jq 就取出需要的字段。cf 直接反过来:JSON 是默认输出。给人看时会排版美化,给 Agent 看时压缩掉多余空白,省上下文。Cloudflare 的判断是,这个工具大多数命令人很少直接碰,你真正的用法是让 Agent 先筛选结果,再按你要的格式汇报,给你一张你根本不会细看的表格没有意义。
但有些事确实需要人来定,比如搜一个域名并购买。这类命令如果用一长串命名参数拼出来很难写,cf 把 API 的要求拆成一组带校验的输入,让人像填表单一样一步步填。
你也可以直接让 Agent 代办;演示里加上 --force,命令就跳过确认,直接返回 JSON 结果。
--force,不再询问确认,直接返回 JSON 结果。3000 个命令,Agent 怎么找到要用的那一个
命令一多,光把命令清单塞给 Agent 就会撑爆上下文。cf 加了一个 cf cli search:Agent 用自然语言说出想做什么,一个小型搜索索引会根据每个命令的 API 描述和参数,返回匹配的命令列表。Agent 第一次运行 --help 时,cf 会自动告诉它有这个命令可用,不用你在提示词里交代。
cf cli search 描述要做的事(例如“查看队列里卡住的消息”),再运行匹配到的命令 cf queues messages peek。配置文件改成 TypeScript,编辑器会替 Agent 纠错
Wrangler 用 TOML 或 JSONC 写配置。Cloudflare 的观察是:TOML 没有可访问的规范,JSONC 虽然可以链接一份规范,Agent 很少去看。cf 的新配置文件叫 cloudflare.config.ts,用 TypeScript 写。好处是,用了 LSP(语言服务协议,编辑器据此提供补全和报错)插件的 Agent,比如 Claude Code 和 Codex,可以直接读到每个字段是什么、能填什么,给出的修改更准。Cloudflare 说,即使 Agent 事先没见过这个格式,也能顺利找到并修改配置,包括 env 这种和 Wrangler 里同名但含义已大幅变化的部分。
还有一个副作用:配置可以用代码生成。Cloudflare 内部有些 Wrangler 配置文件原本超过 5000 行,里面为每个开发者复制了很多份自定义环境;改成从同一个基础配置按环境生成后,缩短了 40%。一个多环境的 Worker,只需要根据 Vite 自带的 mode 参数切换两套配置:
import { bindings, defineConfig } from "cf/config";
import * as entrypoint from "./index.js" with { type: "cf-worker" };
export default defineConfig(({ mode }) => ({
worker: {
name: "example-worker",
entrypoint,
compatibilityDate: "2026-09-27",
env: {
Environment: bindings.text(`This is ${mode} environment`),
},
},
}));
bindings 是 Worker 能连接的东西(环境变量、密钥、KV 缓存、D1 数据库、R2 存储、队列、AI、向量库、另一个 Worker)的统一入口,编辑器可以自动补全并解释每一项,等于给 Agent 一份可以直接查的清单:
env: {
API_URL: bindings.text(
mode === "production" ? "https://example.com" : "https://staging.example.com",
),
API_TOKEN: bindings.secret(),
CACHE: bindings.kv({ id: mode === "production" ? "production-namespace-id" : "staging-namespace-id" }),
DATABASE: bindings.d1({ name: `example-${mode}-database` }),
UPLOADS: bindings.r2({ name: `example-${mode}-uploads` }),
AI: bindings.ai(),
// 还有 queue、vectorize、worker 等
}
triggers 则把“什么会让这个 Worker 跑起来”集中到一处:网页请求、定时任务、队列消息、收到邮件,以前散在配置文件各处,现在写在同一个块里:
triggers: [
triggers.fetch({ pattern: "example.com/*" }),
triggers.scheduled({ schedule: "0 * * * *" }),
triggers.queue({ name: "jobs", maxBatchSize: 10 }),
triggers.email({ addresses: ["你的收件邮箱"] }),
],
现在这份配置只支持 Worker,官方的计划是让它管理整个 Cloudflare:接下来会加策略、域名区域(zone)、DNS 等,全部用同一种带类型的配置来写。
本地开发默认换成 Vite
Wrangler 诞生时 Vite 还不存在,所以它用 esbuild 打包,本地开发服务器(默认在 8787 端口)也是自己写的,想改就得深入 Miniflare(Cloudflare 的本地运行环境)内部。现在 Vite 生态成熟,有大量插件和带热更新(HMR,改代码后页面自动刷新)的开发服务器,打包用 Rust 写的 Rolldown 做 tree-shaking(剔除没用到的代码)。cf 默认建立在 Vite 和 Cloudflare Vite 插件之上,配合 Vitest 插件做测试,得到和 Workers 线上运行环境一致的开发测试环境。
Cloudflare 说,大多数 Worker 可以很顺利地让 Agent 帮你迁过去。但不是所有项目都能马上搬:仍然依赖 esbuild 的 JavaScript Worker,以及 Rust 和 Python 写的 Worker,cf 会继续把开发和部署交给 Wrangler 处理。
从 Wrangler 迁移
已有的 Worker,运行 cf migrate 即可:已经用 Vite 构建的,会被转换成 cloudflare.config.ts;还靠 Wrangler 跑 esbuild 的,构建仍交给 Wrangler。新项目用 cf init 起步,cf init 和 cf deploy 会替你装好 Cloudflare Vite 插件并生成配置文件;静态网站依旧不需要配置文件,在项目里运行 cf deploy 就能部署。
时间表方面:开放测试结束后,Cloudflare 会发布 Wrangler 的最后一个大版本,它会引导你和你的 Agent 改用 cf,之后 Wrangler 再维护 18 个月,给大家留出迁移时间。cf 本身是开源的,问题可以提到 GitHub 的 cloudflare/cf 仓库。
为什么不给 Wrangler 打补丁,而是换新工具
这里有个反直觉的点。Wrangler 有多年文档、博客和第三方教程被大模型学进去,Agent 对它已经很熟;换一个 Agent 没见过的新工具,听上去更容易出错。Cloudflare 的看法是恰恰相反:要在旧工具里做这么大的改动,就得让 Agent 忘掉学过的旧用法,比如同名的 env 含义变了;而全新的工具反而干净,官方可以靠设计上的取舍、能注入的上下文和可追加的 AGENTS.md 文件(项目里写给 Agent 看的说明),把新用法直接教给 Agent。这类给 Agent 的引导,官方说目前只做了几项,后续还会增加;其中让 Agent 自己找命令的办法,官方认为以后会成为更多命令行工具的标配。
该怎么看
这篇讲的不只是 Cloudflare 多了一个命令行,而是一个更大的转向:工具的主要用户从人变成 Agent 后,产品设计的默认值都要反过来。 输出格式默认给机器,找命令靠搜索而不是背,配置要让编辑器能检查,旧习惯不惜断代。如果你在做面向 Agent 的工具或 API,这四点可以直接对照。
两点要注意:开头的 48% 是 Cloudflare 统计的 Wrangler 使用量里 Agent 的占比,不代表所有开发者;cf 目前是开放测试版,配置格式现在只支持 Worker,DNS、策略等其余产品的配置还在计划中。
工具的第一用户,换成了 Agent
Cloudflare 原来的命令行工具 Wrangler,上周有 48% 的使用来自 AI Agent。它干脆重做了一个以 Agent 为第一用户的新工具:cf。
为什么要重做:Agent 用得更重,却被命令清单卡住
Wrangler 是 Cloudflare 让开发者在终端里部署和管理服务的工具。今年早些时候 Agent 占了它使用量的四分之一,一年前还只是个位数百分比;Agent 用得也比人更重,每天用到的不同命令数约是人的两倍。可 Wrangler 只覆盖约 280 个操作,Cloudflare 一共有几千个操作,Agent 想做的事常常没有对应命令。
cf 在四处做法上反了过来
四处改动都是按 Agent 的使用方式设计的。
Cloudflare 内部有些配置文件靠代码按环境生成,从 5000 多行缩短了 40%。
为什么不直接改 Wrangler?Cloudflare 的看法是:Wrangler 的旧用法已经被大模型学进训练数据,大改反而要 Agent 忘掉旧习惯;全新的工具更干净,可以靠设计、注入的上下文和项目里的 AGENTS.md 把新用法直接教给 Agent。
要不要现在迁?
依据 Cloudflare 官方博客《Introducing cf: the agentic CLI for the entire Cloudflare API》与本站解读整理。上面的 48% 是 Wrangler 使用量里的占比,不代表所有开发者。
Introducing cf: the agentic CLI for the entire Cloudflare API
We are releasing cf, our new command-line tool that mirrors the entire Cloudflare API and supports programmatic TypeScript configuration. We are also open-sourcing Forge, our internal SDK generator.
Over the last year, agent use of Wrangler has skyrocketed.
In March 2026, agents were responsible for a quarter of Wrangler use, up from single-digit percentages the year prior. Last week, agent usage reached 48%.
Agents are more prolific users, using almost twice as many distinct commands per day, and are almost four times as likely to use six or more commands.
Agents love CLIs. But Wrangler only provides commands for around 280 operations, and Cloudflare offers thousands.
Earlier in the year we teased how we were planning to solve this and today, we’re enabling agents to use every Cloudflare product by introducing a new CLI: cf.
cf is a CLI that is built for the next generation of software development:
- Agents can find the command they need to do anything they want to do with bespoke search and steering.
- JSON is the default interface, pretty printed for humans and condensed for agents for maximum context savings.
- cloudflare.config.ts is the new configuration format for the whole of Cloudflare, starting with Workers, and bringing the safety and accuracy of TypeScript to you and your agent’s language server protocol (LSP)
- Vite becomes default, bringing with it the best local development server, and a plugin suite for developers and framework authors.
Install the open beta today globally and run it from anywhere:
npm i -g cfcf gives your agent access to the entire Cloudflare API
What if your agent could do everything Cloudflare can do? That’s the question that sparked our interest earlier this year: agents were getting ever more powerful, but what they were able to do with Cloudflare’s CLI was still limited.
Wrangler was hand-built with each product team contributing and taking their own approach to their command developer experience. Enforcing patterns across teams was virtually impossible, even across our ~280 command paths. We had inconsistent terminology across d1 info, hyperdrive get, workflows describe as each team came up with their own practices at different times. Some teams built entirely custom experiences across thousands of lines of code that turned out to be used extremely rarely, and teams came up with different approaches to solve the same problems.
We wanted to both standardize what we had and make a massive expansion, all at once. Forge — Cloudflare’s new unified API generation pipeline — enabled us to do this, building on the idea of generating our CLI commands directly from the API schema that powers our API documentation and SDK generation. Everything we provide has an OpenAPI schema, and if we annotate this with just a little more information, we can use it as the source for Forge to make a CLI.
This enables us to expand cf from the ~280 functions that Wrangler had built up over time, to cover the entirety of the Cloudflare API surface of over 3,000 operations.
Now it’s simple to give your agent cf and ask it to go set up a worker, deploy it, monitor and observe it, protect it with Cloudflare Access, buy a domain, and front it with Cloudflare WAF, all from a single tool.
Building for an agent that has never used cf
cf is built for the trajectory of software engineering, where agentic development is drastically changing how software is built and deployed. This year we’ve been focused on providing tools to support this shift, culminating in cf. cf has been built from the ground up with agents in mind, and includes novel tools for agentic command discovery that we think will become standard in more CLIs in the near future.
Wrangler came with the advantage that years of documentation, blogs, and third-party guides have been absorbed into the training process of LLMs. It also came with the same disadvantage: changing how Wrangler works now goes against learned behavior, and significant change would be inevitable given the scale of improvement we want to make.
Introducing a new CLI that agents have never seen sounds like a big disruptive change — but actually it’s the cleanest thing we can do. Because of the design decisions we have made, the context injections we can make, and the AGENTS.md files we can append, making a switch in this way is actually less confusing than having an agent contextualize the major differences between two versions of a tool it is familiar with. We’re launching with a couple of these agent-focused features built in, with more to come.
Agents need to filter JSON, not look at tables
When agents use Wrangler, they append --json to every command they run, and then often filter the output with jq to extract a subset of fields. But only some commands in Wrangler supported --json ; many commands returned unicode tables, designed for humans looking at output in their terminal. Agents can figure these out, but it costs them more time and tokens than a jq filter.
In cf we’re taking the opposite stance: agents just need JSON, and if agents are the future primary user of this tool, it should be the default. For the vast majority of commands that will rarely be accessed by humans, this is obviously the right call.
You as the human customer of this CLI are, in reality, one step removed from using it. Agents being able to easily filter their results and then return that filtered list in whatever format you request is preferable to supplying tables you will never likely read directly.
But what if you’re looking to do something that might require real personal input, like searching for a domain to buy?
For commands that your agent can access through chaining named parameters in a long and unwieldy sequence, you can simply fill in a form. Cf deconstructs the requirements of the API into a series of validated inputs, so buying a domain, even one with complex requirements, is simple to follow.
Or, if you insist, just ask your agent to do it.
Your agent can find the right command itself
With 3,000 possible routes through a CLI, how can your agent find the right operation it needs quickly without bloating your context? For this reason we have also added cf cli search.
This command allows your agent to ask in natural language what it needs to do, and a small search index will provide a list of appropriate commands, based on their API description and parameters. We automatically tell your agent about this command when it runs --help for the first time.
Configuration that type-checks your agent
Our new configuration format is based on TypeScript, which is easy for humans and agents to parse, and allows you to write your configuration programmatically.
Typed configuration is enormously helpful for agents. We’ve found that even with no prior context of the programmatic configuration format, agents are able to easily identify and edit the configuration on demand, even across elements like env which have dramatically changed from the same named feature in Wrangler. All agents that use LSP plugins, such as Claude Code and Codex, benefit from being able to interpret more about the configuration file format in context, and make much more accurate suggestions as a result.
Compare this to TOML, which had no accessible schema, or JSONC, which had a linked schema that agents rarely used.
Some Wrangler configuration files inside Cloudflare have been condensed by 40% from over 5,000 lines, with many custom environments per developer, to factory files that build each developer’s configuration more efficiently.
This is achieved through programmatically defining each environment from the same universal base, instead of copying env blocks as was typical in Wrangler. A simple Worker with multiple environments simply switches on the Vite-native mode argument to swap between one set of configuration and another.
A simple configuration that does this now looks like:
import { bindings, defineConfig } from "cf/config";
import * as entrypoint from "./index.js" with { type: "cf-worker" };
export default defineConfig(({ mode }) => ({
worker: {
name: "example-worker",
entrypoint,
compatibilityDate: "2026-09-27",
env: {
Environment: bindings.text(`This is ${mode} environment`),
},
},
}));You can migrate your Cloudflare Worker to this new format through cf migrate.
We’re also providing a few helper functions to make building your Worker a breeze.
bindings gives you a simple place for your agent to discover all the developer platform has to offer. Everything — from environment variables to storage, database, and queues — can be auto-completed and explained by your editor.
import { bindings, defineConfig } from "cf/config";
export default defineConfig(({ mode }) => ({
worker: {
// ...
env: {
API_URL: bindings.text(
mode === "production"
? "https://example.com"
: "https://staging.example.com",
),
API_TOKEN: bindings.secret(),
CACHE: bindings.kv({
id: mode === "production"
? "production-namespace-id"
: "staging-namespace-id",
}),
DATABASE: bindings.d1({ name: `example-${mode}-database` }),
UPLOADS: bindings.r2({ name: `example-${mode}-uploads` }),
JOBS: bindings.queue < { userId: string } > ({
name: `example-${mode}-jobs`,
}),
AI: bindings.ai(),
SEARCH_INDEX: bindings.vectorize({
name: `example-${mode}-search`,
}),
API: bindings.worker({ worker: `example-${mode}-api` }),
},
},
}));Similarly, we have included a helper for triggers, which is the new way to define routes, queues, schedules, and email triggers for your Worker. Rather than having these scattered through your configuration file, it’s now simple to find, in a single block, the actions that could trigger your Worker to run.
import { defineConfig, triggers } from "cf/config";
export default defineConfig({
worker: {
// ...
triggers: [
triggers.fetch({ pattern: "example.com/*" }),
triggers.scheduled({ schedule: "0 * * * *" }),
triggers.queue({ name: "jobs", maxBatchSize: 10 }),
triggers.email({ addresses: ["support@example.com"] }),
],
},
});defineConfig.worker is just the start here. Our intention with cloudflare.config.ts is that this is how you manage Cloudflare as a whole. Every product you need — along with its API being available to your agent through cf — will be able to be expressed through typesafe configuration. Soon you will be able to configure entire policies, set up zones, configure DNS and more, all through this configuration file.
A best in class development experience
When Wrangler first started building JavaScript Workers, Vite didn’t exist. Instead, we used esbuild in Wrangler to bundle your Workers. The dev server that Wrangler made available on :8787 was something that the Wrangler team built, and modifying any of this meant reaching into the internals of Cloudflare-specific local tooling like Miniflare.
Vite is a huge improvement on this, and comes with a large ecosystem of plugins you can use, as well as providing a best in class dev server with HMR (hot module replacement), and builds that use the Rust-based library Rolldown for tree-shaking. Anything you can do with Vite, you can do with the Cloudflare Vite Plugin.
The Cloudflare Vite Plugin is the recommended way we suggest you build Workers, whatever you are building: whether that’s a frontend-focused project or a backend API. Together with our Vitest plugin it provides a cohesive development and testing environment that matches the Workers runtime and gives you direct access to bindings and platform APIs.
cf is built on Vite as default. Most of your Workers will migrate simply with agents. Others may take more time, which is why cf will continue to delegate to Wrangler for dev and deployment for JavaScript Workers that need to continue to use esbuild and Rust and Python Workers.
Migrating from Wrangler
Migrating a Worker from Wrangler is as simple as running
cf migrateWorkers that already build with Vite will be converted to cloudflare.config.ts for you. If your Worker relies on Wrangler for esbuild, then cf will continue to delegate builds to Wrangler.
When the open beta ends we will release a final major version of Wrangler that directs you and your agent to use cf. We’ll continue to provide maintenance support for Wrangler for 18 months after the beta ends, to give you time to migrate.
You can also take new projects and automatically configure them for Cloudflare by running cf init/deploy, which will install the Cloudflare Vite Plugin for you and create a configuration file.
Static sites still don’t require a configuration file to start, and deploying them is as simple as running cf deploy in your project.
To start a new Hello World project with cf, use cf init.
cf is open source and issues can be reported to our GitHub repository.
