a11y-loop # a11y-loop ### Accessible UI, checked in a real browser. Your coding agent writes accessible UI, audits the rendered page, fixes what it finds, and tells you what it could not check. Docs npm Benchmark Field notes English · [简体中文](docs/README.zh-CN.md)

a11y-loop, an open-source Agent Skill and command-line tool that has a coding agent write accessible UI, audit the rendered page in a real browser, fix what was found and audit again. The card follows one turn of that loop on the demo page: 159 detectable failures across five rendering passes fall to 0, beside the 44 findings left for review and the 15 manual checks automation cannot judge.
https://github.com/user-attachments/assets/ae827c22-c302-4ca5-b475-ee0c85dbd85e How the film was made: [a11y-loop-promo-film](https://github.com/ChanMeng666/a11y-loop-promo-film).
Previous demo video https://github.com/user-attachments/assets/33ff8672-7690-4581-9ceb-d95476883c54
## Try it **1. The skill, for any agent that reads Agent Skills** (Claude Code, Codex, Cursor, Copilot, Gemini CLI and others): ```bash npx skills add ChanMeng666/a11y-loop -g -y ``` **2. The command-line tool and its browser** (the audit needs both): ```bash npm i -g a11y-loop a11y-loop install-browser # Chromium headless shell for a11y-loop's own Playwright (~280 MB on disk) a11y-loop doctor # checks Node, the browser and where the skill is installed ``` Start a new agent session and ask for UI as usual. The skill applies while the agent plans and writes it. Agents outside Claude Code's plan mode (Codex, Cursor, Copilot, CI) run `a11y-loop plan-check --file plan.md` before building UI; it exits 1 when a UI plan names no accessibility decisions. To audit a page yourself: ```bash a11y-loop audit http://localhost:3000 ``` MCP-only clients (after `npm i -g @modelcontextprotocol/server zod`, which a normal install skips): `a11y-loop mcp` serves the audit, diff, contrast, plan-check and doctor commands, and the manual checklist, as six MCP tools over stdio ([setup](docs/overview.md#mcp-server)). GitHub Actions: `uses: ChanMeng666/a11y-loop@v0.4.1` audits in CI and writes the result to the job summary ([GitHub Marketplace](https://github.com/marketplace/actions/a11y-loop-audit), [setup](docs/overview.md#%EF%B8%8F-using-it-in-ci)). ### Claude Code: the plugin instead of step 1 The plugin carries the skill, a `/a11y-plan` command and two hooks. One asks for an accessibility section in a UI plan. The other asks for an audit before a session that changed UI ends. Install the plugin **or** the skill, not both. The hooks run only in Claude Code; [other clients and CI](docs/agent-gates.md) have their own routes to the same plan and audit checks. ```text /plugin install a11y-loop --marketplace ChanMeng666/a11y-loop ``` From a terminal (Claude Code 2.1.292 or later): ```bash claude plugin install a11y-loop --marketplace ChanMeng666/a11y-loop ``` Older versions: ```bash claude plugin marketplace add ChanMeng666/a11y-loop claude plugin install a11y-loop@chanmeng-a11y-loop --scope user ``` You still need step 2 for the audit. ### Codex: the plugin ```bash codex plugin marketplace add ChanMeng666/a11y-loop codex plugin add a11y-loop@chanmeng-a11y-loop ``` ### Windows Step 1 and step 2 work as written in PowerShell, Windows PowerShell and Git Bash. The `npx skills` installer is the cross-platform way to add the skill. If you copy the skill by hand instead, use the variant for your shell. Re-running it upgrades in place. Do not copy over a skill that `npx skills add` already linked into `~/.claude/skills`: the copy fails on the link, and the skill is already there. PowerShell: ```powershell New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null Copy-Item -Recurse -Force "$(npm root -g)\a11y-loop\skills\a11y-loop" "$HOME\.claude\skills\" ``` Git Bash, macOS, Linux: ```bash mkdir -p ~/.claude/skills cp -r "$(npm root -g)/a11y-loop/skills/a11y-loop" ~/.claude/skills/ ``` cmd.exe is not supported for these commands. Use PowerShell. If you keep browsers off the system drive, set `PLAYWRIGHT_BROWSERS_PATH` before `a11y-loop install-browser` and keep it set when you audit. ### What it runs on your machine - **The skill** is text. It runs nothing by itself. - **The plugin's plan hook** runs `node hooks/plan-gate.mjs` from the plugin's folder before Claude Code leaves plan mode. It reads the plan text and writes one small state file to Claude Code's plugin data directory (or the temp directory). It makes no network requests. Turn it off with `A11Y_LOOP_PLAN_GATE=off`. - **The plugin's audit hook** runs `node hooks/audit-gate.mjs` when Claude is about to finish. It reads the session transcript Claude Code already keeps, looking for UI file edits and audit commands, and writes one small state file to the same place. It runs no audit itself and makes no network requests. Turn it off with `A11Y_LOOP_AUDIT_GATE=off`. - **Installing the plugin** copies the repository's `plugin/` folder into Claude Code's plugin cache and fetches no packages. Version 0.3.0 and earlier shipped the whole repository as the plugin, so the install also ran `npm ci` there and downloaded about 24 MB of packages the plugin did not use. - **The command-line tool** is a separate install (`npm i -g a11y-loop`). It launches a local Chromium, serves `--file` and `--html` targets on a localhost port, and opens only the URL you give it. It sends no telemetry. - **`a11y-loop install-browser`** downloads the Chromium headless shell from Playwright's CDN, about 280 MB on disk. `--full` adds the full Chromium (about 715 MB in all), which only `audit --headed` needs. - **In claude.ai chat**, only the skill's rules apply. There is no Node or browser there, so the audit cannot run and the hooks do not load. A clean audit means no automatically detectable failures were found in the states and passes that ran. It is not a conformance claim. Every run ends with a checklist of what still needs a person. Nothing is collected or sent to the author. See [PRIVACY.md](PRIVACY.md). ## Why a loop - **Five rendering passes, not one page load.** Default, dark mode, forced colors, reduced motion and a 320 px reflow viewport, plus the states the agent built: an open modal, an expanded menu, a form error. - **The end of the loop can be checked.** `a11y-loop diff` marks each finding FIXED, NEW or REMAINING. A new one fails the run even when the total went down. - **It lists what it could not check.** A clean report means no automatically detectable failures were found. It is never a conformance claim. Every run comes with a manual-review checklist for what needs a person or assistive technology. ```mermaid flowchart LR W[Agent writes UI] --> A[Audit in a real browser] A --> V{Violations?} V -->|yes| F[Agent fixes them] --> A V -->|no| D([Report and
manual-review checklist]) ``` ## For your agent This page is all a person needs. Everything else is written for agents: clone the repo and point yours at [`AGENTS.md`](AGENTS.md) and [`skills/a11y-loop/SKILL.md`](skills/a11y-loop/SKILL.md), or start from [`llms.txt`](llms.txt). [Full overview](docs/overview.md) · [Honest coverage](docs/overview.md#-honest-coverage) · [Using it in CI](docs/overview.md#%EF%B8%8F-using-it-in-ci) · [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Third-party notices](THIRD-PARTY-NOTICES.md) · [MIT](LICENSE) Built by [Chan Meng](https://github.com/ChanMeng666).