Omahub
← All plugins
M

Cloudflare

by mdick85

Cloudflare account resources, deployment status, usage meters, and dashboard token shortcuts in the Omarchy bar.

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
39db8b1
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
39db8b1
Reviewed
1 month ago

The plugin is a transparent Cloudflare dashboard widget that reads the user's wrangler OAuth token from local config files and makes API calls to Cloudflare. It performs no hidden actions, installs nothing outside its own directory, and all destructive operations (deploy, rollback, purge) are user-initiated with confirmation. The code is clean and the deterministic scan found no issues.

  • The plugin reads the wrangler OAuth token from config files, which is expected for a Cloudflare widget but means it has access to the user's Cloudflare credentials.
  • Actions like deploy, rollback, and cache purge run wrangler commands, but they require explicit user confirmation and are not automatic.
  • The plugin scans the user's projects directory for wrangler configs, but only reads them to map local projects to Workers.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/meirdick/omarchy-cloudflare --enable
Developer Tools #bar #quickshell #system

Cloudflare widget for Omarchy

A bar icon and a keyboard-driven panel for a Cloudflare account: what is deployed, what it is using, where every resource lives, and one keypress to the dashboard pages that mint API tokens.

Built for Omarchy 4 (shell/plugins, manifest.json, ~/.config/omarchy/plugins/).

Install

omarchy plugin add https://github.com/meirdick/omarchy-cloudflare.git
omarchy plugin enable mdick.cloudflare
omarchy bar move mdick.cloudflare      # optional, to place it

Plugins land disabled so you can read the code first. Removal is omarchy plugin remove mdick.cloudflare — the plugin is a plain git checkout and installs nothing outside its own directory: no hooks, no sudo, no files elsewhere on the system.

Requirements

  • wrangler, logged in (wrangler login). Nothing else to configure — the plugin finds wrangler's OAuth token itself and never asks for a separate API token. It watches both ~/.wrangler/config/default.toml and $XDG_CONFIG_HOME/.wrangler/config/default.toml and uses whichever holds the token that expires latest, because wrangler does not always write to the same one. Override with the wranglerConfigPath setting if yours lives elsewhere.
  • curl, jq is not needed, wl-copy for the copy actions.

The account:read scope that wrangler login grants also covers the GraphQL Analytics API, which is where the usage figures come from.

What the panel shows

It opens on an overview, not a list of everything. Every resource as one flat scroll was a data dump; the account only has a handful of things worth seeing at a glance, and the rest is one keypress away.

Overview

Section Contents
Needs attention Workers over the error threshold, failed Pages builds, inactive zones — by name, because a count of broken things is not actionable
Recent activity the three most recent deploys
Usage Worker requests and errors (24h), R2 storage, D1 rows read, zone traffic (7d)
Resources one row per type: count plus an aggregate — Workers 24 · 6.4k req/24h ›
Live sites a ↗ button on every Worker, Pages project and zone that serves one
Create a token dashboard shortcuts: account, user, R2/S3, AI Gateway, Turnstile

"Needs attention" is absent when nothing is wrong, so its presence is the signal.

Drill down — l or Enter on a resource row opens that type's own view, listed in order of significance: Workers by requests, R2 by size, zones by traffic, Pages by last deploy. h or Escape comes back, and the cursor returns to where you left it.

Search — / searches every resource of every type from anywhere, so you never have to know which category something is in to reach it.

Visit — anything that serves a site gets a ↗ button at the right edge, and o does the same from the keyboard. The row itself still opens the Cloudflare dashboard; the button opens the site. Two destinations, two targets.

The address behind that button is resolved, not guessed. A custom domain wins over the platform hostname, so a Worker shows os.example.com rather than its workers.dev name and a Pages project shows its own domain rather than *.pages.dev. <name>.<subdomain>.workers.dev is only offered when the account confirms that script has the subdomain route enabled — a third of the Workers on the account this was built against have it switched off, and offering those a link would hand out a 404. Workers with neither simply have no button.

Keys

Key Action
j / k, arrows move the cursor
l / Enter open a resource type; on a leaf row, open it in the dashboard
o open the live site (rows that serve one)
h / Escape back out one level, then close the panel
/ search every resource; Escape leaves search
c copy the row's id
u copy the live URL if the row has one, otherwise the dashboard link
r refresh now
t tail a Worker's logs in a floating terminal
D deploy (Worker or Pages project with a local checkout)
R roll back
P purge a zone's cache
Tab move to the next bar panel

D, R and P are uppercase and go through a confirmation dialog. Deploy and rollback run wrangler in a floating terminal rather than in the background, so you see the output and can stop it.

Mouse: left click toggles the panel, right click refreshes, middle click opens the Workers dashboard.

Hover carries what does not deserve permanent space. Over a usage figure it shows the exact number and which setting turns that row into a meter; over a deployment's 7h it shows the absolute timestamp. The configuration hint used to be a row of its own, which spent a line of every session explaining a one-time setting.

