This page keeps the detailed setup rules out of the README while preserving the parts teams need for CI, shared defaults, and report cleanup.
The CLI reads configuration in this order:
--config <file>.a11y-shiftleft.json.a11yrc.jsonpackage.json#a11y
Use .a11y-shiftleft.json for generated shared defaults. Use .a11yrc.json,
package.json#a11y, or --config when your project already keeps tool
settings elsewhere.
Commit .a11y-shiftleft.json when it contains shared project defaults:
{
"framework": "react",
"wcagVersion": "2.2",
"wcagLevel": "AA",
"dynamic": {
"enabled": true,
"urls": ["/", "/settings"]
}
}Keep local-only URLs, experiments, credentials, private preview links, and
machine-specific paths out of git. Use a local config file with --config for
those cases.
Use explore.waitMs when screenshots or axe scans happen before a dynamic page
has finished rendering:
{
"explore": {
"waitMs": 1000,
"waitForSelector": "[data-page-ready]"
}
}Keep shared waits small for pull requests. Prefer a stable waitForSelector
over large fixed delays when the app can expose a loaded-state marker.
Dynamic browser scans and visual exploration scroll each page before running axe. This helps trigger lazy-loaded content below the first viewport:
{
"dynamic": {
"scroll": {
"enabled": true,
"stepPx": 800,
"maxSteps": 25,
"waitMs": 100
}
},
"explore": {
"scroll": {
"enabled": true,
"stepPx": 800,
"maxSteps": 25,
"waitMs": 100
}
}
}Use --no-scroll only when scrolling triggers project-specific side effects.
For long pages, scheduled full-site scans can increase --scroll-max-steps;
pull request checks should keep the limit bounded.
Use --scope <selector> when you want browser checks to stay inside one
component, dialog, checkout step, or page section:
npx a11y-shiftleft audit --url $APP_URL --scope '#checkout' --out reports
npx a11y-shiftleft check --dynamic --url $APP_URL --scope '#main' --out reportsFor shared defaults, use dynamic.scopeSelector for check and
explore.scopeSelector for visual exploration and audit:
{
"dynamic": {
"scopeSelector": "#main"
},
"explore": {
"scopeSelector": "#main"
}
}Scoped checks limit axe scans and safe action discovery to the selected area. Page-level and manual-review evidence should still be interpreted with the overall page context in mind.
Use --hide-elements <selectors> when a cookie banner, sticky ad, chat widget,
survey prompt, or other overlay makes visual evidence hard to read:
npx a11y-shiftleft audit --url $APP_URL --hide-elements ".cookie-banner,.chat-widget" --out reports
npx a11y-shiftleft check --dynamic --url $APP_URL --hide-elements ".cookie-banner" --out reportsFor shared defaults, use dynamic.hideElements for check and
explore.hideElements for visual exploration and audit:
{
"dynamic": {
"hideElements": [".cookie-banner"]
},
"explore": {
"hideElements": [".cookie-banner", ".chat-widget"]
}
}The elements are hidden with CSS during the scan and screenshots. They are not deleted from the page, and the selectors are recorded in generated reports.
By default, browser checks run in Chromium. Use --browser when you need
evidence from another browser engine:
npx a11y-shiftleft audit --url $APP_URL --browser firefox --out reports
npx a11y-shiftleft audit --url $APP_URL --browser webkit --mobile --out reports
npx a11y-shiftleft audit --url $APP_URL --browser webkit --tablet --out reports
npx a11y-shiftleft check --dynamic --url $APP_URL --browser chromium --device "Pixel 5" --out reportsSupported browser engines are chromium, firefox, and webkit. Device names
come from Playwright device presets, such as Desktop Chrome, Desktop Safari,
iPhone 13, and Pixel 5. For visual reports, audit --mobile is a shortcut
for iPhone 13, and audit --tablet is a shortcut for iPad (gen 7).
Install the browser engine before using it:
npx playwright install firefox
npx playwright install webkitFor shared defaults:
{
"dynamic": {
"browser": "chromium",
"device": "Pixel 5"
},
"explore": {
"browser": "webkit",
"device": "iPhone 13"
}
}Lighthouse comparison still runs through Chromium because Lighthouse depends on Chrome DevTools behavior.
explore.safeMode.isolateCookies is enabled by default. It clears browser
cookies between replayed states so one explored action cannot silently change
later states:
{
"explore": {
"safeMode": {
"isolateCookies": true
}
}
}Leave it enabled for CI and pull requests. Disable it only for local debugging when you intentionally need cookies to persist across explored states.
Generated reports should normally stay out of git:
npx a11y-shiftleft init --gitignoreThis adds common report directories such as reports/ and .a11y-reports/ to
.gitignore.
Commit anonymized report samples only when they are intentionally part of docs, demos, or release evidence.
checkoverwritesa11y-report.json,a11y-comment.md, andevaluation-scope.jsonin the selected output directory. Add--format csvor--format allonly when spreadsheet exports are needed.auditwrites the primarya11y-report.html, JSON, Markdown, and screenshots. Excel, PDF, and raw exploration data are created only with--excel,--pdf, and--raw.explorecleans stale generated artifacts before a new run, includinga11y-report.json,a11y-comment.md,evaluation-scope.json,exploration.html,exploration-graph.json, optional CSV exports, and generated state screenshots.- After fixing an accessibility issue, rerun the same command. The fixed issue should disappear from the new report.
- Use
--no-cleanonly when you intentionally want to keep previous generated artifacts for manual comparison.
Use baseline mode when adopting the CLI in a project that already has known accessibility findings:
npx a11y-shiftleft check --dynamic --baseline --out reportsCommit .a11y-baseline.json. Later CI runs with --baseline compare current
findings against that file and fail only on new findings at the configured
--fail-on severity.
For legacy projects that need a gentle first gate, use the built-in quality gate profile:
npx a11y-shiftleft check --dynamic --gate new-critical-only --out reportsThis is shorthand for baseline comparison plus a critical-only failure gate. It allows teams to track existing findings while blocking only newly introduced critical issues.
Refresh the baseline only when the current state is intentionally accepted:
npx a11y-shiftleft check --dynamic --update-baseline --out reportsUse a11y-ignore.json for temporary, reviewed 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"
}
]
}Every ignore must include reason, owner, expires, and at least one match
field such as fingerprint, ruleId, source, severity, selector,
file, url, target, or wcag. Expired or invalid entries do not hide
findings and are counted in the report summary. Reports also count rules that
expire within the next 14 days and summarize ignored findings by owner, so teams
can clean up temporary exceptions before they become permanent accessibility
debt.
Visual audit reports include an Ignore Cleanup section when scoped ignores
are active. Each finding group also has a Copy ignore entry button that
copies a reviewed a11y-ignore.json template with the rule, fingerprint, target
metadata, owner placeholder, reason placeholder, and expiry placeholder.
Audit the ignore file without scanning a website:
npx a11y-shiftleft-cli ignore auditUse JSON output when another script needs the cleanup summary:
npx a11y-shiftleft-cli ignore audit --format jsonGenerate a read-only cleanup plan for stale entries:
npx a11y-shiftleft-cli ignore cleanup-planThe cleanup plan does not edit a11y-ignore.json. It proposes whether each
stale entry should be reviewed before expiry, removed or renewed, or fixed
because required metadata is missing.
Use retention when you write timestamped output directories such as
reports/run-2026-06-11:
npx a11y-shiftleft explore \
--url $APP_URL \
--out reports/run-2026-06-11 \
--retention-max-runs 5 \
--retention-max-age-days 14Preview cleanup without deleting old report runs:
npx a11y-shiftleft explore \
--url $APP_URL \
--out reports/run-2026-06-11 \
--retention-max-runs 5 \
--retention-max-age-days 14 \
--retention-dry-runRetention only removes sibling directories that contain a11y-shiftleft report marker files and never removes the current output directory.