a11y-shiftleft-cli
v0.6.3
Published
Accessibility testing CLI for web apps, pull requests, visual reports, and dashboards.
Maintainers
Readme
a11y-shiftleft-cli
Install from npm:
npm install --save-dev a11y-shiftleft-cli
Accessibility checks for web apps, pull requests, visual reports, and local dashboards.
a11y-shiftleft-cli helps teams find accessibility issues earlier, before they
ship. It scans a running web app in a real browser, optionally adds
framework-specific static checks, removes duplicate findings, assigns severity
and confidence, and writes reports that are useful for developers, QA, CI, and
trend tracking.
You can use it with React, Vue, Angular, Next.js, Svelte, Astro, Rails, Django, static HTML, or any app that can run at a local or preview URL.
Why Use It?
Most accessibility tools solve one part of the workflow:
- axe-core finds browser-rendered issues.
- ESLint plugins catch framework-specific patterns.
- Lighthouse gives a score.
- CI tells you whether a pull request should pass.
This project connects those pieces into one repeatable developer workflow:
- Run static and dynamic checks from one command.
- Deduplicate repeated findings.
- Map findings to WCAG metadata when available.
- Prioritize by severity and confidence.
- Export Markdown, JSON, CSV, visual HTML, and dashboard reports.
- Add bounded checks to pull requests.
- Track whether accessibility is getting better or worse over time.
2-Minute Quick Start
Use this when your app already runs locally.
- Install the CLI:
npm install --save-dev a11y-shiftleft-cli
npx playwright install chromium- Start your app in another terminal:
npm run devCommon dev server URLs by framework or tool:
| Framework / Tool | Default URL |
|---|---|
| Vite (React, Vue, Svelte) | http://localhost:5173 |
| Next.js | http://localhost:3000 |
| Create React App | http://localhost:3000 |
| Angular CLI | http://localhost:4200 |
| Astro | http://localhost:4321 |
| Webpack Dev Server | http://localhost:8080 |
When in doubt, use the URL your terminal prints after npm run dev.
- Run your first scan. Replace the URL with the URL printed by your dev server:
npx a11y-shiftleft check --dynamic --url http://localhost:5173 --out reports- Open the human-readable report:
open reports/a11y-comment.mdThe same run also creates:
reports/a11y-report.json
reports/a11y-metrics.csvOptional Project Setup
Create a config file and add generated reports to .gitignore:
npx a11y-shiftleft init --framework auto --gitignoreThen use a URL shortcut in your terminal:
export APP_URL=http://localhost:5173
npx a11y-shiftleft doctor --url $APP_URL
npx a11y-shiftleft check --dynamic --url $APP_URL --out reportsAPP_URL is only a shortcut. You can always pass the URL directly:
npx a11y-shiftleft check --dynamic --url http://localhost:4200 --out reportsCopy-Paste Recipes
| Goal | Command |
|---|---|
| Scan one running app URL | npx a11y-shiftleft check --dynamic --url http://localhost:5173 --out reports |
| Scan several known pages | npx a11y-shiftleft check --dynamic --url $APP_URL $APP_URL/settings $APP_URL/checkout --out reports |
| Let the CLI discover same-origin pages | npx a11y-shiftleft check --dynamic --url $APP_URL --crawl --crawl-depth 1 --crawl-limit 10 --out reports |
| Trigger lazy-loaded below-the-fold content | npx a11y-shiftleft check --dynamic --url $APP_URL --scroll-step 800 --scroll-max-steps 25 --out reports |
| Create a visual state report | npx a11y-shiftleft explore --url $APP_URL --depth 2 --out reports |
| Force complete page screenshots | npx a11y-shiftleft explore --url $APP_URL --depth 2 --screenshot-full-page --out reports |
| Keep reports refreshed while coding | npx a11y-shiftleft watch --url $APP_URL --out reports/watch |
| Generate a fast PR workflow | npx a11y-shiftleft ci --url $APP_URL --start-command "npm run dev -- --host localhost --port 5173" |
| View historical trends | npx a11y-shiftleft dashboard --reports reports |
What The Reports Mean
After a scan, start with reports/a11y-comment.md. It contains a compact table
and a list of findings with severity, WCAG metadata, confidence, and remediation
hints.
Each finding is labeled as a WCAG violation, best practice, or
unmapped review. Reports also group repeated occurrences into likely root
causes when the same rule and component state appear across routes. This grouping is
heuristic: per-page evidence remains available for review.
Every finding includes a deterministic How to fix recommendation. Known rules
provide specific steps, official guidance links, and framework examples when
available. Unknown rules still receive safe review steps instead of an empty
recommendation; axe findings also preserve their rule-specific help link.
| File | Use it for | Commit it? |
|---|---|---|
| reports/a11y-comment.md | Human review and PR comments | Usually no |
| reports/a11y-report.json | Automation, debugging, integrations | Usually no |
| reports/a11y-metrics.csv | Trends and empirical validation | Usually no |
| reports/exploration.html | Visual review of explored UI states | Usually no |
| reports/exploration.pdf | Portable visual report artifact when --pdf is used | Usually no |
| reports/screenshots/ | Screenshots from visual exploration | No |
| .a11y-shiftleft.json | Shared project config | Usually yes |
| .a11y-baseline.json | Accepted known findings | Yes, when using baseline mode |
| a11y-ignore.json | Temporary reviewed exceptions | Yes, when intentionally used |
Each finding can include:
{
"ruleId": "color-contrast",
"severity": "critical",
"confidence": "high",
"confidenceScore": 95,
"category": "contrast",
"findingType": "wcag",
"contrast": {
"actualRatio": 2.32,
"requiredRatio": 4.5,
"foreground": "#aaaaaa",
"background": "#ffffff",
"suggestions": [
{ "target": "foreground", "purpose": "minimum", "color": "#767676", "contrastRatio": 4.54 },
{ "target": "foreground", "purpose": "recommended", "color": "#6F6F6F", "contrastRatio": 5.02 },
{ "target": "foreground", "purpose": "enhanced", "color": "#595959", "contrastRatio": 7 }
]
},
"wcag": ["1.4.3"],
"wcagCriteria": [
{
"id": "1.4.3",
"title": "Contrast (Minimum)",
"level": "AA",
"principle": "perceivable",
"url": "https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html"
}
]
}Severity answers: "How risky is this finding?"
Confidence answers: "How strong is the tool evidence?"
For axe color-contrast findings, JSON, Markdown, and visual reports include
the measured and required ratios, text and background colors, font metadata,
and deterministic suggestions that meet the reported threshold. Treat suggested
colors as starting points and verify shared design tokens and interactive states.
When a dynamic run checks multiple pages, the CLI also compares document
titles. It reports common starter placeholders such as Vite + React and titles
reused across distinct URLs, while repeated dialogs, themes, and other states of
the same URL are not treated as duplicate pages.
Static Checks For React, Vue, And Angular
Dynamic browser scans work without a framework adapter. Static checks are optional and add framework-specific lint findings.
Install only the adapter package you need:
| Project | Install |
|---|---|
| React | npm install --save-dev @a11y-shiftleft/react |
| Vue | npm install --save-dev @a11y-shiftleft/vue |
| Angular | npm install --save-dev @a11y-shiftleft/angular |
Ask the CLI for a recommendation:
npx a11y-shiftleft adapter add react
npx a11y-shiftleft adapter add vue
npx a11y-shiftleft adapter add angularRun static checks only:
npx a11y-shiftleft check --static --framework react --out reportsRun static and dynamic checks together:
npx a11y-shiftleft check --url $APP_URL --out reportsVisual Exploration
Screenshot privacy: explore captures screenshots of every page it visits.
If the app you are scanning contains personal data, login screens, payment details,
or production customer records, use --no-screenshots to skip them entirely.
See Visual reports for privacy and safe-mode details.
Use explore when you do not want to list every route manually or when you
want screenshots of checked states:
npx a11y-shiftleft explore --url $APP_URL --depth 2 --out reportsDynamic scans and visual exploration auto-scroll pages before running axe. This
helps trigger lazy-loaded sections below the first viewport. The scan still
stays bounded for CI with a default maximum of 25 scroll steps per page. Use
--no-scroll only when a project needs to avoid scroll-triggered behavior.
The same commands automatically compare the rendered light and dark system color schemes when the page actually changes between them. Findings and visual states are labeled by color scheme in the reports. Pages that render identically are scanned once, so no theme option or second command is needed.
Screenshots are compact by default. Short affected pages can be captured in full, while long pages are automatically split into focused crops around nearby errors. This keeps below-the-fold evidence without storing thousands of unrelated pixels. Force complete pages only when an audit specifically needs that context:
npx a11y-shiftleft explore \
--url $APP_URL \
--depth 2 \
--screenshot-full-page \
--out reportsPixel-identical screenshots are stored only once. Repeated UI states remain in the exploration graph, but the HTML report replaces duplicate thumbnails with a link to the shared visual evidence.
For apps that render data after the first page load, add a short settle wait:
npx a11y-shiftleft explore --url $APP_URL --depth 2 --wait-ms 1000 --out reportsIf your app exposes a stable loaded-state selector, wait for that instead of guessing a long timeout:
npx a11y-shiftleft explore \
--url $APP_URL \
--wait-for-selector "[data-page-ready]" \
--wait-ms 1000 \
--out reportsIt safely follows same-origin links and low-risk UI expansion controls such as
menu buttons, tabs, disclosure widgets, and modal triggers. Cookie consent
controls are never clicked automatically, including short buttons such as
Accept or OK when they appear inside a recognized consent banner.
Recognizable theme switches are checked early so explicit app themes are less
likely to be skipped by the bounded action limit.
It creates:
reports/exploration.html
reports/exploration.pdf # only when --pdf is used
reports/exploration-graph.json
reports/screenshots/state-*.jpg
reports/screenshots/state-*-error-*.jpg # focused crops on long pagesScreenshots are compressed, and sensitive form fields are masked by default.
Use --no-screenshots for apps with personal data, login screens, payment
details, or production records:
npx a11y-shiftleft explore --url $APP_URL --depth 2 --no-screenshots --out reportsAdd --pdf when you need a portable copy of the visual report for a PR,
ticket, or internal review:
npx a11y-shiftleft explore --url $APP_URL --depth 2 --pdf --out reportsSee Visual reports for privacy and safe-mode details.
Watch Mode
Use watch during local development:
npx a11y-shiftleft watch --url $APP_URL --out reports/watchIt watches common source folders such as src, app, pages, and
components, reruns checks after file changes, and prints what changed between
runs:
fixed 2, new 1, remaining 4Use custom paths when your UI code lives somewhere else:
npx a11y-shiftleft watch \
--url $APP_URL \
--watch-path src shared/ui packages/app \
--out reports/watchSee Watch mode for more examples and current limits.
Baseline Mode
Use baseline mode when adopting the CLI in a project that already has known findings. The first run records the current findings:
npx a11y-shiftleft check --dynamic --url $APP_URL --baseline --out reportsCommit .a11y-baseline.json. Later CI runs with --baseline fail only on new
findings at the configured severity:
npx a11y-shiftleft check \
--dynamic \
--url $APP_URL \
--baseline \
--fail-on warning \
--out reportsTemporary Ignores
Use a11y-ignore.json only for reviewed temporary exceptions:
{
"version": 1,
"ignores": [
{
"ruleId": "color-contrast",
"selector": ".legacy-muted-text",
"reason": "Legacy theme is scheduled for replacement.",
"owner": "@frontend-team",
"expires": "2026-09-30"
}
]
}Ignores require a reason, owner, and expiration date so they do not become permanent hidden risk.
GitHub Actions
Generate a pull request workflow:
npx a11y-shiftleft ci \
--url $APP_URL \
--start-command "npm run dev -- --host localhost --port 5173" \
--fail-on critical \
--standard wcag22-aaThis creates:
.github/workflows/a11y.ymlFor a fast PR workflow plus a broader scheduled scan:
npx a11y-shiftleft ci \
--profile split \
--url $APP_URL \
--start-command "npm run dev -- --host localhost --port 5173" \
--fail-on critical \
--full-fail-on none \
--crawl-limit 10 \
--full-crawl-depth 3 \
--full-crawl-limit 100 \
--standard wcag22-aaThis creates:
.github/workflows/a11y-pr.yml
.github/workflows/a11y-full.ymlDashboard
After several saved runs, open a local dashboard:
npx a11y-shiftleft dashboard --reports reportsOr write a static dashboard file:
npx a11y-shiftleft dashboard --reports reports --no-serveAdd --pdf when the dashboard should be attached to a ticket, review, or
internal report:
npx a11y-shiftleft dashboard --reports reports --pdfThe dashboard summarizes trends, top rules, affected pages, and recent runs.
Ticket Drafts
Create dry-run Jira, Linear, or generic ticket drafts from an existing
a11y-report.json:
npx a11y-shiftleft ticket export \
--report reports/a11y-report.json \
--tracker linear \
--out reports/a11y-tickets.mdThe export groups findings by severity, rule, page, and target. It does not connect to Jira or Linear yet, so teams can review the draft before creating real tickets.
Manual Review Checklist
Automated tools do not catch every accessibility issue. Generate a manual review checklist when you need human follow-up:
npx a11y-shiftleft check --url $APP_URL --semi-auto --out reportsThis adds:
reports/a11y-manual-checklist.mdThe checklist covers areas such as keyboard flow, screen reader smoke testing, form labels, content clarity, 200% zoom and reflow, alternative-text quality, media and motion, skip links, and representative-user task testing that automated tools cannot fully judge.
WCAG And Compliance Support
Filter mapped findings by WCAG level or version:
npx a11y-shiftleft check --url $APP_URL --wcag-filter AA --out reports
npx a11y-shiftleft check --url $APP_URL --wcag-version 2.0 --out reportsUse a report metadata preset:
npx a11y-shiftleft check --url $APP_URL --standard wcag22-aa --out reports
npx a11y-shiftleft check --url $APP_URL --standard section508 --out reports
npx a11y-shiftleft check --url $APP_URL --standard ada-title-ii --out reportsAutomated reports do not certify full WCAG, ADA, or Section 508 conformance. Use them with manual keyboard review, screen reader checks, content review, and your organization's compliance process.
Troubleshooting
If a scan fails because of Node, Playwright, Chromium, config, or a target URL, run:
npx a11y-shiftleft doctor --url $APP_URLFor CI or scripts:
npx a11y-shiftleft check --dynamic --url $APP_URL --json-summary --out reports
npx a11y-shiftleft check --dynamic --url $APP_URL --quiet --out reports
npx a11y-shiftleft check --dynamic --url $APP_URL --verbose --out reportsLocal Demo
This repository includes a React/Vite demo with intentional accessibility defects.
nvm use
npm install
npm run demo -- --port 5173In another terminal:
nvm use
node bin/cli.js check --dynamic --url http://localhost:5173 --out reportsMore Documentation
- FAQ: Common questions about installing, running, and reading reports.
- Recipes: React, Vue, Angular, Next.js, multiple URL scans, GitHub Actions, ADA Title II, and Section 508 setup guides.
- Configuration: config files,
.gitignore, baseline files, ignores, cleanup, and retention. - Visual reports: screenshot privacy, safe mode, and
advanced
exploreoptions. - Watch mode: local development feedback after file changes.
- Ticket export: dry-run Jira, Linear, or generic
ticket drafts from
a11y-report.json. - Evidence methodology: confidence scoring, issue categories, false-positive review, and metrics definitions.
- WCAG 2.2 coverage: criterion-by-criterion automated, manual, and missing coverage.
- Empirical validation: baseline vs intervention study design and analysis commands.
- Adoption strategy: npm scripts, generated CI, future GitHub Action wrapper, docs-site plan, and outreach ideas.
- Roadmap: Lighthouse comparison, browser overlay, dashboard improvements, and future tracker integrations.
- Contributing: first PR path, local setup, testing, issue templates, and pull request checklist.
- GitHub About setup: recommended repository description, website, and topics.
Release Notes
Current release:
Previous releases:
