Coding agents such as Cursor, Claude Code, GitHub Copilot and Windsurf work inside your own codebase. They read your files, run commands and propose changes you review. That gives you more control than a chat-based site builder, and it also means accessibility depends on the same three things as the rest of your code quality: clear rules, automated checks and a human review. This guide is for developers and covers all three, plus checking the deployed result with ibin.
What coding agents tend to get wrong
Agents copy the patterns they see, in your codebase and in their training data. Most of the web is not accessible: WebAIM’s 2026 analysis of one million home pages found detectable errors on 95.9% of them. Typical results without rules:
- A
divorspanwith anonClickhandler instead of a button, so it cannot be reached with the keyboard. - Icon-only buttons without an accessible name, so a screen reader (software that reads the screen aloud) announces only “button”.
outline: noneto remove a focus ring the designer did not like, without a replacement.- Custom dropdowns, comboboxes and modals rebuilt from scratch, without keyboard support or focus management.
- ARIA attributes added to fix a problem a native element would not have had. Wrong ARIA is often worse than none.
- Hard-coded colours that bypass your design tokens and fail contrast.
- Client-side route changes that leave the document title and focus where they were.
Where the rules go in each tool
Every tool has a file it reads at the start of a task. Check your tool’s documentation, because these locations change.
- Cursor: project rules are
.mdcfiles in.cursor/rules, with frontmatter that controls when they apply. UsealwaysApply: truefor rules that should count in every chat. Cursor also readsAGENTS.mdas a plain-markdown alternative. See Cursor’s rules documentation. - Claude Code:
CLAUDE.mdin the project root (or.claude/CLAUDE.md), loaded at the start of every session. If there is noCLAUDE.md, Claude Code readsAGENTS.mdinstead, and aCLAUDE.mdcan import it with the line@AGENTS.md. See Claude Code’s memory documentation. - GitHub Copilot: repository-wide instructions in
.github/copilot-instructions.md, and path-specific ones in.github/instructions/NAME.instructions.mdwith anapplyTopattern. Copilot’s agents also readAGENTS.md. See GitHub’s documentation. - Windsurf (renamed Devin Desktop in 2026): workspace rules are markdown files in
.devin/rules, with the older.windsurf/rulesstill read. Settrigger: always_onin the frontmatter. A rootAGENTS.mdis always applied. See the rules documentation. - AGENTS.md: an open format for agent instructions, now stewarded by the Agentic AI Foundation under the Linux Foundation and read by many tools, including OpenAI Codex, Gemini CLI, Cursor, Copilot and Windsurf.
A practical setup for a team with mixed tools: put the rules in AGENTS.md, and point the tool-specific files to it. For Claude Code, a CLAUDE.md with a single import line is enough:
@AGENTS.md
For Cursor, if you prefer a dedicated rule over AGENTS.md, create .cursor/rules/accessibility.mdc that starts with this frontmatter:
--- description: Accessibility requirements for all UI code alwaysApply: true ---
The rule block
Add this to AGENTS.md or your tool’s rules file. Adjust the token names and commands to your project.
## Accessibility (WCAG 2.2 AA) - Prefer native elements: button for actions, a href for navigation, label for fields, fieldset/legend for groups, dialog or the design system’s Dialog for modals. Never add onClick to a div or span. - Use ARIA only when no native element fits. Never override a native role. - Every interactive element has an accessible name. Icon-only buttons get aria-label; decorative icons get aria-hidden="true". - Every input has a programmatically associated, visible label. Errors are linked with aria-describedby and shown as text. - Never remove focus outlines without a visible :focus-visible replacement with at least 3:1 contrast. - Use colour tokens from the design system only. Text tokens must reach 4.5:1 against the surfaces they are used on (3:1 for large text and UI parts). Do not hard-code colours. - Focus management: move focus into dialogs, trap it while open, restore it on close. On client-side route changes, update document.title and move focus to the main heading. - Respect prefers-reduced-motion for all non-essential animation. - Keep one h1 per page and headings in order. Set lang on html. - Interactive targets are at least 24x24 CSS px. - Before finishing a UI change, run the linter and the accessibility tests (npm run lint, npm run test:a11y) and fix new violations.
Add automated checks to CI
Rules make good code more likely; checks catch what slips through. Two layers work well together.
A linter for your templates. For React and other JSX code, eslint-plugin-jsx-a11y flags missing alt text, clickable divs, labels without fields and similar mistakes while you type. Vue projects can use eslint-plugin-vuejs-accessibility. With ESLint’s flat config (check that the plugin supports your ESLint version):
import jsxA11y from "eslint-plugin-jsx-a11y"; export default [ jsxA11y.flatConfigs.recommended, // your other configs ];
A browser test for rendered pages. axe-core is an open-source engine that checks a rendered page against many WCAG rules. Playwright, a browser testing tool, can run it on your key pages with the @axe-core/playwright package:
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
test("home page has no detectable accessibility violations", async ({ page }) => {
await page.goto("/");
const results = await new AxeBuilder({ page })
.withTags(["wcag2a", "wcag2aa", "wcag21aa", "wcag22aa"])
.analyze();
expect(results.violations).toEqual([]);
});Run both in CI on every pull request, and mention the commands in AGENTS.md so the agent runs them before it says it is done. Agents are good at fixing a failing check when they can see the error message.
Check the deployed preview with ibin
Tests run against your local build and the pages you chose to cover. A check of the deployed site catches what they miss: third-party scripts, cookie banners, content from your CMS and pages nobody wrote a test for.
- Deploy a preview. Most hosts create a preview address for every pull request. If the preview is protected by a login, use a staging address without protection, or the production address after merging; a checker cannot sign in.
- Check it with ibin. The report lists problems in plain language, ordered by what to fix first, with a close-up picture of each location. The technical detail is under “Code for your developer”.
- Hand the fix to your agent. Each problem has a “Copy instructions for an AI tool” button. The prompt works in Cursor, Claude Code or Copilot just as well as in a site builder: paste it and review the diff.
- Check the whole site. Sign in to check up to 200 pages, and turn on weekly checks so regressions show up in your inbox.
Automated tools, including axe-core and ibin, find roughly a third to half of all accessibility problems. Do the 10-minute keyboard test on new flows, and try a screen reader on your most important form.
What no agent or test can judge
Whether alt text is accurate, whether link texts make sense out of context, whether an error message helps, and whether your copy is clear all depend on meaning. An agent can draft alt text, but it does not know why the image is on the page. Review these by hand when content changes. ibin’s optional second look from AI rates image descriptions, link texts, keyboard use and language from 1 to 5, as leads for a human review.
For the non-technical version of this approach, see the overview for AI builders. The repair guides explain each problem, for example link texts.
Check your deployed site
Deploy a preview and check a page for free with ibin. Paste the instructions for each problem into your coding agent, review the change and check again.
See how your own site does
Check a page for free, without an account. You get a plain list of what to fix first, with pictures of where each problem is.