Accessibility is the distance between intention and outcome. Accessibility Devkit helps shorten that distance with portable checks, focused browser utilities, and a review workflow that says exactly what still needs a browser, assistive technology, or a person.
Accessibility Devkit ships no overlay and assigns no accessibility score. A clean result only means the covered checks found nothing. You still need the listed browser, assistive-technology, and human verification.
Use either runtime. The commands, JSON schema, findings, and exit codes match.
npx @accessibility-devkit/cli contrast '#595959' '#ffffff'
pipx run accessibility-devkit contrast '#595959' '#ffffff'Scan local HTML and add the profiles that need more than a generic source check:
npx @accessibility-devkit/cli scan ./index.html --profile all
pipx run accessibility-devkit scan ./index.html --profile cvi --format jsonLive URLs need a browser. The CLI deliberately hands that work to Deque's maintained runner:
npx @axe-core/cli https://example.comnpm install @accessibility-devkit/corePlain JavaScript with ECMAScript modules:
import { getContrastRatio, meetsContrastThreshold } from '@accessibility-devkit/core';
const ratio = getContrastRatio('#595959', '#ffffff');
const passes = meetsContrastThreshold('#595959', '#ffffff', 'AA', 'normal');CommonJS:
const { assessTimeLimit } = require('@accessibility-devkit/core');
const result = assessTimeLimit({ warningDurationMs: 20_000, extensionCount: 10 });TypeScript:
import { assessTimeLimit, type TimeLimitPolicy } from '@accessibility-devkit/core';
const policy: TimeLimitPolicy = { adjustmentMultiplier: 10 };
console.log(assessTimeLimit(policy));Python:
python -m pip install accessibility-devkitfrom accessibility_devkit import get_contrast_ratio, meets_contrast_threshold
ratio = get_contrast_ratio("#595959", "#ffffff")
passes = meets_contrast_threshold("#595959", "#ffffff", "AA", "normal")Clone the repository, then install the included Accessibility plugin through your coding tool's local marketplace flow:
git clone https://github.com/actually-useful-ai/accessibility-devkit.gitThe portable review source is skills/accessibility. Codex can import .claude-plugin/marketplace.json from the Plugins Directory. Claude Code can use:
/plugin marketplace add actually-useful-ai/accessibility-devkit
/plugin install accessibility@accessibility-devkit
Start with:
$accessibility Review this interface for accessibility barriers. Start with semantics, keyboard behavior, focus, error recovery, and target size. Make the smallest practical fixes and name the manual checks still needed.
Expected output: evidence-backed findings, focused changes or a practical plan, affected interaction modes, and a clear list of unverified checks. In a fresh task, verify that Accessibility appears in the skill picker and that the review separates completed evidence from planned or unverified work. Current Codex steps are in the OpenAI Plugins documentation.
If marketplace import is unavailable, link the skill without replacing anything already installed:
skill_source="$PWD/skills/accessibility"
target="$HOME/.agents/skills/accessibility"
if [ -e "$target" ] || [ -L "$target" ]; then
printf 'Stopped: %s already exists or is a symlink.\n' "$target"
ls -ld "$target"
printf 'After confirming it is no longer needed, remove only that entry with: rm "%s"\n' "$target"
printf 'Or choose a different destination that you control.\n'
exit 1
fi
mkdir -p "$HOME/.agents/skills"
ln -s "$skill_source" "$target"The guard will never overwrite an entry or nest a link inside it.
Node 22+ and Python 3.11+ expose the same interface:
accessibility-devkit scan <files...> [--profile cvi|switch|all] [--format text|json]
accessibility-devkit contrast <foreground> <background> [--level AA|AAA] [--text-size normal|large]
accessibility-devkit readability <file|->
accessibility-devkit timing <policy.json>
Every command accepts --fail-on error|warning|never.
- Exit
0: the selected failure threshold has no matching automated findings. - Exit
1: at least one automated finding meets the threshold. - Exit
2: the input, command, or runtime failed. - Manual checks never fail CI.
readability uses English-specific formulas. timing evaluates the deterministic WCAG 2.2.1 alternatives: disable the limit, allow at least 10× adjustment, or warn for at least 20 seconds with at least ten extensions. Essential and real-time exceptions stay manual.
Profiles keep specialized review visible without pretending it can be reduced to one threshold.
| Profile or need | What the tools can detect | What still needs verification |
|---|---|---|
| Switch access | Positive focus order, source-visible pointer-only risks, timing-policy boundaries | System Switch Control, scan speed, dwell, repeat filtering, simple-action completion |
| CVI | Exact WCAG checks where the source supplies measurable evidence | Individual profile, visual complexity, salience, fatigue, clutter, latency, motion, multisensory alternatives |
| Color-vision deficiency | Four simulation modes and exact color contrast math | Meaning beyond color, real components and states, individual perception |
| Motion and flash | Reduced-motion preference handling and frequency screening | Flash luminance, area, saturated red, vestibular comfort, content context |
| Cognitive access | Time-limit policies, blocked paste, repeated entry, undo helpers, English readability clues | Comprehension, attention demands, recovery, pacing, fatigue, real task completion |
CVI is not color-vision deficiency. Low vision and photophobia are also distinct. The Devkit keeps their language and verification separate.
| Package | Purpose |
|---|---|
@accessibility-devkit/core |
Contrast, English readability analysis, flash-frequency screening, and timing-policy assessment |
@accessibility-devkit/cli |
Conservative static scans and the shared command-line report contract |
accessibility-devkit |
Dependency-free Python core and CLI with the same commands and contract |
| Package | Purpose |
|---|---|
@accessibility-devkit/audit |
axe-core browser audits and jsx-a11y's maintained flat configuration |
@accessibility-devkit/components |
Focus traps, roving tabindex, dialogs, menus, skip links, and live announcements |
@accessibility-devkit/accommodations |
Explicit typography preferences, text-spacing override tests, contrast, and color-vision simulation |
@accessibility-devkit/motor |
Target measurement, pointer cancellation, drag alternatives, dwell, and repeat filtering |
@accessibility-devkit/cognitive |
Timing policy, session helpers, repeated-entry memory, authentication, and undo |
@accessibility-devkit/language |
English readability clues, long-sentence flags, complex words, and abbreviations |
@accessibility-devkit/media |
Captions, transcripts, autoplay-audio review, and media controls |
@accessibility-devkit/motion |
Reduced-motion behavior, safe scrolling, and flash-frequency screening |
All ten npm packages publish ECMAScript modules, CommonJS, TypeScript declarations, source maps, a README, and the full MIT license.
The versioned contract lives at spec/report.schema.json and uses JSON Schema 2020-12. Golden fixtures in spec/fixtures keep the Node and Python implementations aligned.
Reports include:
- schema, producer, runtime, and target metadata;
- a summary with no synthetic accessibility score;
- findings classified as
normative,advisory, orsupplemental; - certainty of
detected,potential, ormanual; - severity, evidence level, WCAG references, location, remediation, and verification;
- a separate
manualCheckscollection.
The scanner is conservative by design. An empty alt can be intentional. A small source dimension does not prove a target-size failure without rendered spacing and exception review. A nested <header> is not a second banner. An unnamed <section> is not a defect. Words such as “autoplay” or “animation” in prose are not executable timing evidence.
Automation catches a useful subset of accessibility barriers. It cannot establish full conformance, assistive-technology usability, comprehension, comfort, or task completion.
A release review should combine:
- Source inspection and deterministic checks.
- Browser automation, preserving incomplete results.
- Keyboard-only navigation and visible focus.
- Screen-reader review on supported browser and platform combinations.
- 200% zoom, narrow reflow, forced colors, and reduced motion.
- Switch Control for switch-critical paths.
- Human testing, including an individual CVI profile when CVI claims matter.
Record completed checks, open verification, and only the claims the evidence supports.
v1.1 makes a clean pre-registry API break so names describe what the code can prove.
| v1.0 | v1.1 |
|---|---|
meetsWCAG |
meetsContrastThreshold |
findAccessibleColor |
findNearestPassingColor |
simulateColorBlindness |
simulateColorVisionDeficiency |
applyDyslexiaFriendlyFont |
applyTypographyPreference with caller-supplied values |
applyTextSpacing |
applyTextSpacingTest, including paragraph spacing and restore |
meetsTextSpacing |
Removed; author spacing values alone do not establish WCAG 1.4.12 conformance |
| accommodation motion helpers | Use @accessibility-devkit/motion |
isUnsafeFlashRate |
exceedsFlashFrequencyLimit; frequency is only one part of flash review |
Invalid colors now throw instead of becoming black. Dwell and repeat intervals are explicit. English readability results identify their method. createSessionTimeout remains an implementation helper; use assessTimeLimit for policy boundaries.
git clone https://github.com/actually-useful-ai/accessibility-devkit.git
cd accessibility-devkit
pnpm install
pnpm build
pnpm lint
pnpm test
pnpm test:packPython has no runtime dependencies:
PYTHONPATH=python/src python3 -m unittest discover -s python/tests -vNode CI covers versions 22 and 24. Python CI covers 3.11 through 3.14. Changesets keeps every npm package in one fixed version group; the PyPI distribution and GitHub release use the same version.
Security guidance is in SECURITY.md. Runtime dependency licenses and review notes are in THIRD_PARTY_NOTICES.md.
MIT © 2026 Luke Steuber. Accessibility Devkit is maintained at actually-useful-ai/accessibility-devkit.