{"_id":"@a11y-lens/cli","_rev":"2-d4a27ee3365e1015e2d9cb1601d2c25a","name":"@a11y-lens/cli","dist-tags":{"latest":"0.4.1"},"versions":{"0.4.0":{"name":"@a11y-lens/cli","version":"0.4.0","keywords":["accessibility","a11y","lint","wai-aria","wcag","ai","agent","pre-commit","semantic-review"],"author":{"url":"https://github.com/jo-duchan","name":"Duchan Jo","email":"jo_duchan@icloud.com"},"license":"MIT","_id":"@a11y-lens/cli@0.4.0","maintainers":[{"name":"joduchan","email":"jo_duchan@icloud.com"}],"homepage":"https://github.com/jo-duchan/a11y-lens#readme","bugs":{"url":"https://github.com/jo-duchan/a11y-lens/issues"},"bin":{"a11y-lens":"bin/a11y-lens.mjs"},"dist":{"shasum":"9c4af4b1b00ec62f0e02efc6b0399fa2480f2d68","tarball":"https://registry.npmjs.org/@a11y-lens/cli/-/cli-0.4.0.tgz","fileCount":18,"integrity":"sha512-ZXWTlg8VkF3zBKX3Mvl+lDp6dxJUcmjgiK6PJZ06ypJr4dIysdFBp+KWyNQ6pCZ0fhWbYyP9W6iY4Gu78f0hKw==","signatures":[{"sig":"MEUCIQDaPRYk7P6NcQFofGl+zPjKCStHKrORs7mXMiqw3adhCAIgSdWEiVijipJ8f+HYgt+NgJJSAETonxPgVLLZoQgDzLI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48074},"type":"module","engines":{"node":">=18"},"gitHead":"cdb35d732a2954fb6730426ed4222353f7149a81","scripts":{"test":"node --test test/"},"_npmUser":{"name":"joduchan","email":"jo_duchan@icloud.com"},"repository":{"url":"git+https://github.com/jo-duchan/a11y-lens.git","type":"git"},"_npmVersion":"11.12.1","description":"AI-powered semantic accessibility linter — reviews what static linters can't see. Runs on Claude Code, Codex, or Cursor at commit time.","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/cli_0.4.0_1783534466448_0.18903425791099204","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@a11y-lens/cli","version":"0.4.1","publishConfig":{"access":"public"},"description":"AI-powered semantic accessibility linter — reviews what static linters can't see. Runs on Claude Code, Codex, or Cursor at commit time.","type":"module","bin":{"a11y-lens":"bin/a11y-lens.mjs"},"scripts":{"test":"node --test test/"},"keywords":["accessibility","a11y","lint","wai-aria","wcag","ai","agent","pre-commit","semantic-review"],"author":{"name":"Duchan Jo","email":"jo_duchan@icloud.com","url":"https://github.com/jo-duchan"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/jo-duchan/a11y-lens.git"},"engines":{"node":">=18"},"gitHead":"3f78d705a7cdf29208d31d1132bb92c6664132d6","_id":"@a11y-lens/cli@0.4.1","bugs":{"url":"https://github.com/jo-duchan/a11y-lens/issues"},"homepage":"https://github.com/jo-duchan/a11y-lens#readme","_nodeVersion":"24.18.0","_npmVersion":"11.18.0","dist":{"integrity":"sha512-ttJs3AZ5l9nmN1L70gm0g7GX7qt0bCpOgT8tG2FoniwY8RyrP/ErF7J6jr8xbSFykRXhaRx4+U9UqldeEtcTIg==","shasum":"4333d797f761ea1f801b56b90c749f27e434a45b","tarball":"https://registry.npmjs.org/@a11y-lens/cli/-/cli-0.4.1.tgz","fileCount":18,"unpackedSize":49669,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@a11y-lens%2fcli@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCCbqd+MYbtrk1eS/0Jp2KfLxQ4hgftKJfBwnPCwOsZPQIgctgum9AgGkgbJrjm/5xVBEKSKM8+Shw2y1FH6jT092Y="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bf3b5aff-2803-4684-afc5-ac753fa1200f"}},"directories":{},"maintainers":[{"name":"joduchan","email":"jo_duchan@icloud.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cli_0.4.1_1783593475299_0.18289447739963327"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-08T18:14:26.289Z","modified":"2026-07-09T10:37:55.812Z","0.4.0":"2026-07-08T18:14:26.588Z","0.4.1":"2026-07-09T10:37:55.491Z"},"bugs":{"url":"https://github.com/jo-duchan/a11y-lens/issues"},"author":{"name":"Duchan Jo","email":"jo_duchan@icloud.com","url":"https://github.com/jo-duchan"},"license":"MIT","homepage":"https://github.com/jo-duchan/a11y-lens#readme","keywords":["accessibility","a11y","lint","wai-aria","wcag","ai","agent","pre-commit","semantic-review"],"repository":{"type":"git","url":"git+https://github.com/jo-duchan/a11y-lens.git"},"description":"AI-powered semantic accessibility linter — reviews what static linters can't see. Runs on Claude Code, Codex, or Cursor at commit time.","maintainers":[{"name":"joduchan","email":"jo_duchan@icloud.com"}],"readme":"# a11y-lens\n\n> **Package** [`@a11y-lens/cli`](https://www.npmjs.com/package/@a11y-lens/cli) · **CLI** `a11y-lens` · **Skill** `npx skills add jo-duchan/a11y-lens`\n\n**AI-powered semantic accessibility linter.** Reviews what static linters can't see — using the AI coding agent you already have (Claude Code, Codex, or Cursor).\n\nStatic linters check **syntax**: *does this `img` have an `alt`?*\na11y-lens checks **semantics**: *does this `alt` actually describe the image? Is this custom dropdown's keyboard interaction complete per the WAI-ARIA combobox pattern? Does the modal return focus to its trigger?*\n\n```\n$ git commit -m \"add plan selector\"\na11y-lens: reviewing 1 file(s) with claude…\n\nsrc/PlanSelect.jsx\n  ✖ error:23  [aria-widgets] Custom dropdown is a div with onClick only — no combobox\n     role, no aria-expanded, no listbox/option semantics. AT users get a plain text node.\n     fix: use role=\"combobox\" + aria-expanded + role=\"listbox\"/\"option\", or a native <select>\n  ✖ error:23  [keyboard-interaction] Dropdown cannot be operated by keyboard: no ArrowDown/\n     ArrowUp/Enter/Escape handling per the APG combobox pattern.\n     fix: add onKeyDown implementing the APG combobox key set\n\na11y-lens: 2 error(s), 0 warning(s) (reviewed by claude)\nhusky - pre-commit hook exited with code 1\n```\n\n## How it works\n\n1. Collects the **staged** UI files (`.jsx`, `.tsx`, `.html`, `.vue`, `.svelte`, …) and their diffs.\n2. Sends them — together with a distilled rule set (`skills/a11y-lens/references/*.md`, drawn from WAI-ARIA APG, WCAG 2.2, eslint-plugin-jsx-a11y and axe-core coverage) — to a headless agent CLI: `claude -p`, `codex exec`, or `cursor-agent -p`, whichever is installed.\n3. Parses the structured findings and gates the commit on `error` severity. Warnings report but never block (unless `--strict`).\n\n**Infrastructure never blocks a commit.** No agent CLI, no network, agent crash → a11y-lens warns and exits 0. Only real accessibility findings gate.\n\n## It samples; it does not audit\n\na11y-lens is an AI reviewer, not a deterministic linter. The same files reviewed twice can return different findings — even zero on a run that flagged issues a moment earlier. Read the output with that in mind:\n\n- **A clean run ≠ zero issues.** It means nothing surfaced *in that sample*, not that the code is fully accessible.\n- **Findings don't converge to zero.** Re-running to \"clear\" every last warning is the wrong mental model; a later run may raise something new.\n- **The intended job is gating `--staged` diffs** — catching problems as they're *introduced*. It is not a full-audit tool for an existing codebase; for that, pair it with a human accessibility review.\n\nThis is deliberate: only clear `error`-severity violations gate and warnings never block, precisely because AI output varies run to run. (This note belongs here, in the tool's own README — not in the `AGENTS.md` rules block that `init` injects into a consuming project, which is reserved for the accessibility rules themselves.)\n\n## Install\n\na11y-lens has two layers — install either or both:\n\n**Write time (agent skill).** Teaches your coding agent the rules so UI code is accessible *before* the hook ever runs. [The skills CLI](https://skills.sh) installs it for Claude Code, Codex, Cursor, and 60+ other agents:\n\n```bash\nnpx skills add jo-duchan/a11y-lens\n```\n\n**Commit time (git hook gate):**\n\n```bash\nnpm install -D @a11y-lens/cli   # or pnpm add -D / yarn add -D\nnpx a11y-lens init\n```\n\n`init` installs the pre-commit hook for you — it detects lefthook (`lefthook.yml`), husky (`.husky/`), or plain `.git/hooks`, picks your package manager's runner (`pnpm exec` / `yarn` / `bunx` / `npx`), and adds the check idempotently. It also injects a rules reference into your `AGENTS.md` (a lightweight fallback for agents without skills support). Use `--no-hook` to skip hook installation.\n\nExample (lefthook):\n\n```yaml\npre-commit:\n  jobs:\n    - name: a11y-lens\n      run: npx a11y-lens check --staged\n```\n\n## Usage\n\n```bash\na11y-lens check --staged           # what the git hook runs\na11y-lens check src/Modal.tsx      # review specific files\na11y-lens check --staged --strict  # warnings also fail\na11y-lens check --staged --agent codex\na11y-lens rules                    # list rule categories\n```\n\nEscape hatches: `A11Y_LENS_SKIP=1 git commit …` or `git commit --no-verify`.\n\n## Rule set\n\nOne markdown file per category in `skills/a11y-lens/references/`, consumed by both the skill and the CLI. Each separates the **static baseline** (what eslint/axe already catch — not re-reported) from the **semantic checks** this tool exists for.\n\n| Category | Semantic checks (examples) |\n|---|---|\n| `01-landmarks-headings` | outline describes the document, not the visual design; one `h1`; labelled landmarks |\n| `02-images-alt` | `alt` describes function in context; decorative silenced, informative never; icon-only controls named by action |\n| `03-forms-labels` | placeholder ≠ label; errors tied via `aria-describedby`; accessible name matches visible label |\n| `04-aria-widgets` | claimed APG patterns must be **complete** — half a combobox is worse than none; state in ARIA, not just CSS |\n| `05-keyboard-interaction` | full APG key sets; no hover-only affordances; no keyboard traps |\n| `06-focus-management` | overlays move focus in and return it; async results announced via live regions; SPA route changes handled |\n\nRules are plain markdown — tune them for your project by editing the files, no code changes needed.\n\n## Why commit-time AI review is cheap now\n\nIn AI-native workflows the entity blocked at pre-commit is usually **an agent, not a human**. A 10–30 second semantic review is a fine price when the committer can read the findings, fix them, and retry without getting annoyed.\n\n## Requirements\n\n- Node ≥ 18, zero runtime dependencies\n- One of: [Claude Code](https://claude.com/claude-code) (`claude`), [Codex CLI](https://github.com/openai/codex) (`codex`), [Cursor CLI](https://cursor.com/cli) (`cursor-agent`), logged in\n\n## License\n\nMIT © Duchan Jo — see [NOTICE](./NOTICE) for rule-set attributions (eslint-plugin-jsx-a11y, axe-core, W3C WAI-ARIA APG, WCAG 2.2).\n","readmeFilename":"README.md"}