Getting started
Install once. Begin read-only. Keep your data.
The CLI, dashboard launcher, and stdio MCP server ship as one versioned package. Connect them to a shared hosted control plane or deliberately use standalone local files. Operator state and policy live outside the installed package.
For control from multiple devices, start with the shared hosted backend. It uses one D1 authority and scoped Access credentials instead of distributing the account API token. The standalone instructions below apply when no hosted URL is selected.
First run
Reach a verified read-only audit
1
Install a tagged source package
Node.js 22 or newer is required. Choose a tag from GitHub Releases; npm copies the package into its global prefix so the command does not depend on a checkout.
npm install --global "github:j-256/cloudflare-fleet#v0.1.0"
cloudflare-fleet --version
2
Export the account credentials
Load the values through your normal shell secret workflow or secret manager. Keep literal values out of repositories and shared MCP configuration.
export CLOUDFLARE_API_TOKEN="your-account-token"
export CLOUDFLARE_ACCOUNT_ID="your-account-id"
3
Verify local and live readiness
The doctor reports effective paths, credential presence, permissions, dependencies, and one bounded zone-list request without printing either credential value.
cloudflare-fleet config show
cloudflare-fleet doctor --live
4
Run the first read-only audit
The audit keeps progress on stderr and emits its report on stdout. Permission-denied optional surfaces remain visible in coverage instead of appearing absent.
cloudflare-fleet audit
cloudflare-fleet audit --format html > audit.html
5
Open the local dashboard when wanted
On macOS, the default launch is read-only. The doctor identifies any missing local dependency before the launcher opens a normal browser tab through its loopback broker.
cloudflare-fleet dashboard
A local checkout is not an installation
Avoid npm install --global . for daily use because npm normally links the executable back to that checkout. Moving or deleting it then breaks the command. Use a tagged GitHub source package for the durable install.
Least privilege
Give the token only the coverage you intend
Scope the token to the intended account and zones. Cloudflare's API token permission groups are authoritative; Fleet's coverage report shows how the chosen token behaves against the actual account.
| Workflow | Typical permission groups | Guidance |
| First connection | Zone Read | Supports account-scoped zone discovery and the bounded live doctor request. |
| Common inventory | Zone Settings Read, DNS Read, Email Routing Rules Read, Zone WAF Read, and the matching groups for other products in use | Add surface access deliberately. Canonical alias policies also need the relevant zone products plus account Workers custom-domain and Pages project reads. Missing optional access is reported as coverage evidence. |
| Reviewed writes | The corresponding Zone Settings Write, DNS Write, Email Routing Rules Edit, or Zone WAF Write | Do not add write permission until the matching operator outcome is required. |
| Deep account audit | Product-specific account read groups for Workers, Pages, D1, KV, R2, Queues, Workflows, and Registrar | These expand evidence only for the selected deep audit and are not a baseline requirement. |
Know where operator data lives
No config file is required for a first run. State defaults to $XDG_STATE_HOME/cloudflare-fleet/state.json or ~/.local/state/cloudflare-fleet/state.json. Policy defaults to $XDG_CONFIG_HOME/cloudflare-fleet/fleet-policy.json or ~/.config/cloudflare-fleet/fleet-policy.json. Files Fleet creates are mode 0600, and the doctor warns about unsafe existing files or symbolic links.
Selection precedence is an explicit command flag, a Fleet environment variable, an XDG environment variable, then the per-user default. Fleet-specific environment paths must be absolute.
export CLOUDFLARE_FLEET_STATE_FILE="$HOME/.local/state/cloudflare-fleet/production.json"
export CLOUDFLARE_FLEET_POLICY_FILE="$HOME/.config/cloudflare-fleet/production-policy.json"
cloudflare-fleet config show
Use --state-file and --policy-file instead when a profile should apply to only one command. State contains inventory snapshots, intent, and activity. Policy contains typed operator exceptions. Neither contains the API token, but both can reveal sensitive fleet configuration and should stay private and backed up.
Use a simple daily operating loop
The dashboard's section links stay visible while scrolling: Overview summarizes fleet health, Configuration opens the comparison workspace, Workflows provides Email Routing, Shared WAF, and DNSSEC alignment, and Read health explains API coverage. Configuration appears before the specialized workflows. Use Focus matrix when you need the full viewport for comparison.
To copy a rule, use Copy rule on its matrix row or Copy to zones in the ruleset workspace. Pick a source and destination zones there, using group shortcuts or search when useful, then review the live changes. The source remains unchanged, and verified copies support guarded undo in Activity. MCP clients use plan_fleet_change and apply_fleet_change with kind: ruleset-rule-copy, exact source identifiers from list_resources, and explicit targetZoneIds.
To record a known-good configuration, choose Current is good on a facet and Save intent. Fleet keeps each selected zone's exact value, including deliberate differences and absent rules. For a batch, select the checkboxes beside facet names and choose Accept current state. The scope picker accepts several groups or individual zones in the same save. These decisions change saved intent only and support Undo last fleet intent change.
Use Edit coverage to change where a saved expectation applies. Check all the groups it belongs to and save once. Keep saved expectation retains the existing value, including custom intent; Match a zone explicitly chooses a live source instead. Must be absent everywhere else replaces other scopes for that facet with an absence default. The manager groups assignments under one facet entry; custom constraints, individual policy removal, and structured editing remain under Advanced or Individual policies and advanced controls. MCP clients use plan_facet_intent and apply_facet_intent with the same current, source, saved, and absent modes. Incomplete reads block acceptance, and a live value change during review requires another review before saving.
Dashboard search respects the selected filters, including the initial review and fleet-pattern filters. When those filters hide matching configuration, a notice reports the hidden matches. Choose Show all matches to search across all loaded facets while keeping the query and selected target zones. For bounded agent lookup, list_facets supports search without inheriting dashboard filters.
Saved policies remain editable when their facets are unavailable in the loaded inventory. Such policies show Not evaluated; they do not claim matching or actionable observed values. Edit their saved scope, presence, or expected value, or remove obsolete intent. These edits persist intent without creating Cloudflare resources. Agents can inspect the saved policy with get_fleet_policy, inspect available live evidence with inspect_facet, and use the intent plan/apply tools for reviewed changes. An unavailable effective facet reports unresolved; incomplete reads report unknown.
cloudflare-fleet doctor --live
cloudflare-fleet audit --fail-on warning
cloudflare-fleet dashboard
cloudflare-fleet intent aliases --format json
cloudflare-fleet intent rate-limits --format json
cloudflare-fleet adoption list --lens gaps --format json
The dashboard is read-only until launched with --write. Use --fresh when a launch should bypass cached inventory. After a reviewed mutation, inspect durable evidence with cloudflare-fleet activity list; begin recovery only with cloudflare-fleet activity undo plan --id ACTIVITY_ID, which blocks if live state no longer matches the verified operation.
The noninteractive CLI follows the same plan and apply split. Generate a JSON plan, present it for approval, and pass its exact digest to the corresponding apply command. A changed digest exits distinctly before mutation.
For one operator outcome that needs several bounded direct changes, pass { "changes": [...] } to change plan and change apply. Fleet composes fresh reads, refuses blocked or overlapping members as one unit, and records the accepted operation sequence under one plan digest and activity.
intent aliases returns the strict canonical passthrough facet, its exact resource envelope, and initial compatibility-domain templates without reading or writing Cloudflare. Persist a selected value through the ordinary revisioned intent plan and apply commands, then remediate drift through alignment.
intent rate-limits returns the required-and-exact Free-plan posture that pairs one path rate rule with the earlier custom WAF skip confining it to selected hostnames. It includes an unused value and an API-path starter. Alignment creates the skip before the rate rule, disables the rate rule before host-scope changes, and removes the rate rule before the skip.
adoption list inspects ungoverned facets and defaults to a coverage-gap lens that surfaces the present-on-most, missing-on-few pattern, names the outlier zones, and tallies how often each zone falls outside the fleet consensus. Use --lens all for every candidate. A zone that could not be read is never reported as a missing gap. adoption plan and adoption apply read an { adopt, exempt } request: adopted candidates default to required presence so their outlier zones surface as drift, and each exemption is an acknowledgement that clears the missing status for named zones. Adoption persists fleet intent through the same revisioned plan and apply split and never writes Cloudflare.
Connect a trusted MCP client
The installed cloudflare-fleet mcp command is a stdio server with no network listener and no arbitrary Cloudflare API passthrough. Its first diagnostic tool, get_runtime_status, can explain missing setup before an agent attempts fleet work. describe_zone_alias_policy and describe_hostname_scoped_rate_limit_policy return the same typed contracts and reusable values as the CLI. list_adoption_candidates, plan_fleet_adoption, and apply_fleet_adoption surface coverage gaps and persist reviewed governance to fleet intent without writing Cloudflare.
Resolve exact identifiers with list_zones and list_resources, or discover normalized comparison keys with list_facets. Then call inspect_facet to see observed values beside effective policies, overrides, conflicts, acknowledgements, and supported actions. The static fleet://catalog/retrieval resource lists the supported categories and resource kinds. These reads also have CLI equivalents:
cloudflare-fleet zone list --name example.com --format json
cloudflare-fleet resource list --kind dns-record --zone-id ZONE_ID --format json
cloudflare-fleet facet list --category "Zone settings" --format json
cloudflare-fleet facet inspect --category "Zone settings" --key always_use_https --zone-id ZONE_ID --format json
cloudflare-fleet activity list --status verification-failed --limit 5 --format json
cloudflare-fleet activity get --id ACTIVITY_ID --path plans --path 0 --format json
cloudflare-fleet intent list --zone-id ZONE_ID --format json
cloudflare-fleet intent get --id POLICY_ID --format json
Lists return compact, bounded items pages. Continue with nextCursor and the original filters; restart if the underlying revision changes. get_activity and get_fleet_policy provide stored detail, while view: "full" adds bounded detail to list results. Large values carry an explicit truncation flag, digest, preview, and child keys for focused traversal. Complete stored exports remain available through get_fleet_intent and get_fleet_state. Check coverage and freshness before drawing conclusions: an incomplete read is unknown, and a recorded successful write does not prove present state. See cloudflare-fleet help retrieval for filters and bounds.
Codex
Add the server to ~/.codex/config.toml and explicitly forward the credential variables from the environment that launches Codex.
[mcp_servers.cloudflare_fleet]
command = "cloudflare-fleet"
args = ["mcp"]
env_vars = ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]
Run codex mcp list, then inspect /mcp in a session and ask Fleet for get_runtime_status. See the official Codex MCP guide for configuration semantics.
Claude Code
Register the command at user scope, then launch Claude Code from the shell that exports the credentials.
claude mcp add --transport stdio --scope user cloudflare-fleet -- cloudflare-fleet mcp
claude mcp list
Inspect /mcp in a session and ask Fleet for get_runtime_status. The registration stores only the command and arguments. See the official Claude Code MCP guide for scopes and environment handling.
Other clients
{
"mcpServers": {
"cloudflare-fleet": {
"command": "cloudflare-fleet",
"args": ["mcp"]
}
}
}
Arrange for the client process to inherit either the standalone account credentials or the hosted URL, expected account, and chosen Access credential variables. Append absolute --state-file and --policy-file arguments only for an explicit standalone profile. Hosted mode rejects those file flags. Read and plan tools work without interactive approval; apply tools require a client that supports MCP input elicitation. Single-change tools use compact per-operation review fields. Explicit alignment batches and plan_fleet_changes/apply_fleet_changes display every operation across bounded required review pages, followed by one final whole-batch decision. Mark every page Reviewed / Continue before selecting Approve entire batch. In the Codex terminal, Left/Right or Page Up/Down navigate fields and Escape cancels. Resize a clipped window until the full page is visible, or use CLI/dashboard review. An oversized value is summarized to a length, digest, and head preview so the review remains legible. Use the CLI or dashboard for review and apply if the client does not present that elicitation.
Update or uninstall without losing state
Choose the desired release tag, install it over the existing package, and rerun the live doctor.
npm install --global "github:j-256/cloudflare-fleet#v0.1.0"
cloudflare-fleet --version
cloudflare-fleet doctor --live
Run npm uninstall --global cloudflare-fleet to remove only the program. npm does not remove the state and policy paths shown by cloudflare-fleet config show.
Work from a source checkout
A checkout is for development and hosted deployment. Its wrappers enter the same implementation without replacing the durable global install.
git clone https://github.com/j-256/cloudflare-fleet.git
cd cloudflare-fleet
npm ci
npm run fleet -- doctor
./launch.sh
The checkout-local launcher is also read-only by default. Run the test and publication commands in CONTRIBUTING.md before proposing a change.
Hosted access
Keep the safe defaults when you deploy.
The hosted generator starts read-only and keeps live deployment values outside Git.
Open deployment