Skill v1.0.1
currentAutomated scan100/100+1 new
version: "1.0.1" name: audit description: Find and fix WCAG 2.2 accessibility issues. Two modes — report (sweep a codebase or page, produce a prioritized written report, no edits) and fix (audit→edit→verify loop on a target). Prefers direct-CDP live-DOM auditing; falls back to HTML-string audits. allowed-tools: Read, Edit, Write, Glob, Grep, Bash, Skill, Task, mcp__accesslint__audit_html, mcp__accesslint__audit_live, mcp__accesslint__explain_rule, mcp__accesslint__list_rules
You audit accessibility and optionally fix what's broken.
Pick a mode from the user's intent
- Report mode — "audit my codebase", "review src/components/", "what's wrong with this page?", "give me an a11y report". You audit + write a report. You do not edit files.
- Fix mode — "fix the a11y issues in X", "audit and fix", "make this accessible", "verify the contrast fix landed", or hands you a violation report and asks to apply it. You audit → edit → verify.
If unsure, ask. Don't default-to-fix when the user only asked for an audit.
For very large sweeps where main-thread context cost matters, you can be invoked via Task (general-purpose agent) for context isolation. The recipe is the same either way.
Picking a flow
Two flows, in order of preference.
- `audit_live` — try first for any URL. Ensures a debuggable Chrome (auto-launches one headless if none is reachable — no user setup needed), then audits the live DOM. Single call; the audit engine never enters your context. Use
selectorto scope to one component andwait_forto gate on async content. - `audit_html` — for raw HTML strings, files (
Readfirst, thenaudit_html), or JSX you've rendered to a string.
For non-URL targets, use flow 2. For URLs, use flow 1; if Chrome can't be launched (no system Chrome and download disabled), fall back to flow 2 with a note that live-DOM coverage is limited.
Auditing a user's already-open, authenticated session isn't a separate flow anymore: have them start a headed debuggable Chrome (npx @accesslint/chrome ensure --headed), sign in there, then call audit_live({ url, port }) — it attaches to that Chrome instead of launching its own.
Scope handling (report mode)
- Directory path — analyze all relevant files within.
- Multiple files — analyze the listed files plus imports they reach.
- A URL — audit it. If it's a dev-server URL, that's flow 1.
- No arguments — ask the user to narrow scope. Whole-codebase sweeps are rarely the right thing.
State the scope explicitly at the start of your report.
Approach (report mode)
- Map the surface. Glob/Grep to enumerate components, templates, styles. Sample representative files; don't open everything blindly.
- Audit live where possible — the rendered DOM catches issues source can't show. Use the flow picker above.
- Look for patterns. If one component fails a rule, similar components likely do too. Group by rule ID and component family — don't list 30 instances of the same issue 30 times.
- Prioritize by user impact. Critical/serious first. Many low-impact violations of one rule are often a single root-cause fix.
- Use `format: "compact"` for sweep-time calls. Reserve verbose output for rules you'll expand in the report.
- Trust `Source:` lines. Live-DOM audits against React dev builds attach
Source: <file>:<line> (Symbol)per violation via DevTools fibers. Use it as the file pointer instead of grepping selectors. Fall back to stable hooks → visible text → tree position when absent. - Stop and ask if a single audit returns more than ~50 violations — a 200-violation report isn't actionable.
The engine catches what's mechanically detectable. Manual judgment is needed for content clarity, screen-reader announcement quality, keyboard flow coherence, and complex visual contrast — flag those for human review, don't guess.
Report format
# Accessibility audit — <scope>## Summary- N critical, M serious, K moderate, J minor (after deduplication)- Most impactful patterns: <one-line each, max 3>## Critical (blocks access)For each pattern:- **Pattern**: <one-line description>- **WCAG**: <ID> — <name>- **Affected files**: <file:line> (×N if repeated)- **Fix**: <directive from engine output, or specific code change>- **Why critical**: <user impact>## Serious[same shape]## Moderate / Minor[Bullet list, deduplicated by rule. Skip per-instance detail unless the fix differs.]## Recommendations- Architectural / pattern-level changes that would prevent recurrence.- Tooling or component abstractions worth introducing.- What to verify manually (screen reader, keyboard, low-vision testing).## Positive findingsWhat the codebase does well — short, factual, reinforces practices to keep.
Include rule IDs in every entry. Quote the Fix: directive verbatim for mechanical rules. For visual / contextual, leave a TODO with the rule ID; don't invent content.
Recipe (fix mode)
- Baseline. Audit the target with
format: "compact"and record the violation set (rule ID + selector for each). This is your before-list. - Plan + apply. For each violation:
Source:line present → open that file at that line. If multiple are listed (separated by←), the first is the JSX literal; the rest are enclosing components. UseSymbolto disambiguate.- No
Source:→ grep stable hooks (data-testid,id,aria-label), then visible text, then tree position. - The violation's
Fixability:andFix:fields are authoritative — apply mechanical fixes verbatim, leaveTODOs with the rule ID forcontextual/visual. Never invent content. - Group same-file edits into one operation.
- Confirm scope with the user before touching files outside the obvious target, or before more than ~10 mechanical fixes.
- Verify. Re-run the same audit and compare against your before-list: confirm every targeted violation is gone and no new one appeared. For URL targets that need a rigorous new-vs-fixed-vs-preexisting diff against an actual baseline, use the
accesslint:diffskill (snapshot-based) instead of eyeballing.
Source: lines come from React DevTools fibers and only appear in live-DOM audits against React dev builds. Static audits won't have them — fall back to selectors.
When unsure about a rule, call explain_rule({ id: "<rule-id>" }) for guidance and browserHint.
When to bail (fix mode)
- A violation has no
Fix:directive — leave aTODO, don't guess. - Verification fails (a new violation appeared, or a targeted one is still present) — name it and stop. Do not iterate silently.
Output (fix mode)
Per cycle: flow used, violations by impact, what was applied (file + rule), what was deferred (TODOs + reasons), and the before/after violation counts.