News2 hours ago

Cloudflare's New cf CLI Put a Delete Command First When We Asked It to Block an IP

We ran 20 tasks through the search built into Cloudflare's new agent-first CLI. It ranked the right command first 13 times out of 19, and its telemetry sends your query text to Cloudflare by default.

The WJS Desk

Sep 30, 2026 · 7 min read

Photo by Stanislav Kondratiev on Pexels

Cloudflare shipped cf on September 28, a new CLI it describes as built for agents first and humans second. The launch post claims it covers "over 3,000 operations" against roughly 280 in Wrangler, and says agents already account for 48% of Wrangler usage. The Hacker News thread (157 points) spent most of its energy arguing about TypeScript.

We cared about something else. If the main user is an agent, the agent's front door is cf cli search, and we wanted to know two things: does it find the right command, and what leaves the machine when it runs? So we installed cf@1.0.0-beta.5 on an M4 Pro Mac, ran 20 task descriptions through search, and turned on the debug flag that prints the telemetry payload. Search put the correct command first 13 times out of 19. And the payload identified our session as "agent":"claude-code" and included our search text word for word.

What actually shipped

The package is cf on npm, currently 1.0.0-beta.5, published on launch day 29 minutes after beta.4. The GitHub repo, cloudflare/cf, was created on September 21 and sits at 396 stars. It is an open beta: Cloudflare says a final major version follows the beta and Wrangler gets 18 more months of support after that.

  • Generated, not handwritten. Commands come from Cloudflare's OpenAPI schemas through an internal pipeline called Forge. That explains both the breadth and some of the rough edges below.
  • JSON by default. Output is JSON rather than tables, which suits an agent and irritates a human.
  • Wrangler underneath, for now. The launch post says cf still delegates to Wrangler for esbuild and Python Workers during the transition.
  • A TypeScript config format, cloudflare.config.ts, which the post says cut some configs by 40%. We did not test that claim.

The install is not light. npm i cf pulled 224 MB of node_modules in 6.8 seconds, including workerd and miniflare. Wrangler 4.143.0 in a clean folder came to 213 MB, so this is not a regression, just not the slim tool the word "CLI" suggests.

What we measured

One HN commenter, amluto, asked the question the launch post skipped: how long does it take to start? We timed --version six times each on the same machine.

Measurecf 1.0.0-beta.5wrangler 4.143.0
Cold --version, median of 60.19 s0.48 s
node_modules after clean install224 MB213 MB
cf cli search, per query0.65 sn/a

The search index ships inside the package at dist/_meta/commands.json, a 5.2 MB file listing 2,936 commands. That is a little short of "over 3,000", though the gap could be commands that delegate to Wrangler and never reach the index. 950 of those 2,936 are flagged hidden, so they are left out of --help but still come back from search. Radar alone accounts for 152 hidden commands and Magic Transit for 138.

The generated origins show in the top-level help. Of the 79 command groups it lists, 31 have a description that is just their own name repeated. Among them are dns, kv, workers and zone, which are exactly the groups an agent reaches for first. zone and zones are also separate groups: cf zone holds one command (activate) while everything else sits under cf zones. Same split for account and accounts.

Does search find the right command?

Search is local. It runs MiniSearch over that bundled JSON with fuzzy matching, boosting the command name by 8, the summary by 5 and the description by 2. No API call is needed to answer a query. We wrote 20 plain task descriptions of the kind an agent would produce, confirmed the intended command existed in the index, and recorded where it ranked.

  • 13 of 19 at rank 1. DNS records, cache purge, KV namespaces, R2 buckets, Pages projects, page rules, Worker secrets and deletion all landed first.
  • 3 more in the top five. "create a d1 database" put cf d1 migrations apply above cf d1 create. "create a queue" put queue consumers first. "create a tunnel" ranked two Magic Transit tunnel types above cf tunnels create.
  • 3 complete misses. "rotate an api token" returned Zero Trust service tokens and API Shield validation rules, because Cloudflare calls the operation roll. Search "roll an api token" and both token roll commands appear immediately. "add a new domain" returned email security domains, not cf zones create.

The miss that worried us: "block an ip address" put cf addressing address-maps ips delete at rank 1. The right command, cf firewall access-rules create, was nowhere in the five. The CLI's own banner tells agents to "pick the best match instead of repeating similar searches", so an agent that follows that advice goes straight to a delete.

The twentieth query, "tail worker logs", is not counted because there is nothing to find: beta.5 has no equivalent of wrangler tail in its index. Rephrased as "stream live logs from a worker", search returned Cloudflare Stream video inputs.

What leaves your machine

Every --help output begins with a 724-character block addressed to agents. One line says: "Keep cf cli search queries anonymous... Never include names, email addresses, domains, account or resource IDs, tokens." That instruction makes sense once you read the telemetry policy. Telemetry is on by default, and the search query is the one free-text field it sends unredacted, "to help us make sure relevant results are being returned."

We ran DEBUG=1 cf cli search "list dns records", which prints the payload before sending it. The finished event contained:

"agent": "claude-code",
"agentSessionKey": "4370c1c9dbd2...",
"cliMode": "non-interactive",
"osVersion": "Darwin Kernel Version 25.5.0: Mon Apr 27 ...",
"searchQuery": "list dns records",
"durationMs": 196

All of this matches what the policy says. The session key is a hash rather than the raw ID, flag values are redacted, and CF_SEND_TELEMETRY=false or DO_NOT_TRACK=1 switches it off. Our issue is where the privacy boundary actually sits. Leaving a customer's domain out of the search query is not enforced in code. It relies on a line of text asking the model to behave. Anyone who has watched an agent paste a hostname into every tool call knows how often that line will be followed.

What the thread argued about

Most of the HN discussion was about language. slowin argued a CLI should be a compiled binary and "Do not force your users to manage the dependencies of your cli." locknitpicker replied that a tool which sends HTTP requests and prints JSON has no performance problem for TypeScript to cause. lelanthran's answer to that was a single line: TypeScript is worse on "anything less susceptible to supply-chain attacks." Our 0.19 second startup supports locknitpicker on speed. Our 224 MB install supports lelanthran on how much you have to trust.

Two practical complaints held up better. esafak pointed out that 1.0 "isn't actually out and CI is red", and the release list backs the first half: beta.4 and beta.5 went out 29 minutes apart on launch day. hackernud3s noted "it can do everything except make the token to give it permissions", We did not log in to a real account, so we cannot confirm or rule that out. What we can say is that cf auth offers login, profiles and whoami, and the token commands all require an existing credential to run. recroad asked whether any of this beats an agent reading the REST docs. Having seen the search results, we would say yes for common tasks and no for anything Cloudflare names differently from how you would describe it.

The bigger picture

Cloudflare is the first big provider to ship a CLI whose documented audience is a model, and the design follows from that: JSON by default, help text that addresses the agent directly, a search command in place of a man page. The part that deserves copying is local search over a shipped index, which is fast and works offline. The part that does not is putting a promise in the help banner and treating that as a privacy control. For a beta, the fix is small: redact anything that looks like a hostname, an ID or an email address before searchQuery is sent, the same way free-form flag values already are.

Until that happens, if you point an agent at cf, set CF_SEND_TELEMETRY=false in its environment, and keep wrangler tail installed for logs.

Your turn

If you already run agents against Cloudflare, what do yours use today: Wrangler, raw REST calls, or the MCP server? And has one ever reached for the wrong command because the search looked right? Tell us which task it fumbled. We will add it to the next round of this test.

We have tested Cloudflare's agent tooling before. In our look at their security audit skill we fed it a fake finding to see whether it would notice, and it is the closest thing we have to a baseline for how much to trust their agent defaults.

Share

We asked Cloudflare's new agent CLI how to block an IP. Its top answer was a delete command. 13 of 19 tasks worked fine, and your search text goes to Cloudflare by default. #Cloudflare #CLI #AIAgents #DevOps

Never miss a ship

The best stuff that shipped this week, delivered every Thursday. Free, no spam. We read all the boring stuff so you get the fun parts.

Keep reading