feat: add webperf-core-web-vitals skill#1198
feat: add webperf-core-web-vitals skill#1198nucliweb wants to merge 18 commits intoChromeDevTools:mainfrom
Conversation
Design decision: agent-first scriptsThe scripts have been rewritten to be agent-first: all This reduced the total script code from ~1481 lines to ~623 lines. What was kept: element highlighting via Open question for reviewers: is the visual highlighting worth keeping, or should the scripts be pure data with zero side effects? Arguments either way:
|
Runs the skill in an isolated subagent so the main context only sees the final analysis result, not the intermediate script execution calls.
|
Added Tip via @lydiahallie. |
Scripts: - fix(LCP-Video-Candidate): apply activationStart correction to LCP value (bfcache navigations returned inflated values without this) - fix(LCP): use getComputedStyle for background image detection (inline style check missed CSS-driven backgrounds) - fix(CLS): add message field to synchronous return so agent knows to call getCLS() - fix(INP): remove misleading rating:"good" from no-interactions error case; preserve getDataFn so agent can retry after user interacts - feat(LCP, LCP-Sub-Parts, LCP-Trail): add window.__cwvHighlight flag to allow disabling visual element outlines without changing scripts Documentation: - docs(schema): document getINPDetails() with return schema and example - docs(schema): add INP error case (no interactions) to schema examples - docs(SKILL): add Error Recovery section with per-script guidance - docs(SKILL): add cross-skill fork note — cross-skill triggers are recommendations to report, not direct calls from the forked subagent - docs(SKILL): add Visual Highlighting section documenting __cwvHighlight - docs(SKILL): prefix cross-skill script references with skill name - docs(SKILL): document getINPDetails() step in INP debugging workflow
Review fixes — based on Anthropic skill-creator recommendationsThis commit applies improvements recommended by Anthropic's skill-creator after a full review of the skill scripts and documentation. Bug fixes
New feature:
|
|
@natorion please review! are we fine with adding skills based on scripts instead of the traces? |
If its stable, reliable and correct I think its at least fine to experiment with it and see how well it performs. A few things to consider:
|
There was a problem hiding this comment.
Apologies for the delay here!
A left a load of comments, but I've a bigger question on the approach here.
Devtools knows a lot of this information (whether from trace events or the Insights) so there's a question to me as to why we need to run JavaScript snippets to get that information. Shouldn't that be "built in" to DevTools MCP? Wasn't Performance one of the main use cases? What does this skill add that is not available there?
@natorion thoughts?
| 4. Cross-reference with **webperf-loading** skill: | ||
| - Resource-Hints-Validation.js (check for video preload) | ||
| - Priority-Hints-Audit.js (check for fetchpriority on video) |
There was a problem hiding this comment.
Should these be here? Ah I see these are part of #1114
| 4. Cross-reference with **webperf-media** skill: | ||
| - Image-Element-Audit.js (check format, dimensions, lazy loading) | ||
| 5. Cross-reference with **webperf-loading** skill: | ||
| - Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy) | ||
| - Priority-Hints-Audit.js (check for fetchpriority="high") | ||
| - Resource-Hints-Validation.js (check for preload) |
I agree with your point @tunetheweb. My approach here is to provide skills that extend the Web Performance metrics already available in DevTools. A key aspect is that these skills are deterministic. Instead of relying on higher-level abstractions, they execute well-defined JavaScript snippets, ensuring consistent and reproducible results across runs. This is something I’ve been exploring in more detail here: https://joanleon.dev/en/ai-web-performance-audits-scripts-reports/ As you know from my project WebPerf Snippets, the idea is to offer more specific, targeted scripts for certain use cases that aren’t always directly covered. After discussing it with @natorion, we decided not to include all the existing WebPerf Skills from the start, but instead introduce them gradually. It’s also possible that some areas, like Core Web Vitals, may not be the most relevant for this particular MCP. That said, thank you very much for the feedback, it’s really helpful and will definitely help improve WebPerf Skills. |
Co-authored-by: Barry Pollard <barrypollard@google.com>
Co-authored-by: Barry Pollard <barrypollard@google.com>
Discussed with with a few of the DevTools team. If non-determinism is a major issue then the whole concept of MCP has bigger problems 😀 I think a key aspect of these are that they can be run without needing a trace file, that is currently required to get the insights data. That does seem a compelling addition to me. So on that basis I'm in agreement with @natorion that this is worth experimenting with. There are still some outstanding issues from my review though: 1 snippet I'm not sure is relevant and also references to other snippets that won't land until after these. Can we address those questions and/or remove those snippets from this PR? |
- Remove LCP-Image-Entropy.js: low-entropy filter has been in Chrome stable since Chrome 112, making the script no longer actionable
- Update LCP-Video-Candidate.js: Chrome now considers the first frame of <video> elements as an LCP candidate. Add lcpSource ("poster" | "first-frame" | "unknown") to details, replace the missing-poster error with contextual info/warning based on lcpSource
- Remove cross-skill references to skills not yet available (webperf-loading, webperf-interaction, webperf-media). Decision trees now reference only scripts in this skill with general guidance where follow-up is needed
|
Hi @tunetheweb, thanks again for the thorough review! Here's a summary of what was addressed: Text/naming suggestions — all applied directly via GitHub's suggestion feature. The
Cross-skill references to |
tunetheweb
left a comment
There was a problem hiding this comment.
Content and advice looks good to me.
One small nit from me is there's still some inconsistency in Subparts (preferred), SubParts, sub-parts, in both the script name, and some of the references in the text, and in the variable names. If you could clean that up that would be great.
@natorion can you review for MCP integration perspective?
Rename LCP-SubParts.js → LCP-Subparts.js, update internal script
identifier ("LCP-Sub-Parts" → "LCP-Subparts"), rename calcSubParts →
calcSubparts, and fix all remaining LCP-Sub-Parts references in SKILL.md
|
Fixed! Renamed |
|
Instead of introducing a parallel skill, we should evolve the existing debug-optimize-lcp skill (or vice-versa - we should merge) into a unified web-performance skill. This provides a single entry point for the agent and a clearer escalation path from script-based auditing to trace-based forensics. Else an agent is just going to throw dice which of the two skills to take as the entry point. |
Motivation
Addresses the non-deterministic performance measurement problem raised in #1114. Instead of letting the LLM generate measurement code on the fly, this skill uses curated, deterministic JavaScript snippets from nucliweb/webperf-snippets executed via
evaluate_script.Benefits:
What's included
SKILL.mdDescribes the complete skill with:
webperf-loading,webperf-interaction,webperf-mediaScripts (7 total)
Core CWV metrics:
LCP.js— Measures LCP, highlights element, returns structured JSON synchronouslyCLS.js— Measures CLS from buffered entries, exposesgetCLS()for ongoing trackingINP.js— Tracking script; returns{ status: "tracking" }, thengetINP()after user interactionLCP diagnostics:
LCP-SubParts.js— Breaks down LCP into TTFB / Resource Load Delay / Resource Load Time / Element Render DelayLCP-Trail.js— Tracks all LCP candidate elements during load with color-coded outlinesLCP-Image-Entropy.js— Detects low-entropy images ineligible for LCP (Chrome 112+)LCP-Video-Candidate.js— Audits video LCP: poster presence, preload,fetchpriority, formatReferences
references/snippets.md— Human-readable descriptions and thresholds for each scriptreferences/schema.md— Structured JSON return schema for agent consumptionScript source and minification
Scripts are sourced from
nucliweb/webperf-snippets— specifically from the/snippets/CoreWebVitals/directory, which is the readable source.The
skills/directory in that repo contains Terser-minified build output (generated viascripts/generate-skills.js). The upstream rationale for minification is token optimization: smaller scripts mean fewer tokens consumed when the skill is loaded into context.For this MCP integration, we're using the unminified source for maintainability and reviewability. If token optimization becomes a concern, minification can be added as a build step later.
INP interaction workflow
INP requires real user interactions to measure. When
INP.jsreturns{ status: "tracking" }, the skill instructs the agent to:getINP()to collect resultsThe agent cannot simulate interactions on behalf of the user for this metric.
Relationship to existing
debug-optimize-lcpskillThe existing skill is a workflow guide that orchestrates MCP tools (trace recording, performance insights). This skill is script-based — it executes curated snippets and returns structured JSON. They are complementary: use
debug-optimize-lcpfor trace-based LCP analysis,webperf-core-web-vitalsfor script-based CWV measurement.Decision: no
!command`` injection in SKILL.mdClaude Code supports embedding shell commands in
SKILL.mdusing the!command`` syntax — the output is injected inline when the skill loads, so the agent receives the content without needing aReadtool call (reference).This was considered for injecting script contents directly into the prompt (e.g.
!`cat scripts/LCP.js`), which would eliminate the file-read step during execution. However, this feature is Claude Code-specific: other agents (Cursor, Windsurf, generic MCP clients) would receive the literal command string instead of its output, breaking the skill entirely.Since these skills target any MCP-compatible agent, we keep scripts as separate files read on demand. Cross-agent compatibility takes priority over saving a tool call.
Next skills
This is the first in the webperf skills series. Planned follow-ups (tracked in issue #1114):
webperf-loading(28 scripts: TTFB, FCP, render-blocking, fonts, resource hints…)webperf-interaction(8 scripts: INP deep-dive, Long Animation Frames, scroll jank…)webperf-media(3 scripts: image audit, video audit, SVG bitmap detection)webperf-resources(1 script: network bandwidth / connection quality)webperf(meta-skill)