Lighthouse Audits skill for Codex

Median-of-five runs and CI assertions that hold. Codex runs Lighthouse against production builds with recorded conditions, takes the median of five runs, and explains a low score through the metric weights and the Lighthouse 13 insight audits rather than the generic checklist. For CI it writes lighthouserc.json assertions on LCP, TBT, CLS and resource sizes with headroom, keeps reports out of public storage unless you agree, and handles logged-in pages.

  • Performance
  • $lighthouse-audits
  • 172 lines
  • 2 files
  • ~1,900 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- lighthouse-audits

Installs to ~/.agents/skills/lighthouse-audits/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $lighthouse-audits, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Runs Lighthouse and Lighthouse CI properly - repeatable settings, median-of-N runs, lighthouserc assertions on metrics and resource sizes, GitHub Actions wiring - and reads the report the way a performance engineer does, from metric weights and insights to the actual fix. Use when asked to run a Lighthouse audit, explain a low performance score, set up lhci in CI, fail a PR on a score or metric drop, or audit pages behind login with user flows.

Use it when

  • Someone asks for a Lighthouse audit or to explain a performance score
  • You want lhci in CI with assertions on scores, metrics or resource sizes
  • Scripts that parse Lighthouse JSON broke after an upgrade to Lighthouse 13

Use something else when

  • Field data already shows which Core Web Vital fails and you need the fix: use core-web-vitals
  • You want budgets across bundles, APIs and Lighthouse in one CI policy: use performance-budgets

How to check the result

Before and after medians come from five runs on the same machine and settings, and lhci autorun exits non-zero when a seeded regression breaks an assertion.

The mistake it prevents

Comparing single runs from different machines or against a dev server and reading a 6-point swing as a real change.

~/.agents/skills/lighthouse-audits/SKILL.md

--- name: lighthouse-audits description: Runs Lighthouse and Lighthouse CI properly - repeatable settings, median-of-N runs, lighthouserc assertions on metrics and resource sizes, GitHub… license: MIT ---

A Lighthouse result is useful when the run conditions are stated (device, throttling, cache, Lighthouse version), the number comes from several runs rather than one, and every recommendation is traced to the metric it moves. A single local score is noise.

How the performance score is built

Lighthouse 10 and later weight five lab metrics:

MetricWeightGood (mobile)Mostly moved by
Total Blocking Time30%≤ 200 msLong JS tasks during load: bundle size, hydration, third-party
Largest Contentful Paint25%≤ 2.5 sServer time, LCP resource discovery and size, render-blocking CSS
Cumulative Layout Shift25%≤ 0.1Unsized media, injected content, font swaps
First Contentful Paint10%≤ 1.8 sRender-blocking resources, TTFB
Speed Index10%≤ 3.4 sOverall visual progress

Each metric is mapped to a 0–100 score on a log-normal curve, so the last points near 100 are expensive. Go for the heaviest failing metric first: TBT and LCP usually.

Lighthouse 13 (Oct 2025) replaced most diagnostic audits with insight audits that match the DevTools Performance panel (lcp-phases-insight, lcp-discovery-insight, render-blocking-insight, third-parties-insight, image-delivery-insight, cls-culprits-insight, document-latency-insight, and others). Scoring did not change, but scripts that read old audit IDs such as render-blocking-resources or uses-long-cache-ttl from JSON break. Lighthouse 13 needs Node 22.19+.

Workflow

- [ ] 1. Decide the question: diagnose one page, compare before/after, or gate CI
- [ ] 2. Fix the run conditions (table below) and record them
- [ ] 3. Run 5 times, take the median run
- [ ] 4. Read metrics -> insights -> trace; map each finding to a metric
- [ ] 5. Fix, re-run with identical settings, compare medians
- [ ] 6. If gating: write lighthouserc assertions with headroom over today's median

Running it

# Needs network for npx and the target. Mobile is the default form factor.
npx lighthouse https://staging.example.com/ \
  --only-categories=performance \
  --output=json --output=html --output-path=./lh/home \
  --chrome-flags="--headless=new"

npx lighthouse https://staging.example.com/ --preset=desktop ...   # desktop profile
ConditionDefaultRule
ThrottlingSimulated (Lantern) slow 4G + 4x CPUKeep it for comparisons; --throttling-method=devtools only to debug a simulation artefact
MachineWhatever runs itSame machine class for before/after; CI runners are noisy, so use medians
CacheColdLighthouse always clears storage unless --disable-storage-reset
ExtensionsLocal Chrome profile may have themHeadless or a clean profile; extensions inflate TBT
TargetDev serverNever audit a dev server (unminified, HMR); build and serve production output

Variance of ±5 points between runs is normal. Five runs and the median run is the minimum for any decision; LHCI does this with numberOfRuns.

Reading the report

  1. Metrics: which weighted metric is furthest from good?
  2. Insights for that metric. LCP -> lcp-phases-insight (which phase), lcp-discovery-insight (lazy, late discovery, no fetchpriority). TBT -> main-thread work, JS execution time, third-parties-insight, legacy-javascript-insight, duplicated-javascript-insight. CLS -> cls-culprits-insight, unsized-images.
  3. Open the trace (DevTools “View Trace”, or save with --save-assets) when an insight is vague. Long tasks have stack attribution there.
  4. Translate to code: file, component, script tag, server route.

Phase-level fixes for LCP, INP and CLS are in $core-web-vitals; JS weight in $bundle-size-reduction; third-party cost in $third-party-scripts.

Lighthouse CI

Install as a dev dependency so CI is pinned: npm i -D @lhci/cli (needs network). LHCI bundles its own Lighthouse version; check npx lhci --version and its changelog before asserting on insight audit IDs.

lighthouserc.json:

{
  "ci": {
    "collect": {
      "startServerCommand": "npm run start",
      "startServerReadyPattern": "ready",
      "url": ["http://localhost:3000/", "http://localhost:3000/products/demo"],
      "numberOfRuns": 5,
      "settings": { "onlyCategories": ["performance"] }
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.85, "aggregationMethod": "median-run" }],
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500, "aggregationMethod": "median" }],
        "total-blocking-time": ["error", { "maxNumericValue": 300, "aggregationMethod": "median" }],
        "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1, "aggregationMethod": "median" }],
        "resource-summary:script:size": ["warn", { "maxNumericValue": 350000 }],
        "resource-summary:third-party:count": ["warn", { "maxNumericValue": 10 }]
      }
    },
    "upload": { "target": "filesystem", "outputDir": "./.lighthouseci/reports" }
  }
}
npx lhci autorun        # collect + assert + upload
npx lhci collect --staticDistDir=./dist   # static sites: LHCI serves the folder itself
  • Prefer explicit assertions over the lighthouse:recommended preset; presets reference audit IDs that change between Lighthouse majors.
  • upload.target: "temporary-public-storage" publishes reports to a public URL. Ask the user before enabling it; staging pages can contain unreleased content. Default to filesystem plus CI artifacts, or a self-hosted LHCI server.
  • Set thresholds from today’s median with headroom (score minus 5, metrics plus 10–15%), then ratchet. A gate that flaps gets disabled. See $performance-budgets.

GitHub Actions (pin action versions to a commit SHA in real use):

- run: npm ci && npm run build
- run: npx lhci autorun
- uses: actions/upload-artifact@v4
  if: always()
  with: { name: lighthouse, path: .lighthouseci }

Pages behind login or after interaction

  • LHCI collect.puppeteerScript runs a script before each URL; use it to log in with a test account from the project’s fixtures, never a real user’s credentials.
  • Lighthouse user flows (startFlow from the lighthouse npm package with Puppeteer) measure navigation, timespan (interactions, gives INP-like data) and snapshot modes in one report. Use timespan mode to audit a click-heavy flow.

Gotchas

  • PageSpeed Insights lab numbers come from Google’s servers and differ from your local run; its field section is CrUX and is what Search uses.
  • Score 100 on desktop with simulated throttling says little about mid-range Android.
  • A redirect on the audited URL (http -> https, trailing slash) adds to every metric. Audit the final URL.
  • Cookie banners and interstitials change LCP and CLS. Decide whether to audit with or without consent state, and keep it consistent.
  • Do not chase the “unused JavaScript” byte count blindly; split code only on routes where TBT or LCP is failing.

Report template

## Lighthouse: <URL> (<mobile|desktop>, Lighthouse <version>, median of 5)
Score: 62 (before) -> 81 (after)
| Metric | Before | After | Weight |
|---|---|---|---|
| TBT | 820 ms | 240 ms | 30% |
| LCP | 4.1 s | 2.6 s | 25% |
Top findings -> fixes:
1. <insight id>: <what it showed> -> <code change, file>
Conditions: <machine, throttling, server, commit>
Field data (CrUX/RUM) still pending: <yes/no>

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Lighthouse Audits"
  short_description: "Median-of-five runs and CI assertions that hold"
  default_prompt: "$lighthouse-audits Why is our Lighthouse performance score 58 on mobile and what should we fix first?"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
New

Introducing Codex Skills Pro

79 professional skills that take Codex through complete engagements, each with its own scripts, references and a report that verifies the result.

All-AccessOne-time payment, no subscription
$49
Get All-AccessOr browse individual skills from $2.99 →

Secure checkout by Creem