Settings

Edit the widget's entry in ~/.config/omarchy/shell.json. Omarchy 4.0.0.alpha parses manifest.json's schema but ships no settings UI yet, so this is the only way in for now.

{ "id": "mdick.cloudflare", "refreshIntervalSec": 60, "r2StorageGb": 500 }
Key Default Meaning
refreshIntervalSec 60 resource and deployment poll
analyticsIntervalSec 900 GraphQL usage poll; analytics lag by minutes anyway
projectsRoot ~/Projects scanned 3 deep for wrangler.toml/jsonc/json to map Workers to local directories
deployRows 8 deployments listed
workerRequestsPerDay 0 requests meter denominator
r2StorageGb 0 R2 meter denominator
d1RowsReadPerDay 0 D1 meter denominator
errorRatePercent 1 error rate that puts a warning badge on the bar icon

The three allowances default to 0, meaning "not set". Those rows then show the real figure with no percentage; hover one to see which setting turns it into a meter. Set it to your plan's allowance and the row grows a bar. They are not pre-filled with free-tier numbers on purpose: a paid account well past the free tier rendered as a red four-figure percentage against a 10 GB limit that was never real. A percentage against a guessed denominator is worse than no percentage.

What does not work

Cache purge is refused. The wrangler OAuth grant carries zone:read and there is no cache-purge scope in it, so Cloudflare answers 10000 Authentication error. The action is still there and says exactly that when it fails; u on a zone row copies the link to the token page where you can mint a token with the Cache Purge permission. Everything else works on the wrangler login alone.

Deploy and rollback need a local checkout. wrangler deploy runs inside a project directory. The plugin scans projectsRoot for wrangler configs and maps the name field to its directory; a Worker with no local checkout reports that instead of failing halfway through.

Marketplace

Listed via omarchyplugins.com. Conformance:

  • public repo with manifest.json at the root
  • all eight required manifest fields: schemaVersion, id, name, version, author, description, kinds, entryPoints
  • README.md and LICENSE present
  • safe install and removal — a git checkout with no install hooks
  • preview.png for the listing card
  • passes omarchy plugin validate

The preview image is rendered from fabricated data, not a real account.

Category: Developer Tools. Tags: Quickshell, Bar, System.

Development notes

Things that cost time here, recorded so they do not cost it twice:

  • Editing a .js file does not hot-reload. Saving under ~/.config/omarchy/plugins/ logs Local plugin changed, reloading and reloads .qml, but an imported .js module keeps its old contents. Run omarchy-restart-shell after touching Api.js or Model.js.
  • QML load failures are silent on screen. The widget just does not appear. quickshell list --all then quickshell log -i <instance> -t 100.
  • qmllint on this system is a stub — it exits 0 on a deliberate syntax error, so it proves nothing. qmlformat's exit code is also ambiguous (first-party files return 1 too). The real test is loading it.
  • The debug hatch is omarchy-shell mdick.cloudflare diagnose, which dumps credentials state, per-type counts, cursor position and the last error as JSON. It is how every bug below was found.
  • curl config booleans are bare words. location = false is rejected as "unsupported trailing garbage" and kills the whole request.
  • The Pages list endpoint rejects per_page, unlike every other list endpoint. It must be requested bare.
  • Check Nerd Font codepoints before using them. The first glyph set all rendered as «. Read the font's cmap rather than trusting a chart.
  • Wrangler's config path is not fixed. This machine has both ~/.wrangler and ~/.config/.wrangler, and wrangler switched which one it wrote to mid-session. Watch every candidate and prefer the latest expiry; hardcoding one path reads as a broken login when it goes stale.
  • expiration_time in the wrangler config is a hint, not a gate. wrangler whoami only rewrites that file when the API actually rejects the token, so refusing to send requests until the timestamp looks fresh leaves the widget frozen on stale data forever. Requests go out regardless and a real rejection triggers the refresh.

Credentials

The token is written to curl's stdin as a config file (curl -K -), never into argv. /proc/<pid>/cmdline is world-readable; a -H "Authorization: Bearer …" argument would expose the token to every process on the machine. Verified: a live request's argv is curl -K - and its environ holds no token.

Request bodies are not secret and do travel in argv, which avoids escaping JSON into curl's config quoting rules.

Layout

manifest.json        id, kind, entry point, settings schema
Panel.qml            bar icon, panel, cursor, row components
Service.qml          credentials, fetch pipeline, timers, actions
Api.js               URLs, curl config, GraphQL query, dashboard links
Model.js             row shaping and formatting
CloudflareIcon.qml   the mark, drawn from primitives

qs.Ui and qs.Commons are imported directly — qs is an engine-global import path, so a third-party plugin resolves them exactly as a first-party one does. Nothing is vendored.