Site speed skills for Claude Code, Codex & Cursor

The score went up. The menu got slower.

Your agent says the site is faster, because the score went up. The Site Speed Pack makes it measure first, change one kind of thing at a time, and prove after each change that the phone menu opens on the first tap, video waits for play, signed-in pages stay out of the edge cache and the layout doesn’t move. It was built from a real pass on a WordPress course and store site, where mobile scores went from 67–90 to 94–100.

$39. Every pack, now and later: $149.

Works with

  • Claude Code
  • Codex
  • Gemini CLI
  • Cursor
  • Windsurf
  • Aider

Fit check

Is this for you?

It’s for you if

  • A WordPress or code-built site scores badly on a phone or feels slow to open, and you want it faster.
  • Your agent made the score better, and you can’t tell whether the phone menu, forms, video and checkout still work.
  • You run a speed plugin, such as WP Rocket or Perfmatters, or Cloudflare caching, and want each setting changed with a way to undo it.

You’ll need

  • An AI coding agent that can run commands: Claude Code, Codex, Cursor or Gemini CLI.
  • Node.js 18 or newer, and Playwright and sharp in the project you run the scripts from. Lighthouse 13 needs Node 22.19 or newer.
  • For WordPress, WP-CLI, a WordPress MCP server that can run PHP, or wp-admin by hand. To cache pages at Cloudflare’s edge, the site on Cloudflare and the owner’s approval.

Skip it if

  • Your site is on Shopify, Webflow, Squarespace or Wix. The measurements work on any public URL, but the platform controls the server, the caching and often the images, so many fixes are out of reach.
  • You only need a fair before-and-after speed comparison of a code-built site. See the Spotter Round

Sound familiar?

Has this ever happened to you?

Tap every one you’ve lived through.

Nothing yet? Time your phone menu after the next speed change.

Why it keeps happening

Lighthouse never taps.

A speed score loads the page on a simulated phone and stops. It never opens the menu, plays the video or signs in, and it can’t tell a new page from an old copy a cache still holds. So a change that holds the first tap, strips an image size or caches the wrong page can raise the score, and the agent reports a win and means it.

The visitor finds it first: a menu that ignores a tap for seconds, a page that jumps under a thumb, a play button that a control bar covers. The score says nothing went wrong.

What the test runner timed

3.8 seconds from the tap to an open menu.

What the page recorded

20 ms. The runner had stalled while the page loaded its scripts, so it timed itself.

Observed on November 5, 2026, on the WordPress site this pack was built from. first-tap.mjs now records the tap and the open menu inside the page, and that site’s real delay, 3.9 seconds, was a delay setting holding the first tap.

The fix

Make it prove nothing broke.

The Site Speed Pack is two skills your agent loads and sixteen scripts it runs. site-speed-pass is the method on any site; wordpress-speed adds the server check, the plugins, the backups and the logged-in rules for WordPress. Every change is measured before and after, and checked for what the score can’t see.

  1. The first tap, timed in the page

    first-tap.mjs taps the phone menu on a throttled phone and times it inside the page. Over 300 ms fails, whatever the score says.

  2. One kind of change at a time

    Scripts, then CSS, then images, then caching. After each batch: purge every cache layer, confirm what is served, measure, and prove nothing broke, with a note on how to undo it.

  3. Edge caching only where it’s safe

    Logged-out HTML cached at Cloudflare’s edge, with the owner’s yes. edge-cache-check.mjs proves a second request is a hit and that no skip-list cookie or path ever is.

Proof

Real runs of the download.

Three runs of the shipped zip, unzipped fresh, with every connection off the machine refused. The harness breaks copies of the scripts and each broken copy must fail; the first-tap check catches a held tap on a page it serves itself; and a cache check with nothing to check refuses before any request.

[ Range card ] // What I aimed for, what came back
  1. [ Shot 01 ]

    ci/speed-skills.mjs

    Aimed: every selftest at the count its skill states, then copies of the scripts broken on purpose; each broken copy must fail

    ok server-check.mjs --selftest: 39 cases, as skills/wordpress-speed/SKILL.md states

    ok first-tap.mjs selftest fails with a slow tap no longer judged against --max-ms (1 case(s) caught it)

    ok edge-cache-check.mjs selftest fails with a bypass cookie answered from the cache passing (1 case(s) caught it)

    ok server-check.mjs selftest fails with a full OPcache with no restart coming no longer ACT (2 case(s) caught it)

    speed skills: clean (103 checks)

    Landed where it was aimed // exit 0

  2. [ Shot 02 ]

    first-tap.mjs --selftest

    Aimed: a menu that opens at once, one whose first tap is held and replayed, and one timed while the page blocks

    ok a menu that opens on the tap passes, timed by the page (19 ms, exit 0)

    ok a first tap swallowed and replayed 1.5 s later is measured as slow and fails the limit (1519 ms, exit 1)

    ok a menu that opens at once while the page then blocks for 1.5 s is timed by the page's clock, not the runner's (17 ms)

    19 cases behaved as designed

    Landed where it was aimed // exit 0

  3. [ Shot 03 ]

    edge-cache-check.mjs (no URL named)

    Aimed: a cache check with nothing to check; it must refuse before any request

    edge-cache-check.mjs: --url <url> or --base <origin> is required (or --selftest)

    usage: node edge-cache-check.mjs --url <url>[,<url>...] | --base <origin> --routes /,/about/

    Landed where it was aimed // exit 2

Run from a fresh unzip of the 1.1.0 download on Node 25, with any connection off the machine refused; the selftests serve their own pages on loopback. Indents and column padding trimmed; nothing else changed.

Who it’s for

Built for people who ship sites.

For
Developers, freelancers and small studios who make sites faster with an AI coding agent (Claude Code, Codex, Cursor, Gemini CLI) and need to know the site still works afterward.
Best fit
WordPress sites with a page cache and a speed plugin or two, and code-built sites (Vite, Astro, Next, plain HTML), where you can change the scripts, the images and the caching.
Works with
WP Rocket, Perfmatters and EWWW Image Optimizer with Easy IO, measured; LiteSpeed Cache, FlyingPress, Autoptimize, WP-Optimize and others from their docs. Cloudflare for the edge cache, on its Free plan. Node 18 or newer, Playwright and sharp; Lighthouse 13 needs Node 22.19.
Not for
A site on Shopify, Webflow, Squarespace or Wix, where the platform controls the server, the caching and how scripts load: the checks run on any public URL, but most fixes are out of reach, and none of it has been measured there. Slow handlers beyond the menu need a profiler’s trace.

Two skills, one pass.

site-speed-pass is the method on any site. wordpress-speed adds what a WordPress site needs on top of it. Each comes with lines from the selftest that proves it.

Explain it
  1. video-before-play.mjs --selftest

    ok a poster and preload="none": no media before play, poster requested (exit 0)

    ok preload="auto" downloads the video before play and fails (exit 1)

    ok a play button that does nothing fails as still paused (exit 1)

    20 cases behaved as designed

    Pass

    Measure, change one thing, prove it

    Lighthouse 13, the version PageSpeed Insights runs, and a byte census of what a phone downloads, all written down before anything changes. Then one kind of change at a time, and after each one: the phone menu opens on the first tap, video waits for play, signed-in pages stay out of the edge cache, and the layout doesn’t move.

    • site-speed-pass
  2. delay-exclusions.mjs --selftest

    ok WP Rocket plugin entries match by plugin folder, from paths seen on the pages

    ok a plugin that no page loads and nobody named is not matched

    ok a service is not offered because the page loads jQuery, which its entry also lists

    24 cases behaved as designed

    Pass

    WordPress, setting by setting

    Every cache layer and speed tool listed and backed up, one tool per job, and the delay exclusions WP Rocket and Perfmatters publish, read when it runs and matched to the plugins, theme and services the site runs.

    • wordpress-speed

What’s in the pack

Two skills and sixteen scripts. Your agent loads site-speed-pass for any speed work, and wordpress-speed beside it on a WordPress site.

  • site-speed-pass

    Faster, and proven

    Measure with Lighthouse 13 and a byte census, change one kind of thing at a time, purge and confirm what is served, then prove the menu, video, layout and edge cache before calling it done.

  • wordpress-speed

    WordPress speed, setting by setting

    The server checked first, every cache layer and speed tool listed and backed up, one tool per job, the vendors’ published delay exclusions, checkout left alone, and logged-in users checked for each tool.

Where it lands, and what it proves.

One download: the two skills for Claude Code, the same instructions to paste into any tool that reads AGENTS.md, their references, and the harness that proves each check can fail.

site-speed/

  • .claude-plugin/
    • plugin.json
  • ci/
    • pack.json
    • skill-frontmatter.mjs
    • speed-skills.mjs
    • verify.sh
  • CHANGELOG.md
  • install.sh
  • LICENSE
  • README.md
The files in site-speed/, as the download ships them.

Install it, then prove the pack works

install.sh copies both skills into ~/.claude/skills/, or you can load the whole folder as a Claude Code plugin. It copies, never links, and moves an existing folder aside with a timestamp instead of overwriting it.

ci/speed-skills.mjs is the pack’s own proof. It runs every selftest at the count its skill states, makes each of the pack’s own scripts refuse to run with no arguments, and breaks copies of the scripts on purpose; each broken copy must fail its selftest.

Every check can fail on purpose.

A check that has never failed is a green light with extra steps. Each script ships a selftest that serves pages with planted defects on loopback, and the harness breaks copies of the scripts to prove each selftest notices. Run them first, before you trust a clean result.

Building the pack found bugs in the checks it came from.

  1. A 3.8-second menu that opened in 20 msThe first timing ran in the test runner, which stalled while the page loaded its scripts. first-tap.mjs records the tap and the open menu inside the page and subtracts.
  2. A layout-shift failure that wasn’t realA local server sent no-store on fonts, so the masthead reflowed on every load and the gate failed a page that measures 0 live. The skill now says to suspect the harness first.
  3. 32 share images never checkedThe earlier asset check read 560 files on a live build and skipped same-origin absolute URLs, the share images among them. asset-audit.mjs read 592 on the same build, every one served.
Show the commands and what they must do

Run the controls

Shell
# with the Site Speed Pack unzipped at /path/to/site-speed, run these from a project with playwright and sharp. Nothing here leaves the machinenode /path/to/site-speed/skills/site-speed-pass/scripts/first-tap.mjs --selftest   # must report 19 cases behaving as designednode /path/to/site-speed/skills/site-speed-pass/scripts/video-before-play.mjs --selftest   # must report 20node /path/to/site-speed/skills/site-speed-pass/scripts/after-interaction.mjs --selftest   # must report 18node /path/to/site-speed/skills/site-speed-pass/scripts/edge-cache-check.mjs --selftest   # must report 24, no browser needednode /path/to/site-speed/skills/site-speed-pass/scripts/asset-audit.mjs --selftest   # must report 25, no browser needednode /path/to/site-speed/skills/wordpress-speed/scripts/delay-exclusions.mjs --selftest   # must report 24, no browser needednode /path/to/site-speed/ci/speed-skills.mjs   # from the same project, each broken copy must fail its selftest

I call these negative controls: a planted defect the check has to fail on. The harness removes the shadow-root hit test, the skip-cookie check, the data-* URL reader and the touch in the phone interaction, among others, and each broken copy must fail its own selftest. Without playwright, every browser check prints SKIP, never ok.

The check that has never failed is the one to distrust.

Works with the agent you already use.

The skills are plain text files your agent reads. The scripts are commented Node files, and they run on your computer.

  • Claude Code
  • Codex
  • Gemini CLI
  • Cursor
  • Windsurf
  • Aider
Shell
claude --plugin-dir /path/to/site-speed

The skills need nothing at all. The scripts need Node 18 or newer, with Playwright and sharp in the project you run them from; Lighthouse runs need Node 22.19 or newer. server-check.php runs in the site’s own PHP, through WP-CLI’s wp eval-file. For a WordPress site with no project of its own, an empty folder with a package.json is enough:

Shell
npm i -D playwright sharp && npx playwright install chromium

Everything the scripts touch

Your scratch folder
Reports, screenshots and JSON go only where --out, --dir or --json points. No script writes to the site, the repository or Cloudflare.
The pages you name
Read as a visitor would, at phone and desktop widths, in Playwright’s Chromium, or in Google Chrome for the video check when it’s installed.
Your build folder
asset-audit.mjs reads the folder you name, then sends a HEAD request, or a GET when a server refuses HEAD, for each image and font on the host you name. It never follows a redirect and never fetches another host.
The edge cache
edge-cache-check.mjs sends plain GET requests, some with the cookie values you pass, to tell a cached response from one that bypassed the cache.
Your WordPress server
server-check.php runs inside WordPress and reads PHP’s code cache, the database’s settings and counters, table sizes and the autoloaded options. It writes nothing, and prints names and sizes only: no credentials, keys or option values.
Two vendor lists
delay-exclusions.mjs reads WP Rocket’s exclusion list on GitHub and Perfmatters’ docs page each time it runs, or saved copies you pass.
The npm registry
lh.mjs runs Lighthouse 13 through npx, which fetches it on first use, unless LH_BIN points at a copy you installed.
The network
No telemetry, no license check, no phone-home. Each selftest serves its own pages on loopback.

Plain, commented JavaScript, nothing minified into a blob. A pack that says “don’t trust a report you can’t read” has to be readable itself.

One payment. Yours forever.

Site Speed Pack

$39.

  • One company, team or solo operator
  • As many computers and projects as you like
  • Change and adapt it freely
  • Keep the version you bought, forever
  • No subscription
  • Every future version of the Site Speed Pack included
  • 14-day refund, no questions

Please don't resell it or share it outside your company.

All-Access Bundle

Every pack, now and later.

Spotter Round, the Agent Setup Pack, the Email Pack, the WordPress Pack, the App Stack Pack, the Campaign Tracker Pack and the Site Speed Pack, plus every pack added after them, each with every future version.

$149.

The seven separately: $273

Get every pack — $149

Questions before you buy.

Which pack do I need?

Spotter Round if an agent writes your web pages: it proves the work before and after it ships. The Agent Setup Pack if you use more than one agent or more than one tool, or hand agents API keys. The Email Pack if you send HTML email. The WordPress Pack if you build on WordPress with Bricks. The App Stack Pack if you build web apps on Cloudflare Pages, Supabase or Stripe, or use SureContact or OttoKit on any site, WordPress included. The Campaign Tracker Pack if you run ads and want short links, leads, purchases and cost per lead tracked from the server, on any site behind Cloudflare. The Site Speed Pack if a WordPress or code-built site needs to be faster, with proof that the phone menu, forms, video and checkout still work after each change. The All-Access Bundle is every pack, now and later, for less than the seven together.

Does this work with Codex, Cursor, Gemini CLI, Aider, Windsurf?

Yes, if the agent can run commands in a terminal. The skills are plain text files and the scripts are plain Node. Claude Code loads the skills from its skills folder. Codex, Cursor and the rest take them pasted into your repository’s AGENTS.md, and Gemini CLI reads that file once its settings name it.

Which WordPress speed plugins does it cover?

Measured: WP Rocket, Perfmatters and EWWW Image Optimizer with its Easy IO CDN, setting by setting. From their docs and their own code, not yet run: LiteSpeed Cache, WP-Optimize, Autoptimize, W3 Total Cache, Hummingbird, Breeze, FlyingPress, WP Meteor and others, including what each one’s delay does with the first tap, and the popular image optimizers. Each line says how it was read, and a measured run promotes it.

Will it get my site to 100?

Maybe not, and it won’t chase it. The pass behind this pack took seven pages from 67–90 to 94–100 on mobile. The skill reports the metric beside the score, because 99 to 100 can be 200 ms and 78 to 86 can be 1.7 s, and a pass that raises the score and slows the first tap is worse than no pass.

Does it change my site?

The scripts never do: they read pages as a visitor would and print what they measured. Your agent makes the changes, one kind at a time, after backing up every speed setting, and writes down how to undo each one. Caching HTML at the edge waits for the site owner’s yes.

What about Shopify, Webflow, Squarespace or Wix?

The measurements and checks work on any public URL. The platform controls the server, the caching, how its scripts load and often the images, so many fixes are out of reach. The skill says which, and that none of it has been measured on those platforms.

Has it run on a real site?

Yes, two. A WordPress course and store site on November 5, 2026: mobile Lighthouse on seven pages from 67–90 to 94–100, LCP from 3.5–5.6 s to 1.3–3.0 s, the home page from 2,469 KB to 233 KB, desktop 100 on every page and layout shift 0 throughout. A code-built marketing site on Cloudflare Pages on September 10, 2026: mobile 100 on every audited page, and phone weight from 777 KB to 377 KB on the home page. The WordPress numbers are for the whole batch; no single setting was measured on its own.

Does it send anything anywhere?

No telemetry, no license check, nothing phoning home. The scripts read the pages you name, server-check.php reads your own server from inside WordPress, asset-audit.mjs checks files on your own host, delay-exclusions.mjs reads WP Rocket’s list on GitHub and Perfmatters’ docs page, and npx fetches Lighthouse 13 from npm unless you point LH_BIN at your own copy. The selftests never leave the machine.

Do I need Spotter Round too?

No. The measurement and fidelity scripts here are the same files as Spotter Round’s build-ab-harness and visual-fidelity-gate, shipped in this pack so it works on its own. Spotter Round adds post-deploy-proof, which checks the live site serves what you built after a deploy.

What do updates look like?

Numbered downloads with a list of what changed. Every future version of the Site Speed Pack is included at no charge, so you never pay for a new version, and you are never forced to update.

Can I use it for client work?

Yes, that’s what it’s for. One company covers every project that company delivers.

Refunds?

Fourteen days, no questions. A product about checking things that argued with you over a refund would be a poor advertisement for itself.

Measure it before you call it faster.

Sold separately

Six more packs. One job or stack each.

Each pack is sold on its own and ships its own checks, the same way this one does.

Spotter Round$39
Agent Setup Pack$39
Email Pack$39
WordPress Pack$39
App Stack Pack$39
Campaign Tracker Pack$39
All-Access Bundle$149

Spotter Round

$39

The layout, the pixels, the speed and the live deploy: your agent’s work, proven before it says it’s done.

1 / 7