Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add tmj-90/gaffer --skill frontend-performancegit clone --depth 1 https://github.com/tmj-90/gafferWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/tmj-90/gaffer/frontend-performance)<a href="https://agentmods.dev/skills/tmj-90/gaffer/frontend-performance"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/frontend-performance/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/tmj-90/gaffer/frontend-performance"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/frontend-performance.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00101 | $0.01790 |
| Opus 5.5 | $0.00040 | $0.00716 |
| Sonnet 5.5 | $0.00020 | $0.00358 |
| Haiku 4.5 | $0.00010 | $0.00179 |
Grade A, and why
frontend-performance scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 16d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 115 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Make the frontend fast, measurably
Performance is what the user's browser does: bytes shipped, main-thread work, layout shifts. Measure the right metric, find the biggest cost, subtract it, and measure again the same way. A change with no before/after number is not a performance fix.
The targets (web.dev Core Web Vitals)
Assessed on field data at the 75th percentile, mobile and desktop separately:
| Metric | Good | Poor | What it measures |
|---|---|---|---|
| LCP | ≤ 2.5 s | > 4 s | when the largest image/text block in the viewport renders |
| INP | ≤ 200 ms | > 500 ms | slowest-ish input → next paint across the visit (replaced FID in 2024) |
| CLS | ≤ 0.1 | > 0.25 | unexpected layout shift, largest session window |
Lab tools (Lighthouse) cannot measure INP; use Total Blocking Time as the lab proxy and a scripted interaction trace for the specific slow input.
Steps
- Pin the metric and the conditions. Name one metric from the ticket (LCP, INP, CLS,
route JS bytes gzipped, a component's commit time). Call
search_lorefor budgets and the measurement set-up. Record the baseline command and conditions, e.g.npx --no -- lighthouse <url> --preset=perf --form-factor=mobile --throttling-method=simulate --chrome-flags="--headless=new" --output=jsonrun 5 times (report the median), or the repo's Lighthouse CI / bundle analyzer /web-vitalsreport. Use a production build, never the dev server. Use only tools already installed (installs are hook-blocked; headless, plainnpxdownloads a missing package, so writenpx --no -- <tool>) — if none can measure the metric, say so in the evidence rather than guessing. - Diagnose by sub-part, not by guess.
- LCP = TTFB + resource load delay + resource load duration + element render delay.
Find which part dominates from the Lighthouse JSON (the LCP element and its phase
breakdown) or a Playwright/Chrome trace — you have no interactive DevTools. Common causes: the LCP image is
discovered late (CSS background, client-rendered,
loading="lazy"), render-blocking CSS/fonts/JS, slow server response. - INP = input delay + processing duration + presentation delay. Script the slow
interaction (Playwright plus a trace, or the
web-vitalsattribution build); look for long tasks (> 50 ms) before or inside the handler and for large re-renders or style/layout work after it. Theweb-vitalsattribution build (onINP(cb, { reportAllChanges: true })) names the element and phase. - CLS: the Lighthouse layout-shift audit or the
web-vitalsattribution shows which node moved. Usual causes: images/iframes/ ads without dimensions, late web fonts with different metrics, content injected above existing content, animations of layout properties. - Bundle: the analyzer (
vite-bundle-visualizer,@next/bundle-analyzer,source-map-explorer) shows the top modules per route.
- LCP = TTFB + resource load delay + resource load duration + element render delay.
Find which part dominates from the Lighthouse JSON (the LCP element and its phase
breakdown) or a Playwright/Chrome trace — you have no interactive DevTools. Common causes: the LCP image is
discovered late (CSS background, client-rendered,
- Fix the dominant cost — subtract first.
- LCP: server-render or statically render the hero; make the LCP image discoverable in
the HTML with
fetchpriority="high"and never lazy;preloadonly it and the one critical font; inline critical CSS or cut render-blocking CSS; cache the HTML/CDN where the data allows (thecaching-strategyskill). - INP: do less in the handler (update the visible state first, defer the rest); yield
between chunks of work (
await scheduler.yield()where supported, elsesetTimeout(0)); in React mark non-urgent updates withstartTransition/useDeferredValue; virtualise long lists; avoid forced synchronous layout (readingoffsetHeightafter writing styles in a loop); move heavy pure work to a Web Worker. - CLS:
width/heightoraspect-ratioon all media and embeds; reserve space for late content (skeletons at the final size); fonts withfont-display: optionalor a metric-matched fallback (size-adjust,ascent-override); animate onlytransformandopacity. - Bytes: route- and component-level code splitting (
import()); replace or deep-import heavy libraries; drop unneeded polyfills; defer third-party scripts; responsive images (srcset/sizes, AVIF/WebP) sized to their rendered box. - Also check back/forward cache eligibility (no
unloadhandlers, noCache-Control: no-storeon HTML without reason) — bfcache makes back navigations instant.
- LCP: server-render or statically render the hero; make the LCP image discoverable in
the HTML with
- Re-render storms (React/Vue). Count renders in a test (React
<Profiler>onRender, or the framework's equivalent) rather than interactive devtools; fix the cause (state too high, unstable props, context carrying fast-changing values) before adding memoisation. If the React Compiler is enabled, do not hand-addmemo/useMemo; if it is not, memoise only what the profiler shows is costly. - Measure again with the identical command and conditions, same number of runs; report median before/after and the spread. A change within run-to-run noise is not a win — say so.
- Guard it. Add or tighten the budget the repo uses (Lighthouse CI assertion,
size-limit, bundle-size check) for the metric you improved, so a regression fails CI. - Evidence via the
record-evidenceskill: the command, baseline and after medians, the dominant cost you removed, the bundle diff. Then stop.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 16d ago Changed · +51 lines 21bcd4979961
- 19d ago First seen · 64 lines · 101 tokens per session scan A e45750534140
frontend-performance is a skill published in the GitHub repository tmj-90/gaffer (2 stars, last pushed 17d ago), licensed Apache-2.0. It adds 101 tokens to every session and 1,790 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-28.
Other skills, from other repositories
maintaining-dev-playground
Keeps the Dev Playground current with the application. Use when editing UI components in apps/client/src/ — assesses playground candidacy, checks existing playground coverage, and guides adding or updating showcases. Also use when directly editing files in apps/client/src/dev/, building new widgets or features, or…
styling-with-tailwind-shadcn
Implements the Calm Tech design system using Tailwind CSS v4 and Shadcn UI. Use when writing styles, building components, or theming. For design decisions, see designing-frontend.
bulwark-brainstorm
Role-based brainstorming with dual modes: --scoped (sequential Task tool, 5 roles) and --exploratory (Agent Teams peer debate, 4 roles). Use for feasibility assessment and idea validation.
plan-creation
Create structured implementation plans via a 4-role scrum team (Product Owner, Architect, Eng/Delivery Lead, QA/Critic) with optional Agent Teams peer debate mode.
anthropic-validator
Validates Claude Code assets (skills, hooks, agents, commands, MCP servers, plugins) against official Anthropic standards. Fetches latest docs dynamically and produces structured validation reports.
create-subagent
Generates single-purpose Claude Code sub-agents for use via the Task tool. Use when creating dedicated sub-agents, scaffolding agent definitions, or generating agents with diagnostics and permissions setup.