Skip to content

Repository files navigation

eliware.org

cfops npm version license build status

An OAuth-first Cloudflare administration CLI for inspecting and managing zones, DNS, rules, settings, lists, and account services. cfops is designed to feel familiar to anyone who uses the GitHub CLI: commands are composable, automation-friendly, and safe by default.

Features

  • OAuth browser login with a guided scope picker and OS keychain storage.
  • API-token login for headless automation with --token-stdin.
  • Multiple named profiles with switch, status, verify, list, and logout commands.
  • Zone, DNS record, zone setting, ruleset, Cloudflare list, and list-item commands.
  • Account resource commands for load balancers, tunnels, Workers, Pages, R2, D1, Queues, Stream, Images, AI, and Access.
  • Read-only health, audit, inventory, SSL, Origin CA, and cache commands.
  • cfops api for direct access to any Cloudflare API endpoint.
  • Human-readable and JSON output, including --jq and templates.
  • --dry-run for supported writes and --force for destructive operations.
  • GitHub CLI-style help, aliases, typo suggestions, and command discovery.
  • Dependency-injected ESM architecture with an extension/plugin contract and example extension.

Requirements

  • Node.js 26 or newer.
  • A Cloudflare account and permission to authorize the Eliware OAuth client, or an API token for automation.
  • Account and zone IDs for commands that need an explicit scope when defaults are not configured.

Installation

Install the published package:

npm install --global cfops

Or install from source:

git clone https://github.com/eliware/cfops.git
cd cfops
npm install
npm link

Verify the installation:

cfops --version
cfops --help

Authentication

Interactive users should start the OAuth flow:

cfops auth login

The local web interface lets users select the scopes they need before authorizing with Cloudflare. Access and refresh credentials are stored in the operating system keychain when available. The callback page confirms success or failure and then the temporary local server shuts down.

Default OAuth client

Running cfops auth login uses the public Eliware OAuth client built into the CLI. The command starts a temporary local OAuth web server, opens the scope picker, and then sends the selected authorization request to Cloudflare. The client can request only scopes enabled in its Cloudflare registration, so the picker's selections are limited by that registration.

Use your own OAuth client

You can register and manage a Cloudflare OAuth client in your own account or organization. This is useful for teams that want their own application identity or a different set of approved scopes:

  1. Create an OAuth application in Cloudflare.
  2. Enable the authorization-code response type (Code), rather than an implicit token response.
  3. Register http://127.0.0.1:8765/oauth/callback as the redirect URL. If the registration accepts multiple redirect URLs, also add ports 8766 through 8769; cfops uses those ports when an earlier one is busy.
  4. Select all scopes the client is allowed to request. The scope picker can select permissions only when the Cloudflare client registration permits them.
  5. Start the normal login command with the client ID:
CF_OAUTH_CLIENT_ID=your-client-id cfops auth login

There is no separate OAuth-server command: cfops auth login starts the temporary server automatically. The default browser redirect remains 127.0.0.1; for remote access, the server can bind on all interfaces while the registered redirect remains local to the browser:

CF_OAUTH_CLIENT_ID=your-client-id \
CF_OAUTH_BIND_HOST=0.0.0.0 \
CF_OAUTH_REDIRECT_HOST=127.0.0.1 \
cfops auth login

The client ID environment variable overrides the built-in Eliware client for that login only. Do not commit client credentials, tokens, or .env files.

For headless automation, provide an API token through standard input:

printf '%s' "$CLOUDFLARE_API_TOKEN" | cfops auth login --profile ci --token-stdin

Use profiles to separate accounts or automation contexts:

cfops auth list
cfops auth status
cfops auth switch --profile work
cfops auth verify
cfops auth logout --profile work

An unauthenticated command reports that the user is not logged in and directs them to cfops auth login, matching the familiar GitHub CLI workflow.

The CLI checks npm for a newer version at most once per day. The check is best-effort, does not delay commands, and never updates automatically. Disable it with CF_NO_UPDATE_CHECK=1 or permanently with:

cfops config set update-check false

Configuration

Environment variables may be supplied directly, through a local .env, or as optional defaults in the project configuration:

CLOUDFLARE_API_TOKEN=your_api_token
CLOUDFLARE_ACCOUNT_ID=your_account_id
CLOUDFLARE_ZONE_ID=your_zone_id

OAuth profiles are stored in the ~/.cfops configuration directory, while secrets are stored in the OS keychain. Existing environment variables take precedence over profile values. Keep tokens, .env files, keychain exports, and generated state private; none should be committed.

Usage

Inspect zones and DNS records:

cfops zones list
cfops zones get --zone-id <zone_id>
cfops dns-records list --zone-id <zone_id>
cfops dns-records get --zone-id <zone_id> --id <record_id> --output json

Create or preview a DNS change:

cfops dns-records create --zone-id <zone_id> \
  --data '{"type":"A","name":"www","content":"192.0.2.1"}' \
  --dry-run

Destructive operations require explicit confirmation:

cfops dns-records delete --zone-id <zone_id> --id <record_id> --force

Use JSON, jq selection, templates, or dashboard links in automation:

cfops zones list --json
cfops zones list --json --jq '.result[]'
cfops api /zones --json --jq '.result[].name'
cfops api /zones --json --template '{{.result}}'
cfops zones get --zone-id <zone_id> --web

Access the full Cloudflare API when a built-in command is not available:

cfops api /zones
cfops api zones/<zone_id>/dns_records --method POST \
  --data '{"type":"TXT","name":"example.com","content":"hello"}'

Run <resource> --help or <resource> <command> --help for detailed command-specific help. Singular aliases such as cfops zone, cfops dns, cfops rules, and cfops list are supported.

Extensions

Extensions add local commands without changing the built-in CLI. The repository includes an example extension and documents the extension manifest and handler contract:

cfops extension list
cfops extension install --path examples/extensions/hello
cfops hello --name Eli

See docs/extensions.md for the extension contract and docs/gh-orientation.md for the GitHub CLI familiarity guide.

Development

Install dependencies and run the validation suite:

npm install
npm test
npm run lint
npm run test:gaps
npm run pack

The test suite uses dependency injection for Cloudflare clients, filesystem access, environment loading, output, handlers, and process exits. Browser checks for the OAuth web interface are available without authenticating:

npm run test:e2e:screenshots
npm run test:e2e:lighthouse
npm run test:e2e:web

Screenshots and Lighthouse reports are written under the ignored artifacts/ directory. Puppeteer is a development dependency and the local web test page can simulate the OAuth picker and callback result states.

Project structure

  • bin/ - executable CLI entry point.
  • src/cli.mjs - dependency-injected command runtime.
  • src/handlers/ - built-in resource and authentication handlers.
  • src/oauth-web/ - standalone OAuth picker and callback pages.
  • src/ - argument, environment, API, profile, output, and extension utilities.
  • examples/extensions/ - example extension.
  • tests/ - unit and integration tests.
  • tests/e2e/ - Puppeteer and Lighthouse checks.
  • dream.md - product vision.
  • dream_sprints.md - roadmap.

Support

For help, questions, or community chat:

Discord
eliware.org on Discord

License

ISC © 2026 Eli Sterling, eliware.org

Links

About

OAuth-first Cloudflare operations CLI

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages