Accessibility test toolkit

CLI reference

Every command, subcommand, and option in the a1 binary. Run a1 help-all to print the whole tree in one response, which is the fastest way to give an agent the full command set.

Map

Command families

Most commands check a target against axe-core (axe), an open-source rules engine that runs inside the page and flags accessibility problems, or look up the Web Content Accessibility Guidelines (WCAG), the standard most accessibility requirements come from.

a1 srControl a screen reader through a session.
a1 wcagLook up criteria, techniques, axe rules, search results, and coverage.
a1 axeRun axe-core against one or more targets.
a1 treePrint a target's accessibility tree.
a1 auditRun axe, the accessibility tree, and applicability together, with a criterion rollup.
a1 mcpStart the stdio MCP server.
a1 doctorCheck the host and list the setup steps still needed.
a1 setupRun the Guidepup setup steps this host needs, then re-check.
a1 help-allPrint help for every command and option at once.

Options

Shared options

--jsonPrint one structured object instead of formatted text.
--verboseAdd detail to the text output. No effect with --json.
--wcag <version>WCAG version for wcag, axe, and audit. Accepts 2.1 or 2.2. Defaults to 2.2.

-V at the top level prints the package version. --wcag inside a subcommand selects the WCAG version, so the two no longer share one flag name.

Environment

A11IED_STATE_DIR sets the directory that stores the active session's state file, lock, and broker socket. Without it, a11ied uses $XDG_STATE_HOME/a11ied, then ~/.a11ied/state. Native CLI sessions always run in a separate broker so cleanup can be retried after the command exits. A11IED_DRIVER_MODE=in-process applies to virtual sessions and API hosts that remain running.

Screen reader

a1 sr

One session is active at a time. No command takes or prints a session id. A landmark, in the next and previous kind list below, is a named region such as banner, navigation, or main that a screen reader lets a user jump straight to.

sr start [url]Start the session, stopping any active one first. Opens the URL in a browser and waits until its window is in front. Takes --sr, --browser <name>, --app <name> for a native app instead of a page, --recording <path>, --idle-timeout <minutes>.
sr open <url>Move the running session to another page.
sr statusPrint the session target, URL, uptime, recording, and transcript counts.
sr stopStop the session and delete its state file. Takes --out <path> and --format.
sr readThe current item without moving: role, name, value, states, the phrase, and the source of each field.
sr titleThe page title: document.title, the VoiceOver window summary, or the NVDA window title.
sr next [kind], sr previous [kind]
Move one item, or jump by kind: heading, link, landmark, control, button, table, list, graphic, region, form-field. Takes --level <1-6> with heading and --times <n>.
sr top, sr bottom
Move to the start or the end of the document or the current area.
sr interact, sr stop-interacting, sr activate
Enter a group or control, leave it, and activate the current item.
sr escapePress Escape to dismiss a menu or a dialog.
sr find <text>Move the cursor to the next place the text appears. Exits 4 when it is not found. Needs an active session.
sr table <move>Inside a table: next-cell, previous-cell, next-row, previous-row, next-column, previous-column, row-header, column-header.
sr gotoStep forward until the current item matches --role <role>, --name <text>, or both. Takes --max. Exits 4 when nothing matches. Needs an active session.
sr elements <kind>The rotor: from the top, every element of one kind as the reader announces it. Takes --max, default 200. Needs an active session.
sr read-allRead from the cursor to the end of the document, or to --max (default 500), and say which. Needs an active session. Use sr walk to read a whole page instead.
sr walk [url]Start a session when none is active, move to the top, read the whole page, and print the transcript of the walk. Takes --sr, --max, --out, --format. With no --sr and no active session, this starts VoiceOver on macOS.
sr press <chord...>Press key chords in order, one chord per argument.
sr type <text>Type text through the active target.
sr do <command>Run a named command, or <command-set>:<name> when two sets share a name. Takes --command-set.
sr listThe commands sr do accepts, grouped by command set and by what they do. Takes --query, --sr, --command-set.
sr focusBring a window to the front. With no options, refocus the app the session opened. Takes --app, --bundle-id, --process, --pid, --window-title, --match.
sr screenshot <path>Save a picture of what the VoiceOver cursor is on. NVDA and virtual exit 2.
sr waitPause for --ms, or poll the transcript until --for <text|/regex/> is announced. Use --since <checkpoint> to include announcements after a checkpoint. Exits 4 at --timeout, default 5000 ms.
sr expect <text|/regex/>Check the transcript for a phrase. Takes --since <checkpoint> and --not. Exits 4 on a mismatch.
sr checkpoint <label>Mark a point in the transcript for --since.
sr transcriptPrint what the reader said, with timestamps. Takes --since, --tail, --after-index, --limit, --out, --format. Index paging defaults to 200 entries. The transcript window reports omissions and the next index.
sr tailStream spoken announcements continuously in real time. Takes --lines <n> (default 10), --since <checkpoint>, --interval <ms> (default 250), --phrase (phrase only), and --json (NDJSON). Aliases: follow, stream, watch.
sr batch [file]Run JSON lines of actions, one per line or from stdin, over one broker connection. Stops at the first failed expect unless --continue.

Session options

Native sessions default to guarded. Commands check the observed foreground target, and typing checks between characters. Read the fresh current item, focus observations, and transcript after each action. If focus changes, refocus deliberately and inspect state before continuing. require-binding is an optional strict mode that refuses unavailable native binding. development bypasses target checks. Foreground checks do not guarantee that focus cannot change during dispatch.

--sr <reader>voiceover, nvda, or virtual, on sr start, sr walk, and the commands that start a session. Without it, a11ied picks the platform reader and falls back to virtual.
--timeout <ms>Bound the screen reader command instead of using the built-in limits. On sr wait it is how long to wait for the phrase.
--phraseOn a navigation verb, print the last spoken phrase alone, one line.
--ephemeralRun one action and stop its session. Native actions use a detached broker. Unconfirmed cleanup leaves a recovery session.
--command-set <set>auto, portable, voiceover-commander, or voiceover-keycode. Defaults to auto.
0The command ran.
2Usage error: a command the target cannot run, or a verb run with no active session.
3The browser or the broker process failed to start.
4A check failed: find, goto, wait --for, expect, or a batch with a failed expect.

press, type, do, and walk start a session when none is active. The other verbs need one and exit 2 without it.

Keys

Key chord syntax

sr press takes one chord per argument, and each chord joins its tokens with +: Tab, Shift+Tab, VO+ArrowRight, or NVDA+N.

ModifiersShift, Control, Alt
Letters and digitsa to z, KeyA to KeyZ, 0 to 9, Digit0 to Digit9
ArrowsArrowUp, ArrowDown, ArrowLeft, ArrowRight, and the Up and UpArrow aliases
NavigationTab, Enter, Escape, Space, Backspace, Delete, Home, End, PageUp, PageDown
VoiceOverVO for Control and Option, plus Command, Option, Meta, and Fn
NVDANVDA for Insert, plus Windows, Application, and the NumPad0 to NumPad9 keys
a1 sr press Tab Tab --sr virtual --json
a1 sr press "VO+ArrowRight" --json
Full list

a1 sr press --help prints every token the current platform accepts, including function keys and punctuation names. press starts a session when none is active, defaulting to VoiceOver on macOS, so pass --sr virtual unless a VoiceOver chord such as VO+ArrowRight is what you want to run.

Standards

a1 wcag

A success criterion is one testable WCAG requirement, identified by a number such as 1.4.3 and assigned a conformance level of A, AA, or AAA that says how strict it is. This family looks up criteria by that number, by slug, or by technique ID.

wcagWith no arguments on a terminal, an interactive finder: fuzzy search on the left, the criterion on the right, t, f, u, and a for testing it, if it fails, the Understanding document, and everything, y to copy the a1 axe --criterion command. Piped output prints the help.
wcag <criterion>One criterion by ID or slug, or one technique by ID such as G18. Same output as wcag show.
wcag criteriaList criteria. --level A, AA, or AAA narrows it. --summary prints the count of automated, hybrid, and manual criteria per level instead. See test methods.
wcag show <criterion>The requirement, a plain restatement of what to do, what WCAG2Mobile says about it on a mobile platform, how to test it, and what to do when it fails. --verbose adds the raw testMethod.method, preferredEvidenceMode, procedure IDs, and the rest of the mobile guidance.
wcag understanding <criterion>The full Understanding document for one criterion, converted to Markdown, with the source line the W3C Document License requires.
wcag rule <ruleId>One axe-core rule: the criteria it maps to, and the axe help text and URL.
a1 wcag 1.4.3
a1 wcag show status-messages --json
a1 wcag understanding status-messages
a1 wcag criteria --level AA --wcag 2.1 --json
a1 wcag criteria --summary
a1 wcag rule color-contrast
a1 wcag G18

These read bundled data. No command in this family opens a browser or makes a request.

pattern

The ARIA Authoring Practices Guide publishes, for each of its 68 examples, a keyboard support table and a role, property, state, and tabindex table. This family reads those tables, and checks a live page against one.

patternEvery pattern with its example count. Same as pattern list.
pattern <name>One pattern by id such as combobox, with the guide's own text for it, section by section, and the examples the guide publishes for it. Or one example by id such as combobox-select-only, with its keyboard and attribute tables. --section about, keyboard, attributes, or examples narrows the output.
pattern role <role>The examples the APG example index files under one ARIA role.
pattern attribute <attribute>The examples the index files under one property or state, such as aria-expanded.
pattern check <target>Press every key one example declares against a live widget, and check its documented attributes. --pattern and --selector are both required. --click opens a widget the page renders only after a click, such as a dialog behind its trigger. --table and --setup reach a state the first keyboard table does not cover.
pattern record <target>Record what you decided about one row the check could not decide. --pattern, --row, --outcome, and --selector are required. Pass the same --click the check used. Supply --run, --provenance, and the current --subject-hash for a scoped assessment. A note alone stays unverified. Keyboard rows require typed keypress evidence for a documented key; attribute rows require observations of the widget's role or attribute.
pattern pending <target>The rows still awaiting verified evidence. Supply --run, --pointer, and --subject-hash to match the observed widget. Every queued state and environment must be assessed.
a1 pattern combobox
a1 pattern combobox-select-only --section keyboard
a1 pattern windowsplitter --section keyboard
a1 pattern role combobox
a1 pattern attribute aria-expanded
a1 pattern check http://localhost:3000 --pattern combobox-select-only --selector '#fruit'
a1 pattern check http://localhost:3000 --pattern dialog --selector '[role="dialog"]' --click '#open-settings'
a1 pattern pending http://localhost:3000 --pattern combobox-select-only

Everything but pattern check reads bundled data. pattern check exits 4 on two findings and no others: a key the guide declares that changed nothing, and an attribute pointing at an id the document does not have. Every other key is printed with what changed next to the guide's own description of what should have changed, because whether the right thing happened is a judgment the tool does not make.

axe

a1 axe

<targets...>One or more http(s) URLs or file paths, or - for HTML on stdin. Multiple targets print one report each.
--html <markup>Load inline HTML instead of the positional target.
--timeout <ms>Timeout for loading the target, in milliseconds. Defaults to 10000.
--level <level>Run the rules mapped to one WCAG level and every level below it.
--criterion <criterion>Run the rules mapped to one criterion, by ID or slug.
--rule <ruleId...>Run named axe rules. Repeat the flag for more than one.
--selector <css>Scope the scan to elements matching this CSS selector.
--exclude <css>Exclude elements matching this CSS selector from the scan.
--wait-for <css>Wait for an element matching this CSS selector before scanning.
--click <selector>Click the one element this selector matches after the page loads, before the scan. Reaches a dialog or a menu the page renders only after a click.
--viewport <WxH>Set the browser viewport, for example 1280x800.
--header <header...>Repeatable. Add a request header, as Name: value.
--cookie <cookie...>Repeatable. Add a cookie, as name=value.
--fail-on <impact>Only count violations at or above this impact toward the exit code: minor, moderate, serious, or critical. Defaults to any violation.
--baseline <file>JSON file of accepted findings, keyed by rule id and node target, that do not count toward the exit code.
--update-baselineWrite the current violations to --baseline instead of asserting against it.
--format <format>text, json, sarif, or earl. Defaults to text, or json with --json.
--out <file>Write the report to this file instead of stdout.
a1 axe http://localhost:3000 --level AA --json
a1 axe http://localhost:3000 --criterion 1.4.3 --json
a1 axe src/components/Dialog.html --rule color-contrast --rule link-name --json
echo '<button></button>' | a1 axe -
a1 axe --html '<img src=x>'
a1 axe http://localhost:3000 --selector '#app' --exclude '.ads'
a1 axe http://localhost:3000 --fail-on critical --json
a1 axe http://localhost:3000 --baseline known-findings.json --update-baseline
a1 axe http://localhost:3000 --format sarif --out results.sarif
a1 axe http://localhost:3000 --format earl --out report.earl.json
a1 axe http://localhost:3000/a http://localhost:3000/b --json

With no selector, the run covers every rule mapped in the WCAG version. The result has violations, passes, incomplete, and inapplicable, plus the resolved rule list under selection.

A file target loads through file://. axe never fetches a URL target's HTML itself, since Playwright loads the page directly.

With more than one target, the JSON result's targets array has one report per target, and text mode prints one report after another.

--format sarif writes a SARIF 2.1.0 log with one rule descriptor per unique axe rule and one result per violating node, merged across every target when more than one is given. It bypasses the envelope entirely, so combine it with --out to feed a static analysis tool such as GitHub code scanning.

--format earl writes an EARL 1.0 report as JSON-LD, the format the W3C reads. The graph is a flat list of assertions, one per failing element, each naming the axe rule that found it and the success criteria that fail with it. Violations become earl:failed, passes earl:passed, incomplete results earl:cantTell, and a run that matched no rule at all becomes a single earl:untested assertion rather than an empty report. Like SARIF it bypasses the envelope, so pair it with --out.

axe exits 4 when a violation remains after --fail-on and --baseline filtering, and 0 otherwise. The JSON envelope's ok field stays true either way. The exit code is the verdict, and the envelope repeats it under result.verdict.

Run with --update-baseline once to accept the current findings, then commit the baseline file so CI only fails on new ones. See understand a violation for what impact means and how to get from a violation to a fix, and script the CLI for the exit codes and the envelope shape.

Thin pages

If the page has fewer than 10 elements and under 50 characters of text, the result adds a warning that a single-page app may not have mounted.

tree

a1 tree

<target>An http(s) URL, a file path, - for HTML on stdin, or --html.
--click <selector>Click the one element this selector matches after the page loads, before reading the tree.
--role <role>Keep only nodes with this role, and their ancestors.
--name <text>Keep only nodes whose accessible name contains this text, and their ancestors.
a1 tree http://localhost:3000
a1 tree http://localhost:3000 --role link
a1 tree http://localhost:3000 --name "Sign in" --json

tree reads Playwright's ariaSnapshot() for the target: the role and name tree a screen reader sees, including JavaScript-rendered content, with no heuristics. Text output is the YAML Playwright produces.

--json parses that YAML into result.nodes, an array of { role, name, level, children } objects.

--role and --name keep a matching node together with every ancestor needed to reach it, so the tree's shape stays intact.

