# 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.
English · [简体中文](docs/README.zh-CN.md)
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).