CLI

WebPerf Snippets CLI

Run curated WebPerf Snippets headlessly via Playwright. Diagnose Core Web Vitals beyond what Lighthouse exposes and gate CI on real performance budgets.

WebPerf Snippets CLI

Why

Lighthouse gives you a score. The DevTools snippets give you the diagnosis, TTFB / Resource Load Delay / Element Render Delay sub-parts, LoAF script attribution, render-blocking resources, and more. The CLI runs the same curated snippets in a headless browser so you can:

  • Diagnose LCP regressions in CI without copy-pasting into DevTools.
  • Gate pull requests on real performance budgets.
  • Automate the snippets you already run by hand.

Install

Playwright is a peer dependency. Install both, then download the Chromium browser:

npm install --save-dev webperf-snippets playwright
npx playwright install chromium

Usage

npx webperf-snippets <url> [options]

Examples

Run the default Core Web Vitals workflow (LCP + CLS, plus LCP-Subparts when LCP exceeds 2.5s):

npx webperf-snippets https://web.dev

JSON output (for piping into jq or CI scripts):

npx webperf-snippets https://web.dev --json

Run a single snippet by alias:

npx webperf-snippets https://web.dev --snippet LCP-Subparts
npx webperf-snippets https://web.dev --snippet render-blocking
npx webperf-snippets https://web.dev --snippet fonts

Snippet aliases

AliasSnippetCategory
LCPLargest Contentful PaintCore Web Vitals
CLSCumulative Layout ShiftCore Web Vitals
LCP-SubpartsLCP Subparts breakdownCore Web Vitals
fontsFonts Preloaded, Loaded, and Used Above The FoldLoading
render-blockingFind render-blocking resourcesLoading
resource-hintsResource Hints ValidationLoading
preload-scriptsValidate Preload / Async / Defer ScriptsLoading
priority-hintsPriority Hints AuditLoading
critical-cssCritical CSS DetectionLoading
ttfbTTFB Sub-PartsLoading
script-partiesFirst and Third-Party Script InfoLoading
script-loadingScript LoadingLoading
lazy-atfAbove-the-fold lazy-loaded imagesLoading
lazy-conflictImages with lazy + fetchpriority conflictLoading
eager-below-foldNon-lazy images outside viewportLoading

Gate CI on performance budgets:

npx webperf-snippets https://web.dev --budget-lcp 2500 --budget-cls 0.1

Run the structural audit workflow:

npx webperf-snippets https://web.dev --workflow audit

Simulate a mobile viewport (default) or switch to desktop:

npx webperf-snippets https://web.dev --viewport mobile
npx webperf-snippets https://web.dev --viewport desktop

Show all items, including passing checks:

npx webperf-snippets https://web.dev --verbose

Options

OptionDescription
--workflow <name>Workflow to run. Default: core-web-vitals. Options: core-web-vitals, audit.
--snippet <name>Run a single snippet by alias or Category/Name path.
--jsonOutput JSON instead of formatted text.
--viewport <preset>Viewport preset. Default: mobile. Options: mobile, tablet, desktop.
--wait <ms>Post-load wait before evaluating snippets. Default: 3000.
--budget-lcp <ms>Exit 1 if LCP exceeds this value.
--budget-cls <score>Exit 1 if CLS exceeds this value.
--verboseShow all items, including passing checks.
--headedShow the browser window (debug).
-h, --helpShow help.

Exit codes

CodeMeaning
0All checks passed.
1Budget violation, or a snippet errored.
2Usage error (missing URL, unknown workflow).

CI Integration

GitHub Actions example, fail the PR if LCP exceeds 2.5s:

- run: |
    npm install --no-save webperf-snippets playwright
    npx playwright install --with-deps chromium
    npx webperf-snippets https://staging.web.dev --budget-lcp 2500 --budget-cls 0.1

How it works

  1. Launches headless Chromium via Playwright.
  2. Pre-registers PerformanceObservers for LCP and layout-shift before navigation.
  3. Navigates and waits for the page to settle.
  4. Evaluates each snippet's IIFE in the page context, capturing the returned object.
  5. Applies the workflow's decision tree to enqueue follow-up snippets.
  6. Renders results (human-readable or JSON) and exits with the appropriate code.

Known limitations

  • No INP: INP requires real user interactions. Synthetic interaction support is planned.
  • CLS in headless is conservative: layout shifts that only happen on scroll are missed unless you script the scroll.
  • First navigation only: each invocation runs one URL. SPAs need the post-route URL passed directly.
  • Decision-tree follow-ups re-navigate: when a follow-up snippet fires (e.g. LCP-Subparts), the page reloads. A shared page session is planned.

Further reading