No heuristics

tree runs the page in a real browser, so it sees content a client-side framework renders after load.

Page observations

a1 audit

<target>An http(s) URL, a file path, - for HTML on stdin, or --html.
--fail-on <impact>Only count axe violations at or above this impact toward the exit code: minor, moderate, serious, or critical. Defaults to any violation.
--baseline <file>JSON file of accepted axe findings that do not count toward the exit code.
--update-baselineWrite the current axe violations to --baseline instead of asserting against it.
--results <file>Read recorded manual results from here. Defaults to .a11ied/evidence.jsonl, or $A11IED_EVIDENCE.
--format <format>text, json, or earl. Defaults to text, or json with --json.
--out <file>Write the report to this file instead of stdout.
a1 audit http://localhost:3000 --json
a1 audit http://localhost:3000 --fail-on critical
a1 audit http://localhost:3000 --format earl --out report.earl.json
a1 audit --html '<h1>Hi</h1>'

audit runs axe against every rule mapped in the WCAG version, reads the accessibility tree, and derives applicability from the target's HTML, all against one resolved target. The result includes these sections:

axeThe full axe run.
treePage title, first heading, and landmark, heading, link, button, and form counts.
applicabilityThe signal-backed matrix. See applicability for how the states are decided.
criteriaA per-criterion rollup of axe verdict, applicability state, coverage state, evidence mode, and whether the criterion is still pending a person.
recordedThe results a person or an agent recorded for this target.

result.nextCommands lists a1 wcag rule calls for every failing axe rule.

audit exits 4 when an axe violation remains after --fail-on and --baseline filtering, and 0 otherwise, the same verdict rules as a1 axe.

Checks a11ied cannot automate

Axe checks specific conditions within selected criteria. Assessment procedures cover the remaining behavior and content requirements. An agent records observed results through these commands.

a1 audit pending <target>List criteria with remaining manual procedures. Each returned procedure needs its own recorded result. Reads WCAG data and the evidence file without opening a browser.
a1 audit record <target>Record one outcome. Takes --criterion, --outcome, and optionally --pointer, --note, --procedure, --mode, --by, --run, and --provenance. --finding <file> accepts a JSON title, userImpact, optional remediation, and optional impact. Notes without current run and artifact provenance remain unverified and do not complete a criterion.
a1 audit clear <target>Drop recorded results for one target.
a1 audit pending http://localhost:3000 --level AA
a1 audit record http://localhost:3000 --criterion 2.4.4 --outcome failed \
   --pointer 'nav > a:nth-child(3)' --note "Four links read 'Learn more'."
a1 audit http://localhost:3000 --format earl --out report.earl.json

Pass --results <run-dir>/evidence.jsonl on every audit, pending, and record call in a site audit. Resume with the same file; use a fresh file for a new run. A passing procedure does not erase a failure recorded for another procedure.

--outcome takes passed, failed, cantTell, or inapplicable. Results go to .a11ied/evidence.jsonl, one JSON object per line, so several agent calls can record at once. Recording the same procedure and element again replaces its earlier result. Recording a result never stores it under the axe procedure, so a person's judgment cannot appear in the report as an automated one.

--format earl then writes one report holding both. A recorded result keeps mode: earl:manual or earl:semiAutomatic, so a reader can tell it from an axe result.

One target, one report

audit is the command to reach for first on a new page. Follow up with a1 axe, a1 tree, or a1 wcag show once you know what to look at.

Agent-led assessment

audit run creates durable work for a host agent. It sends no UI input. The agent performs each procedure, saves observed evidence, and evaluates the result. The environment JSON records its observed platform, OS, capabilities, and limitations. Web scope defaults to site; --app selects an existing desktop app target and defaults to app scope.

With --inventory, startup uses the discovered run ID and links the coordinator without editing JSON. Its default path is run.json beside the inventory. A compatible coordinator can be attached after interrupted startup; conflicting identity, profile, environment, policy, or inventory paths are rejected.

Evidence provenance and non-image artifact envelopes include the claimed check's attempts value as attempt. A retry requires fresh proof for that generation, even after a clock change. Raw screenshots retain their PNG format; their provenance and companion artifacts identify the attempt.

a1 audit discover https://createdbyfireside.com --out .a11ied/fireside/inventory.json
a1 audit run https://createdbyfireside.com --environment environment.json \
  --inventory .a11ied/fireside/inventory.json --run .a11ied/fireside/run.json
a1 audit next .a11ied/fireside/run.json --json
a1 audit status .a11ied/fireside/run.json --limit 20 --json
run [url]Requires --environment. Accepts --app, --scope, --wcag, --level, --inventory, --run, --id, and --policy. Policy JSON declares allowed origins and approved submission or destructive actions; both action flags default to disabled.
state, journey, queue <run>Register an observed state, ordered journey, or explicit obligation with --input <file>. Use - for stdin. Responses return the saved identity and revision even beyond the first status page.
next <run>Claim one check with its procedure and observed scope context. Execute its setup and actions, preserve evidence, and supply the required agent judgment. A changed claim is rejected before any UI input.
evaluate <run>Requires --check, --outcome, and saved --evidence <id...> from audit record --run. Missing, mismatched, or stale proof is rejected.
block, resume <run>Block a check with --check and --reason. Resume preserves interrupted work as blocked. After restoring a safe state, pass explicit --retry <check...>; completed assessments cannot be replayed.
status, finalize <run>Status revalidates coverage, artifacts, and scope. Lists use --offset and --limit (1 to 100; default 20). Finalize requires complete validated coverage; --partial returns unresolved work and keeps the run active.

Finalization updates assessment status. Report building remains a separate operation over discovery and page artifacts. Native reader binding and complete installed audits still require their own runtime verification.

Runtime

a1 doctor, a1 mcp, and a1 help-all

a1 doctor
a1 doctor --json
a1 doctor --task scan --strict
a1 doctor --task audit --sr voiceover --strict
a1 doctor --task reader --sr nvda --recording
a1 setup
a1 setup --json
a1 setup --skip-setup
a1 mcp
a1 help-all

doctor checks this machine and leads with a verdict: ✓ ready, or ✗ with the number of setup steps still needed. Action items with the exact commands come first, then each target with its individual checks, the browser a11ied will automate, and the a11ied, Node, npm, and host versions at the bottom.

Use --task scan for browser scans, --task reader for reader sessions, or --task audit for desktop audit prerequisites. Use --sr voiceover on macOS or --sr nvda on Windows to check one reader. A virtual reader cannot satisfy audit prerequisites. These checks do not establish audit coverage.

Recording permission is checked only with --recording. On macOS this captures a temporary video from the current host app and deletes it. Scans do not check reader settings. The exit code is 0 unless you pass --strict, which exits with 3 while a required step is missing. --json wraps the report in the standard envelope, under result.

setup runs the Guidepup commands for this host in order, npx -y @guidepup/setup setup on macOS and then npx -y @guidepup/setup install on macOS and Windows, from the directory where @guidepup/guidepup resolves. Each command keeps the terminal while it runs, and setup stops at the first failure.

It then prints the doctor report and exits with 3 when a required step is still missing. --skip-setup and --skip-install drop one of the two steps. --json replaces the progress lines with an envelope that includes each step's exit code and the closing doctor report under result.

mcp takes no options and speaks stdio. help-all prints every command, option, and the full named-command list in one response, which is what to give an agent instead of a sequence of help calls.

Browsers

Browser selection

The policy is system browser first. a1 axe prefers an installed Chrome, Edge, Brave, or Chromium over Playwright's managed Chromium. If neither is present, the command tells you to run npx playwright install chromium.

a1 doctor --json lists every candidate it found under result.browserAutomation.candidates, with the executable path for each.