a11y-pass
v0.3.0
Published
Static accessibility audit for code and design. WCAG 2.2 AA, severity-tiered, zero deps.
Maintainers
Readme

a11y-pass
Static accessibility audit for code and design. Zero deps. Severity-tiered output. CI-friendly exit codes.

Install
As a Claude Code plugin
/plugin marketplace add incomparable-design/a11y-pass
/plugin install a11y-pass@incomparable-designAs a CLI
npx a11y-pass src/**/*.tsxOr install globally:
npm install -g a11y-pass
a11y-pass src/**/*.tsxBy clone
git clone https://github.com/incomparable-design/a11y-pass
node a11y-pass/scripts/audit.mjs your-file.tsxRun directly
node scripts/audit.mjs fixtures/bad.tsx
node scripts/audit.mjs fixtures/page.html --json
node scripts/audit.mjs "src/**/*.tsx" # via shell glob expansiona11y-pass --help lists all flags. Supports --json, --diff [base], --config <path>, --fix, --dry, --standard=AAA, --version.
Exit codes:
0— no blockers1— at least one blocker (CI gate)2— usage error
PR-aware CI
Audit only files changed against a git base:
a11y-pass --diff origin/mainDefaults to origin/main if base omitted. Returns non-zero on blockers, suitable for pull_request workflows.
As a Claude skill
SKILL.md defines invocation rules. Drop the dir into .claude/skills/a11y-pass/ of any project. Claude loads it when user mentions a11y / accessibility / WCAG, runs the script, formats output, and offers fixes via Edit tool.
Rules (19)
| ID | Severity | WCAG |
|----|----------|------|
| img-alt | blocker | 1.1.1 |
| btn-name | blocker | 4.1.2 |
| link-name | blocker | 2.4.4 |
| color-contrast | blocker | 1.4.3 (AA) / 1.4.6 (AAA) |
| link-text | serious | 2.4.4 |
| iframe-title | serious | 4.1.2, 2.4.1 |
| empty-heading | serious | 1.3.1, 2.4.6 |
| interactive-role | serious | 4.1.2 |
| label-missing | serious | 1.3.1, 3.3.2 |
| heading-skip | serious | 1.3.1, 2.4.6 |
| outline-none | serious | 2.4.7 |
| focus-visible-removed | serious | 2.4.7 |
| duplicate-id | serious | 4.1.1 |
| role-invalid | serious | 4.1.2 |
| redundant-aria | moderate | 4.1.2 |
| autoplay | moderate | 1.4.2 |
| target-size | moderate | 2.5.8 |
| table-caption | advisory | 1.3.1 |
| lang-attr | advisory | 3.1.1 |
See SKILL.md for invocation flow + fix policy.
Config
.claude/a11y.config.json:
{
"standard": "AA",
"ignore": ["target-size"],
"severityOverrides": { "lang-attr": "moderate" }
}Fixtures
fixtures/bad.tsx— every rule firesfixtures/good.tsx— passes cleanfixtures/page.html— plain HTML violations
Known limits
- Regex-based JSX parsing — no AST. Misses nested same-tag bodies and dynamic strings.
- Color contrast covers the full default Tailwind v4 palette, inline
stylecolors, and statically-resolvable className values (string literals and template literals without${}interpolation). Ternary expressions and other dynamic forms are skipped. - No runtime DOM checks. Pair with axe-core/Playwright for URL targets.
- Does not trace
aria-labelledbyIDs across files.
Roadmap
- AST parser to widen color contrast and label association coverage.
- Component-aware checks (e.g. design system
<Button>→ native button rules). - Cross-file
aria-labelledbyID resolution.
