Install
$ agentstack add skill-kevin-burns-claude-skills-ux-audit ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
UX Audit
Audit an existing, rendered page against a fixed rubric and return findings the caller can act on. The discipline that makes this useful: audit what's actually on screen, cite the heuristic or success criterion, and propose a concrete fix. A finding with no location and no fix is noise; a "problem" you assumed without observing the page is worse.
This is distinct from neighbours:
- design-council deliberates one high-stakes design decision (preserves dissent).
Use it for "should we restructure this flow?", not "audit these 12 pages."
- webapp-testing checks that features work. UX audit checks whether they're *usable
and accessible* even when they work.
Inputs you need
- The page(s): a URL, a local file, or a running dev server. For a series of pages, the
ux-auditor agent fans out — one auditor per page (see that agent).
- The page's goal — what is the user there to do? You can't judge usability without it.
If not given, infer it from the page and state your assumption in the finding set.
- Viewports to check (at least one mobile ~375px and one desktop ~1280px). Responsive
problems only show up if you actually resize.
Render the page first — don't audit blind
Audit the rendered DOM and the visual result, not the raw source. Use whatever browser driver is installed (prefer agent-browser, fall back to playwright-cli; the CLI binary is playwright-cli, not playwright):
# preference order — use whichever exists
if command -v agent-browser >/dev/null 2>&1; then echo agent-browser
elif command -v playwright-cli >/dev/null 2>&1; then echo playwright-cli
else echo NONE; fi
For each page capture: a screenshot at each viewport, the rendered HTML/DOM, and (where the driver allows) computed styles for contrast and a tab-order walk for keyboard checks. The screenshot is your evidence; reference it in findings.
Isolate the session — the #1 cause of bad audits under fan-out. Both drivers default to a single shared browser session via a background daemon. When several audits run at once (the fan-out pattern), they collide on that shared session and you get cross-contamination — evals returning another page's DOM. Always give each audit its own named session and close it when done. This, not the tool, is what broke an early run of this skill.
Time-box the driver. If it still doesn't render cleanly within a few tries, switch drivers or drop to a static audit and say so — don't sink 30 calls into fighting it.
agent-browser recipe (preferred — handles local files and concurrency cleanly)
S="uxaudit-$$" # unique session per audit (fan-out safe)
agent-browser --session "$S" --allow-file-access open "file:///abs/path/page.html"
agent-browser --session "$S" --allow-file-access open "https://example.com" # remote too
- Local files load directly with
--allow-file-access— no HTTP server needed. evalvia--stdinavoids all shell-quoting corruption (the trap that wastes calls);
return a string with JSON.stringify(...): ``bash agent-browser --session "$S" eval --stdin { const noAlt = Array.from(document.images).filter(i => !i.alt).length; const p = document.querySelector("p"); const s = getComputedStyle(p); const b = document.querySelector("button"); const r = b.getBoundingClientRect(); return { noAlt, color: s.color, bg: s.backgroundColor, target: r.width + "x" + r.height }; })()) EOF ``
- Evidence & viewports:
snapshot -i(a11y refs/roles),screenshot --annotate
(numbered labels — ideal for icon-only buttons), screenshot --full. For mobile, set viewport via config/flags or audit at the iOS profile (-p ios).
- Always
agent-browser --session "$S" closewhen done.
playwright-cli recipe (fallback — binary is playwright-cli, not playwright)
- Serve local files over HTTP —
file://URLs often don't load. Start a throwaway
server and target http://localhost: ``bash ( cd "$DIR" && python3 -m http.server 8731 & ) # or uv run python -m http.server playwright-cli open # start the browser playwright-cli goto "http://localhost:8731/page.html" # goto, not open-with-arg ` open may stay on about:blank; always goto explicitly after open`.
evaltakes a function and the value prints under### Result. Use() => ...
form; a bare expression containing => is misparsed as a function-to-apply. Return a string (JSON.stringify(...)) so the result is unambiguous: ``bash playwright-cli eval "() => { const b=document.querySelector('button'); const r=b.getBoundingClientRect(); return JSON.stringify({w:r.width,h:r.height}); }" ``
- High-yield evals: images missing
alt, inputs whose.labelsis empty, computed
color/backgroundColor for contrast, getBoundingClientRect() for target size.
- Viewports & evidence:
playwright-cli resize 375 812thenscreenshot, repeat at
1280 900. playwright-cli snapshot dumps the accessibility tree (names/roles).
- Always
playwright-cli closewhen done.
If no driver is installed (or you abandoned a flaky one), set "driver": "static-only", audit the static HTML + any screenshot the user provides, and flag in notes that dynamic/contrast/keyboard/viewport checks were not performed. An honest partial audit beats a guess.
The rubric
Walk all three lenses. Don't stop at accessibility — usability and responsiveness catch different failures.
1. Nielsen's 10 usability heuristics
- Visibility of system status — does the UI show what's happening (loading, saved,
selected, where-am-I)?
- Match with the real world — language/concepts the user knows, not system jargon.
- User control & freedom — undo, cancel, back, clear exits from unwanted states.
- Consistency & standards — same thing looks/acts the same; platform conventions.
- Error prevention — constraints, confirmations, sensible defaults that stop mistakes.
- Recognition over recall — options visible; don't make users remember across steps.
- Flexibility & efficiency — accelerators for experts without blocking novices.
- Aesthetic & minimalist design — no competing clutter; signal over noise.
- Help users recover from errors — plain-language errors that say what and how to fix.
- Help & documentation — findable, task-oriented help where needed.
2. WCAG 2.2 — target Level A & AA
Check the high-yield criteria first:
- Text alternatives — meaningful
alton informative images; emptyalt=""on
decorative ones.
- Contrast (1.4.3 / 1.4.11) — text ≥ 4.5:1 (≥ 3:1 for large text ≥ 18.66px bold /
24px); UI components & graphics ≥ 3:1. Measure from computed colours, don't eyeball.
- Keyboard (2.1.1) & focus visible (2.4.7) — everything operable by keyboard; a
visible focus indicator; logical tab order; no keyboard traps.
- Labels & names (1.3.1 / 4.1.2) — form controls have associated ``s; controls
expose an accessible name; ARIA used correctly (or not at all).
- Headings & structure (1.3.1 / 2.4.6) — one logical heading outline; landmarks
(main, nav, header); descriptive page ``.
- Target size (2.5.8, new in 2.2) — interactive targets ≥ 24×24 CSS px (or spaced).
- Resize/reflow (1.4.10) — usable at 320px width / 400% zoom without horizontal scroll.
- Don't rely on colour alone (1.4.1) — state shown by more than hue.
3. Responsive & device behaviour
- Layout holds at mobile (~375px) and desktop (~1280px); no overflow, overlap, or cut-off
controls. Tap targets aren't cramped. Content reflows rather than requiring zoom/scroll.
Severity — so the caller can triage
Match the fleet's review scale (same as code-reviewer):
- blocking — users can't complete the page's goal, or a WCAG Level A failure shuts
out a group (e.g. unlabeled critical control, keyboard trap, no alt on the only CTA icon).
- major — serious friction or a WCAG AA failure (contrast below 4.5:1, focus not
visible, confusing error with no recovery).
- minor — polish: inconsistency, clutter, small-but-real friction.
Reserve blocking for "this stops someone," and back every finding with what you observed.
Return format (final message) — JSON only
One object per audited page. (When fanned out, the agent merges these.)
{
"page": "url-or-path",
"goal": "what the user is here to do (stated or inferred)",
"viewports_checked": ["375x812", "1280x900"],
"driver": "agent-browser | playwright-cli | static-only",
"summary": { "blocking": 0, "major": 0, "minor": 0 },
"findings": [
{
"severity": "blocking | major | minor",
"lens": "usability | accessibility | responsive",
"ref": "Nielsen #5 | WCAG 1.4.3 | responsive@375px",
"location": "selector or region, e.g. 'form#signup > button.submit'",
"evidence": "what you observed (+ screenshot ref / measured value)",
"suggested_fix": "concrete change to make",
"confidence": "high | medium | low"
}
],
"notes": "assumptions, what couldn't be checked, empty if none"
}
Be precise over exhaustive. Ten located, fixable findings beat forty vague ones. If you couldn't render the page, say what you could and couldn't assess rather than inventing problems.
Privacy
The audited pages and any findings about a specific product are often the client's property — keep the page content and results out of any shared/committed location. This skill and the ux-auditor agent are generic and publishable; the data they process is not.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kevin-burns
- Source: kevin-burns/claude-skills
- License: MIT
- Homepage: https://techblog.kevinburns.de
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.