, ,

I Gave Claude Code My MU Plugins – It Revived a 16-Year-Old Plugin

I gave Claude Code my entire mu-plugins folder.

Every WordPress developer reading this knows what that folder looks like. Years of accumulated snippets. Uncommented functions copied from Stack Overflow at midnight. Three different versions of the same heartbeat throttle. remove_action calls targeting hooks that don’t even exist anymore. The kind of code that’s too small to be a plugin but too important to leave out, so it just… lives there. On every site you’ve ever touched.

My snippets folder had been growing for ages.

I dumped the whole thing in and said: “Look at this. Tell me what it does. Turn it into something clean”.

What came back was a settings page. Toggles. All my accumulated WordPress muscle memory — a decade of “does this site actually need this?” decisions — extracted into something I could see, edit, and ship.

I looked at it and thought: I’ve built this before.


2010 – YSlow – WP Avoid Slow.

Sixteen years ago I published a WordPress plugin called WP Avoid Slow.

WordPress 2.9.x was released. YSlow was the performance Bible. Steve Souders had written the rules, Yahoo! built the grader, and every developer I knew was obsessing over HTTP request counts.

The fastest request is the one that never happens.

My plugin generated .htaccess rules. Gzip compression. Browser caching headers. The checklist that every “speed up WordPress” post repeated for years.

Then YSlow died. Lighthouse replaced it. The real problem had shifted anyway — it wasn’t the server config. It was WordPress itself, quietly running things on your site you never asked for.

I let the plugin sit for sixteen years.


The Moment These Two Things Connected

Looking at what Claude Code had extracted from my mu-plugins, I had one of those slow realisations.

This was WP Avoid Slow. Not the .htaccess version — the version it should have always been.

WordPress ships defaults for everyone. Billions of sites. Millions of use cases. Features that some sites need, loaded on all sites, always. Your emoji script. Their oEmbed discovery. Somebody’s Windows Live Writer manifest — a product discontinued in 2017, still sitting in your <head> right now.

The YSlow principle still holds. The fastest request is the one that never happens. I just had the wrong target for sixteen years.

So I merged them. Revived the old plugin. Rewrote it with the help of Claude Code. Added everything from the mu-plugins folder. Organised it properly. And gave everyone a switch for each one.

That’s how you end up with 66 toggles and a plugin called The Off Switch.


Opening The Box — Everything WordPress Has Been Running On Your Site

Here’s every switch, described the way I wish someone had described it to me in 2010.


The Default WordPress Outputs (18 switches)

Things silently added to every page — <head>, HTTP headers, the DOM — that most sites have never needed.

  • Emoji Script — ~15 KB + one HTTP request. Browsers handle emoji natively. Fires for Internet Explorer compatibility. In 2025.
  • Embed Scriptwp-embed.min.js so others can embed your content. You’ve been paying for it on every page load whether you use it or not.
  • RSD Link — Really Simple Discovery. <link rel="EditURI"> in your <head>. Legacy XML-RPC client technology. Still there.
  • WLW Manifest — Windows Live Writer. Discontinued in 2017. Still linked from your <head>.
  • WP Generator Tag<meta name="generator" content="WordPress 6.x.x">. Tells every automated scanner exactly which version you’re running.
  • Shortlink<link rel="shortlink"> in <head> and an HTTP header. Search engines have never used it.
  • Asset Query Strings?ver=6.x on every script and stylesheet URL. Breaks CDN caching. Added by default.
  • XML-RPC — Remote publishing endpoint. Also the first thing every brute-force scanner tries.
  • Heartbeat API — AJAX request to your server every 15 seconds. Even on the frontend. Even with no editor open.
  • Dashicons (Frontend) — ~35 KB of CSS and a font file for admin icons, loaded for every logged-out visitor who will never see a single admin icon.
  • REST API Discovery Link<link rel="https://api.w.org/"> in <head>. Advertises your REST endpoint to every parser.
  • RSS Feed Links — Feed autodiscovery tags. Modern browsers stopped acting on them years ago.
  • Speculation Rules (WP 6.8+) — Prefetches pages before users click. Can inflate analytics, spike bandwidth, and trigger consent on pages users never visited.
  • All Feeds — Redirects every /feed/ URL to the homepage. For sites with no RSS subscribers.
  • Comment Auto-Links — Converts plain-text URLs in comments to clickable links on every page load that has comments.
  • Editor Autosave — POSTs your editor content to the server every 60 seconds while you write.
  • DNS Prefetch<link rel="dns-prefetch"> hints for external resources. Mostly redundant once Emoji and Embed scripts are off.
  • Recent Comments Inline CSS — Inline <style> block in <head> for the Recent Comments widget. Fires even if your theme already styles it.

Script & Style Control (7 switches)

  • jQuery Migrate — ~30 KB. For plugins written before jQuery 1.9. Your modern stack doesn’t need it.
  • Block Library CSS — ~7 KB on every page, even with no Gutenberg blocks in your content.
  • Global Styles — 10–50 KB of inline CSS generated from block theme configuration.
  • SVG Duotone Filters — Hidden SVG blob on every page for the Duotone image filter. Even with no duotone images.
  • Type Attributestype="text/javascript" and type="text/css" on every tag. Invalid in HTML5. Still added.
  • Defer JS — Adds defer to non-critical scripts. jQuery is never deferred.
  • Move Scripts to Footer — Relocates enqueued scripts before </body>. jQuery never moves.

