Skip to content
Back to skills

a11y-toolkit

ASecurity

Use for ALL accessibility work — WCAG 2.2 audits of URLs or HTML, real rendered contrast checks (including text over images, pixel-level), color-pair contrast and nearest passing color, European Accessibility Act / RD 1112/2018 accessibility statements, pre-deploy regression detection (accessible names, tab order), aria-live announcement monitoring, keyboard/focus review. Triggers on "accessibility", "a11y", "WCAG", "contrast", "screen reader", "accesibilidad", "contraste", "auditoría", "EAA"...

  • 2 stars
  • 0 votes
  • 0 copies
  • 8 views
  • Added October 30, 2026
ai-agentsrustgobashexpressgit

Works with

  • cli
  • mcp

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 30, 2026

npx -y skills add kinti/a11y-toolkit --skill a11y-toolkit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of a11y-toolkit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for a11y-toolkit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kinti-a11y-toolkit/badge)](https://www.skillsdirectory.com/skills/kinti-a11y-toolkit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: a11y-toolkit
description: Use for ALL accessibility work — WCAG 2.2 audits of URLs or HTML, real rendered contrast checks (including text over images, pixel-level), color-pair contrast and nearest passing color, European Accessibility Act / RD 1112/2018 accessibility statements, pre-deploy regression detection (accessible names, tab order), aria-live announcement monitoring, keyboard/focus review. Triggers on "accessibility", "a11y", "WCAG", "contrast", "screen reader", "accesibilidad", "contraste", "auditoría", "EAA", "declaration", "declaración", "target size", "focus order", "aria".
---

# Skill: A11Y Toolkit — the WCAG 2.2 loop for agents

Audit → fix → document → watch, with zero-dependency tools. Prefer the MCP tools
(`a11y_*`) when the a11y-toolkit MCP server is connected; otherwise run the same
engine via `uvx` — no clone, no venv:

```bash
uvx --from a11y-toolkit a11ytoolkit pair "#1f2328" "#fbfaf7"          # color pair
uvx --from a11y-toolkit a11ytoolkit audit --url https://example.com   # static audit
uvx --from a11y-toolkit a11ytoolkit image hero.jpg --text "#fff" --region 120,40,420,90
uvx --from a11y-toolkit a11ytoolkit declaration --entity "Acme" --url https://acme.example --status partial --framework eaa --lang en --output decl.html
```

All output is English by default; pass `--lang es` (or the `lang: "es"` MCP argument) for Spanish.

## Decide in one step

| The user asks about… | Use |
|---|---|
| "is this site/page accessible?" | `a11y_audit_url` (fast, static, 0-100 score) then `a11y_audit_dom` if Playwright exists |
| real text contrast, incl. over images/gradients | `a11y_contrast_pair` / `a11y_contrast_image` / `a11y_audit_dom` (now pixel-samples image/gradient zones) |
| "measure THIS element against its background" (live page) | `a11y_contrast_dom` (url + selector: captures, samples, excludes text pixels — auto-region) |
| "what color passes AA here?" | `a11y_suggest_color` (target 4.5 normal, 3.0 large/UI) |
| legal accessibility statement (EU/Spain) | `a11y_generate_declaration` |
| "did the deploy break a11y?" | `a11y_snapshot` + `a11y_diff` (or `a11y_diff_urls`) |
| "what does the screen reader hear?" | `a11y_aria_live_snippet` injected via Playwright + the snapshot's focus order |
| keyboard/zoom/manual items | do them yourself as the agent — checklist in `references/wcag22-manual-checklist.md` |
| "what does criterion X.Y.Z mean?" | `a11y_criterion` (code like `1.4.3`, `2.5.8`) |
| "watch the site / only NEW regressions should block" | `a11ytoolkit budget`: accept the baseline once, then only new blocking findings fail (exit 2). Recipe: `examples/a11y-watch.yml` (weekly GitHub Action) |
| "put these findings in the PR / code scanning" | `a11ytoolkit sarif --from-audit audit.json -o a11y.sarif` → upload with github/codeql-action/upload-sarif |
| "a badge for the audited site" | `a11y_badge` (score + date + "automated screening" scope — never claims conformance) |
| "audit the section, not just one page" | `pages` parameter (or `a11ytoolkit audit --pages N`): sitemap-first same-domain crawl (links fallback), aggregated by mean/worst score |
| "the staging site is behind a login" | rendered tools accept `auth_state`: path to a Playwright storage_state JSON exported from a logged-in session — file stays local |
| "what does the W3C validator say?" | `a11y_html_validate` (Nu parser: doctype, structure, authoritative alt/lang/role; self-hosted vnu for sensitive pages) |
| "does the form explain what went wrong?" (3.3.1/3.3.3) | `a11y_forms`: fills invalid data, really submits, judges error identification/announcement in the post-submit DOM |
| "record what I verified by hand/agent" | pass `verified` (criterion codes) to `a11y_evidence`: they become agent-verified in the matrix; automated-fail never erases |
| "full evaluation / conformance / WCAG-EM" | the `conformance-wcagem` prompt — three tiers, escalate one at a time; protocol in `references/wcagem-guide.md` |
| "produce something a human auditor can sign" | `a11y_evidence`: the verifiable pack (criteria matrix + hashed artifacts + empty signature block). Vendor-neutral — any qualified human |
| "a VPAT for the US market (ADA)" | `a11y_generate_vpat`: VPAT 2.5 (WCAG edition) draft from the pack — Remarks auto-filled, levels Not Evaluated until a qualified human sets them (`overrides`) and signs (hash-referenced). Draft until signed |
| "a machine-readable ACR for US procurement (GSA OpenACR)" | `a11y_generate_openacr`: OpenACR YAML from the same pack — chapters A/AA, hyphenated adherence levels in the YAML, human sets them via `overrides` (same vocabulary as the VPAT). Render/validate in the GSA OpenACR editor |
| "export findings as ACT Rules / EARL" | `a11ytoolkit earl --from-audit audit.json -o earl.json` (curated ACT map; failures asserted, absence never asserted as pass) |
| "FIX it for me" (zoom blocked, missing autocomplete, missing lang/title) | `a11y_autofix`: deterministic safe fixes + the accessible form-error layer (3.3.1/3.3.3, skips forms with their own handling); judgment fixes come back as `not_applied` + remediation. Never promise overlay-style full fixes |
| "does it scroll sideways on mobile?" (1.4.10) | `a11y_reflow` (320px viewport, real overflow + offenders) — axe/Lighthouse don't automate this |
| "is the modal a keyboard trap?" (2.1.2) | `a11y_keyboard`: real Tab walk + cycle detection + Escape release test. Correct modals pass; traps are high severity |
| "infinite scroll / feed / more posts keep loading" | `a11y_scroll`: real scroll batches — focus survival (2.4.3), announcements (4.1.3), end or load-more (Deque/APG Feed). Best on feeds you own or can log into |
| "can a blind user actually DO this?" (task usability, not rules) | the `blindfold-task` prompt: attempt the task perceiving ONLY the accessibility tree — your browser's own accessibility snapshot each step (it preserves filled forms and open dialogs; `a11y_sr_transcript` once at start for the linearized prose) — acting by accessible name and keyboard; log friction per step; close with `a11y_journey_verdict` — scored pass/partial/fail/blocked, criteria-mapped, pack-ready (`report:journey`) |

## 1. Audit

`a11y_audit_url` = express static pass: 20+ signals across 17 WCAG criteria with a
weighted **0-100 score** (alt, accessible names, labels, autocomplete 1.3.5, keyboard
onclick, unknown ARIA roles, broken aria-labelledby, unnamed duplicated landmarks,
meta refresh, skip mechanism, lang validity, title, headings, zoom, captions, autoplay,
generic/duplicated link text, tabindex, aria-hidden-on-focusable, tables, duplicate ids,
accesskeys). Each finding carries a concrete `remediacion`. **Always relay finding +
remediation + WCAG criterion to the user, grouped by severity; quote the score with the
score_nota caveat.** When you need to explain a criterion, call `a11y_criterion`.

`a11y_audit_dom` = rendered audit in Chromium: computed text contrast against
effective backgrounds with alpha compositing (1.4.3), 24×24 minimum target size
(2.5.8 — new in WCAG 2.2), visible focus indicator heuristic (2.4.7),
**:focus/:hover state contrast** (disabled controls are WCAG-exempt — say so),
and **same-origin iframes scanned too**, same 0-100 score. If Playwright is
missing, fall back to the static audit and say so.

`a11y_audit_url` also accepts raw HTML you already fetched (`html` argument) —
audit without re-fetching.

**Honesty rule (non-negotiable):** automation ≈ 1/3 of WCAG. Every audit report
must say so and then cover what you CAN check manually as the agent — that is
what separates a real audit from a lint run. Use the manual checklist.

## 2. Fix contrast

Colors accept `#hex`, `rgb()`, `hsl()`, CSS color names; alpha composites over
the background. The pair tool returns per-criterion verdicts (1.4.3 AA, 1.4.6
AAA, 1.4.11 non-text) and the nearest passing color. Apply the suggestion to the
source, then re-verify the pair. For text over an image, NEVER trust a pair
check against a guessed color: screenshot the region and use `a11y_contrast_image`
— if `area_passes_aa_normal_text_4_5` < 100%, you need a scrim, a crop, or to move
the text (`worst_zone` tells you where).

## 3. Document (EU law)

`a11y_generate_declaration`: `framework="eaa"` for the European Accessibility Act /
Ley 11/2023 (private sector), `framework="rd1112"` for art. 10 RD 1112/2018 (Spanish
public sector). Collect missing legal fields (feedback contact, claim procedure,
evaluation method/dates) before generating; derive `inaccessible_content` from
audit findings. The statement must be linked from every page.

## 4. Watch regressions

Before deploy: `a11y_snapshot` (also captures the computed accessibility tree) → save
JSON. After: snapshot again, `a11y_diff` (now also reports accessibility-tree changes).
For continuous watching, set up the error budget: `a11ytoolkit budget --init` from today's
audit, then every run only flags NEW blocking signals — recommend it for every client.
`ok: false` = interactives added/removed/renamed or focus-order changed. Elements
without `id` are matched by tag+name+href — recommend stable ids for fine-grained
diffs. This is a great pre-deploy gate: audit + diff, then GO/NO-GO.

## 5. The aria-live monitor (arialive.js)

Inject via `page.evaluate` (Playwright) or as a bookmarklet; `lang` argument or
`window.ALM_LANG='en'` localizes the panel. It logs every live-region
announcement with time, politeness, role, text.

**Bug already fixed — do not reintroduce:** the panel must NOT carry `role="log"`
and must exclude itself from the MutationObserver; a `role="log"` panel matches
its own selector and creates an infinite self-observation loop that hangs the
page. If a run hangs, look for orphan chromium processes and retry.

## Blindfold golden rules (do not skip)

- Perception = accessibility tree ONLY. If a step needed something the tree
  didn't expose, that IS a finding — do not fall back to vision to "help".
- Navigate like a screen-reader user: HEADINGS and LANDMARKS first, Tab as
  the fallback. List them from each snapshot and jump by them — broken
  heading hierarchies and missing landmarks are findings (2.4.6 / 2.4.1),
  not inconveniences. This is the navigation real users run on every page.
- Keep the SAME browser tab across steps (state matters); snapshot after
  every action, before deciding the next.
- Log friction at the step it happened, with the pattern key — post-hoc
  reconstruction loses the sequence, and sequence is the evidence.
- Run journeys at 320px viewport for mobile too: the tree changes, and
  2.5.8/1.4.4-class failures show up only there.

## Notes

## Notes

- Images: Pillow if present, else macOS `sips`; PPM always — zero deps otherwise.
- The math is identical to the public web version: https://jquin.net/lab/
- Canonical source + MCP install: https://github.com/kinti/a11y-toolkit
- Test suites: `tests/test_audit.py`, `tests/test_contrast.py`, `tests/test_dom.py`, `tests/test_mcp.py` (plus v32/cli/solido).

Files in this skill

  • SKILL.md10.8 KB
  • references/wcag22-manual-checklist.md3.2 KB
  • references/wcagem-guide.md2.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.