Terraform-style plan and apply for Cloudflare.

murus plan shows what will change. murus apply changes it. No state file, no surprises.

curl -fsSL https://murus.dev/install.sh | sh

Checks the binary against the published SHA256SUMS and refuses to install on a mismatch. Read it first, the way you should with any installer.

$ murus plan

admin-api  account 00000000  no environment
./wrangler.jsonc

  settings
  ~ compatibility_date  2025-01-01 → 2025-11-01

  bindings
  + RATE_LIMITS   kv_namespace
      rate-limits-prod (0000000000000000000000000000aaaa)
  ~ ADMIN_DB      d1
      prod-admin (9f3c2211-4d5e-6f70-8192-a3b4c5d6e7f8)
    → staging-admin (aaaa1111-bbbb-2222-cccc-333344445555)
  - LEGACY_CACHE  kv_namespace old-cache (0000000000000000000000000000cccc)

  vars
  - LEGACY_FLAG  true

  !  LEGACY_FLAG is set on the deployed Worker but absent from config, and will
     be deleted.
     Add them to `vars`, or set `keep_vars = true` in the config to preserve
     them.

     1 secret set outside config and left untouched. STRIPE_KEY

1 to add, 2 to change, 2 to destroy.

How it works

  1. Write the config

    Your wrangler.jsonc is the source of truth. murus reads it. There is nothing else to maintain.

  2. murus plan

    Diffs the config against the live Worker and prints every add, change, and destroy. The command is read-only. It cannot change anything.

  3. murus apply

    Makes exactly the changes the plan listed, then reads each resource back to confirm it matches. A 200 is not proof. The read-back is.

No state file

Cloudflare already returns a deployed Worker's complete configuration.

So plan is a structural comparison against live infrastructure. There is no .tfstate to store, share, lock, or drift, and nothing is deployed into your account to hold state on your behalf.

$ rm -rf ~/.config/murus

murus is gone. There is nothing else to uninstall.

Least privilege, derived

wrangler login asks for 28 OAuth scopes to deploy a Worker that needs six. Your config already declares every binding, so murus computes the minimal set and shows you the difference on a credential you already hold.

Aspect wrangler login murus
OAuth scopes requested 28 6
Where scopes come from A fixed set Derived from your config
Permissions you did not ask for 22 None

A status code is not proof

Three of the four Cloudflare create endpoints tested return 200 while silently dropping fields they do not recognise. So apply reads the resource back afterwards and checks it against what the plan promised.

$ murus apply

  applying 1 to add, 2 to change, 2 to destroy
  + RATE_LIMITS        kv_namespace bound to rate-limits-prod     ok
  ~ compatibility_date              2025-01-01 → 2025-11-01       ok
  - LEGACY_CACHE       kv_namespace unbound                       ok

  5 resources read back. All match the plan.

Free for solo work. Team murus is $19 a month, for shared plan history and CI plan checks.