WordPress Behaviour (4 switches)

  • Self-Pings — WordPress pings your own posts when you link between them. Wasted request. Unwanted comment on the target post.
  • Capital P Filter — Corrects “Wordpress” to “WordPress” on every rendered string.
  • Post Revisions — Unlimited by default. Three is enough.
  • Attachment Pages — A full template page for every uploaded file. Crawl budget waste on most sites.

Database & Query (5 switches)

  • Expired Transients — Daily sweep of expired wp_options rows WordPress doesn’t reliably clean on low-traffic sites.
  • Auto-Drafts — WordPress creates one every time you open the editor. Abandoned sessions leave rows in wp_posts permanently.
  • Skip Row Count on SinglesSQL_CALC_FOUND_ROWS runs on every single post/page. Needed for paginated archives. Single posts never paginate.
  • Adjacent Post Links — Two DB queries per single post for <link rel="prev/next"> in <head>. Google dropped support in 2019.
  • Reduce Trash Retention — WordPress keeps trash for 30 days. Seven is enough.

Image Performance (5 switches)

  • Google Fonts display:swap — Without it, browsers hide text while fonts download. One filter. Massive perceived performance improvement.
  • Add Image Dimensions — Images without width and height attributes cause layout shifts. Reads from attachment metadata and injects them automatically.
  • LCP FetchPriorityfetchpriority="high" on the first content image. Everything else gets loading="lazy" and decoding="async".
  • Lazy Load Imagesloading="lazy" below the fold. The first image is never lazy-loaded.
  • PDF Thumbnails — WordPress generates image previews for every uploaded PDF when ImageMagick is available. Real processing overhead on upload.

Admin Hardening (9 switches)

  • User Enumeration?author=1 redirects to /author/username/. One request exposes every account name on your site.
  • Author Archives — Full paginated archive at /author/username/ for every registered user.
  • File Editor — In-browser PHP editor under Appearance → Editor. A compromised admin account can inject code directly.
  • Application Passwords — Long-lived API tokens. An unused authentication surface is an unnecessary one.
  • Admin Email Check — Full-screen prompt asking admins to confirm their email. Periodically. Forever.
  • X-Pingback Header — Every HTTP response advertises your xmlrpc.php URL. Even when XML-RPC is disabled.
  • Admin Bar Noise — WP logo dropdown, duplicate Visit Site link, admin bar search.
  • Update Nag for Non-Admins — Editors can’t apply updates. The nag creates confusion, not action.
  • REST API (unauthenticated) — Publicly accessible by default, including /wp/v2/users.

Block Editor (5 switches)

  • Remote Block Patterns — HTTP request to api.wordpress.org on every editor load. Even if nobody uses the Pattern inserter.
  • Core Block Patterns — WordPress’s built-in pattern library. Headers, galleries, CTAs.
  • Block Directory — Live block search and install from the editor.
  • Font Library (WP 6.5+) — Upload fonts and browse Google Fonts in Site Editor.
  • Widget Block Editor (WP 5.8+) — Restores the classic Widgets screen for classic themes.

WooCommerce (9 switches)

Only visible when WooCommerce is active.

  • Cart Fragments — AJAX request to keep mini-cart counts live when the Cart Widget renders.
  • WC Generator Tag<meta name="generator" content="WooCommerce x.x.x">.
  • WC Scripts on Non-WC Pages — ~114 KB of CSS and JS on your blog, about page, and every non-store page.
  • Password Strength Meter — zxcvbn (~80 KB gzipped) on pages that don’t need a password field.
  • Status Dashboard Widget — WooCommerce Status box on the wp-admin dashboard.
  • WC Block Patterns — WooCommerce’s own patterns in the editor inserter.
  • WC Legacy Widgets — 12 widget classes registered on every page load, even on block themes with no sidebar.
  • WC Version Header — HTTP response header advertising your WooCommerce version.
  • Stripe Gateway Scripts — Stripe.js loading when the Payment Request Button is disabled in Stripe settings.

Login Page (4 switches)

  • Login Error Details — WordPress tells attackers whether a username exists by varying the error message. This makes all errors identical. On by default.
  • Email Login — WordPress 4.5+ accepts email addresses as login identifiers. This enforces username-only.
  • Register Link — The “Register” link on wp-login.php. Remove the entry point without disabling registration.
  • Language Switcher (WP 5.9+) — Locale dropdown on the login form. Noise on single-language sites.

What This Actually Is

This isn’t a performance plugin in the way people usually mean that.

WP Rocket, Autoptimize, LiteSpeed Cache — those take what WordPress produces and process it. Minify it. Cache it. Defer it. Compress it. They optimise the output.

This plugin operates before any of that. It removes things before they’re ever generated. No output to cache. No JavaScript to defer. No request to optimise.

The request never happens.

Every plugin in that space is trying to solve a problem that starts earlier in the chain than they touch. My mu-plugins folder was my personal answer to that for all these years. Claude Code helped me see it clearly enough to ship it.

Sixteen years after WP Avoid Slow. Same principle. Finally the right tool.


The Off Switch is free on WordPress.org — search wp-avoid-slow or The Off Switch

66 switches. Pure PHP hooks. No .htaccess. No upsell. No Pro version. Read the entire source in an afternoon.

If you’ve got your own mu-plugins folder — you already know which switches to flip.