@a11y-ai/cli
v0.1.0
Published
AI Accessibility Engineer — scan, fix and verify web a11y (WCAG/KWCAG)
Maintainers
Readme
a11y-ai — AI 접근성 엔지니어
웹 접근성을 스캔 → 수정 → 재검증하는 CLI. 결정론적 엔진(axe + 정적 규칙, KWCAG 2.2 / WCAG 2.2)이 사실을 잡고, 자체 학습한 판별기가 규칙이 못 잡는 의미 품질(무의미한 alt·모호한 링크/제목/라벨)을 판단한다.
npx @a11y-ai/cli scan . # 접근성 스캔 (정적/런타임)
npx @a11y-ai/cli scan . --ai --fix # AI 판단 + 최소 안전 패치 + 재검증
npx @a11y-ai/cli ci . --static # CI 게이팅 + SARIF(Code Scanning) + PR 요약- 결정론 + AI 2계층 — axe는 ground truth로 유지, AI는 의미 품질만 판단(스키마 검증, 그대로 신뢰 안 함)
- 다프레임워크 — React · Vue · HTML · JSP · PHP · Thymeleaf 등
- CI 네이티브 — SARIF 2.1.0 → GitHub Code Scanning, PR 게이팅(GitHub Action)
- 로컬 대시보드 —
a11y-ai dashboard(점수·추이·히스토리, 자체완결 HTML) - 프라이버시 — 데이터 수집 기본 off·로컬, 원격은 명시 동의 + 메타데이터 전용(데이터 & 프라이버시)
AI 판단 provider (--provider) — 키·비용
AI 의미 품질 판단의 백엔드를 당신이 선택한다. CLI는 완전 클라이언트측이라 어떤 데이터도 이 도구 제작자의 서버·키로 라우팅되지 않는다.
| --provider | 무엇 | 키·비용 |
| --- | --- | --- |
| mock (기본) | 오프라인 휴리스틱 | 키·API 없음, 무료 |
| anthropic | Anthropic LLM 판단 | 당신 자신의 ANTHROPIC_API_KEY(환경변수)로 호출 → 당신이 과금 |
| local-clf / local-ens | 자체 파인튜닝 분류기 | 당신이 직접 서빙(serve_clf.py), A11Y_CLF_URL |
npx @a11y-ai/cli scan . --ai # 기본 mock(무료)
ANTHROPIC_API_KEY=sk-ant-... npx @a11y-ai/cli scan . --ai --provider anthropic # 본인 키anthropic은 실행 시점에 **본인 환경의ANTHROPIC_API_KEY**를 읽는다. 안 넣으면 "키 없음,--provider mock쓰세요" 에러.- 패키지에는 어떤 API 키도 포함돼 있지 않다(번들 시크릿 스캔 통과). 키는 각자 본인 것만 쓴다.
설치 & 준비 (사용자)
설치 없이 npx로 바로, 또는 전역 설치 — 매니저 무관:
npx @a11y-ai/cli scan . # 설치 없이 일회 실행
pnpm dlx @a11y-ai/cli scan . # pnpm
pnpm add -g @a11y-ai/cli # (또는 npm i -g / yarn global add / bun add -g)- 정적 스캔(
--static)·CI: 추가 준비 없음. 소스만 읽는다(브라우저 불필요). - 런타임/인증 스캔(실제 렌더된 페이지·로그인 화면): Playwright 브라우저가 필요하다 —
그 뒤 대상 앱 dev 서버를 띄우고npx playwright install chromium chromium-headless-shellscan --base-url …(로그인 화면은 §4-1 인증).
로컬(개발) 실행 — 이 저장소에서 직접
리포에서 직접 돌릴 때는 대상 프로젝트를 경로 인자로 지정한다. 대상을 수정·설치할 필요 없이 (런타임 스캔 시 대상 dev 서버만 떠 있으면) 어디서든 검사·수정할 수 있다.
1. 준비 (최초 1회)
# 이 저장소(agentic)에서
pnpm install
pnpm --filter @a11y-ai/browser exec playwright install chromium chromium-headless-shell- Node 22+, pnpm 필요.
- Playwright 크로미엄은 이 저장소에 한 번만 설치하면 모든 대상 프로젝트에 재사용됩니다.
2. a11y-ai를 어디서나 실행되게 만들기
bin/a11y-ai 런처를 PATH에 연결하면 됩니다(빌드·전역 설치 불필요):
# 이 저장소 루트에서
ln -s "$(pwd)/bin/a11y-ai" /usr/local/bin/a11y-ai
# 또는 PATH에 <repo>/bin 추가: export PATH="$PATH:$(pwd)/bin"
a11y-ai --help런처는 심볼릭 링크를 따라 이 저장소를 찾아, 저장소의 tsx·의존성·브라우저로 CLI를 실행합니다.
(이하 예시는 a11y-ai로 표기 — 저장소 안에서는 pnpm cli로도 동일하게 실행됩니다.)
3. 대상 프로젝트 요구사항
- dev 서버 스크립트:
package.json에dev(또는start)가 있어야 합니다. 없으면 프레임워크 기본값을 추정합니다. 서버사이드(PHP/JSP/Django/Spring)는 dev 스크립트로 서버 기동 명령을 지정하세요 (예:"dev": "php -S 127.0.0.1:8000 -t public"). - 의존성 설치 완료: 대상 프로젝트에서
npm install등으로 앱이 실제 구동 가능해야 합니다. - (선택)
.a11y-ai.json을 대상 루트에 두면 baseUrl·게이팅·routes 등을 지정할 수 있습니다.
// <your-project>/.a11y-ai.json
{
"level": "AA",
"failOn": "serious", // 이 심각도 이상이면 CI에서 빌드 차단
"provider": "mock", // mock(무료)|anthropic(본인 ANTHROPIC_API_KEY)|local-clf — §provider
"baseUrl": "http://localhost:5173", // 대상 dev 서버 URL(미지정 시 프레임워크 기본값)
"command": "pnpm run start", // (선택) 구동 명령 오버라이드 — 프로덕션 빌드 검사(§프로덕션)
"routes": ["/"], // 검사할 경로들 (미지정 시 프레임워크 라우트 자동 발견 — §라우트 커버리지)
"maxIterations": 3, // 자동 수정 재시도 상한
"minFixConfidence": 0.7, // 소스 매핑 신뢰도 하한(미만이면 자동수정 보류)
"exclude": ["node_modules", "dist"],
"auth": { "storageState": ".a11y-ai/auth.json" } // 로그인 필요 화면 검사(§4-1)
}4. 실제 사용 흐름
# 0) 정적(무실행) 진단 — dev 서버·브라우저 불필요, 어떤 프로젝트든 즉시
a11y-ai scan ~/work/my-app --static # 소스만 파싱해 마크업 규칙 검사(수초)
a11y-ai scan ~/work/my-app --static --format json --output a11y.json
# 0-1) AI 판단형 탐지 — 규칙이 못 잡는 "의미 품질"
# alt · 링크·버튼("여기 클릭") · 제목("제목"·"Section") · 폼 라벨("입력")
a11y-ai scan ~/work/my-app --static --ai # 오프라인 휴리스틱(무료)
a11y-ai scan ~/work/my-app --static --ai --provider anthropic # 실제 LLM 의미 판단(고품질)
# 0-1a) AI 개선 제안 — 지적한 항목을 "더 나은 텍스트"로 제안(탐지→수정, 참고용)
a11y-ai suggest ./app # 휴리스틱 가이드
a11y-ai suggest ./app --provider anthropic # LLM 구체 제안(현재 → 제안)
# 0-1b) AI 판단 정확도 평가 — gold 벤치마크 대비 정밀도/재현율/F1
a11y-ai eval # 오프라인 휴리스틱 정확도
a11y-ai eval --provider anthropic # 휴리스틱 vs 실제 LLM 비교
# 0-2) 학습 데이터 수집(옵트인·로컬) + 사람 라벨링 — "데이터 해자"(§DATA.md)
a11y-ai scan ~/work/my-app --static --ai --collect-data # 판정을 .a11y-ai/data 에 적재
a11y-ai review ~/work/my-app # 기계 판정을 사람이 확인/교정(gold)
a11y-ai dataset ~/work/my-app # 학습셋 빌드(.a11y-ai/dataset)
# 1) 런타임 진단 — 실제 브라우저로 렌더해 판정(권장, 색대비·포커스·동적까지)
a11y-ai scan ~/work/my-app
a11y-ai scan ~/work/my-app --format html --output a11y.html # 공유용 리포트
# 2) 원인·위치 분석
a11y-ai analyze ~/work/my-app
# 3) 자동 수정 (승인 → 적용 → 재빌드 → 재검사, 실패 시 재시도·롤백)
a11y-ai fix ~/work/my-app # 대화형 승인
a11y-ai fix ~/work/my-app --all --yes # 모든 SAFE 이슈 일괄
a11y-ai fix ~/work/my-app --changed --yes # git 변경 파일만 (PR 워크플로)
a11y-ai fix ~/work/my-app --commit # 통과한 수정을 새 브랜치에 커밋
# 4) 개발 중 저장할 때마다 자동 재검사
a11y-ai watch ~/work/my-app
# 5) 리포트/대시보드/인증
a11y-ai dashboard ~/work/my-app # 점수·추세·AI 성능 (누적)
a11y-ai cert ~/work/my-app # KWCAG 2.2 인증 준비도
a11y-ai metrics ~/work/my-app --format json
# 6) CI (SARIF + Job Summary + 게이팅)
a11y-ai ci ~/work/my-app --changed --base origin/main --fail-on serious --sarif a11y.sarif산출물은 대상 프로젝트의 .a11y-ai/(캐시·스캔 히스토리·수정 시도 기록)에 쌓입니다.
.gitignore에 .a11y-ai/를 추가하는 것을 권장합니다.
4-0. 라우트 커버리지 (런타임 스캔 대상 페이지)
런타임 스캔은 방문한 페이지만 검사합니다. routes를 지정하지 않으면 프레임워크의 파일 규칙에서
정적 라우트를 자동 발견해 전 페이지를 커버합니다(설정하면 그게 우선):
| 프레임워크 | 발견 방식 | 예 |
| --- | --- | --- |
| Next App Router | app/**/page.* → 디렉터리 경로 | app/about/page.tsx → /about (라우트 그룹 (...) 제거) |
| Next Pages / Nuxt | pages/ 파일 경로 | pages/blog/index.tsx → /blog |
| React Router | 소스의 <Route path="…"> 정적 추출 | path="/settings" → /settings |
- 동적 세그먼트(
[id]·:id·*)는 자동 제외 — 실제 파라미터 값을 지어낼 수 없기 때문. 필요하면"routes": ["/posts/123"]처럼 대표 URL을 직접 지정하세요. - 정적 스캔(
--static)은 이미 소스 전수 검사라 이 문제가 없습니다(런타임에만 해당).
4-1. 로그인이 필요한 화면 검사 (인증)
대시보드·마이페이지처럼 로그인해야 보이는 화면은 저장된 세션으로 검사합니다. 실제 브라우저에서 한 번 로그인하면 쿠키·localStorage(세션)를 파일로 저장해 두고, 이후 스캔이 그 세션을 재사용합니다.
# 1) 실제 브라우저 창이 뜹니다 → 손으로 로그인 → 터미널에서 Enter
a11y-ai login ~/work/my-app # 세션을 .a11y-ai/auth.json 에 저장
a11y-ai login ~/work/my-app --output .secrets/auth.json # 저장 위치 지정
# 2) 이후 모든 명령에 --auth 로 인증 상태 검사 (scan/analyze/fix/watch 공통)
a11y-ai scan ~/work/my-app --auth .a11y-ai/auth.json
a11y-ai analyze ~/work/my-app --auth .a11y-ai/auth.json
a11y-ai fix ~/work/my-app --auth .a11y-ai/auth.json --all --yes검사할 보호 화면은 .a11y-ai.json의 routes에 추가하세요(예: "routes": ["/", "/account", "/dashboard"]).
또는 "auth": { "storageState": ".a11y-ai/auth.json" }를 넣으면 --auth 없이도 항상 인증 상태로 검사합니다. 세션 파일에는 로그인 쿠키가 들어 있으니 커밋하지 마세요
(.gitignore에 추가). 세션이 만료되면 a11y-ai login을 다시 실행하면 됩니다.
login은 실제 창을 띄우는 headed 브라우저라 로컬(사람이 앉아 있는) 환경에서만 실행됩니다. CI처럼 무인 환경에서는, 로컬에서 만든auth.json을 안전한 시크릿으로 주입하거나 테스트 계정 세션을 스크립트로 생성해--auth로 넘기세요.
5. 실제 LLM(Anthropic) 사용
기본은 결정론적 mock(네트워크 불필요)입니다. 실제 모델을 쓰려면:
echo 'ANTHROPIC_API_KEY=sk-ant-...' >> .env # 실행 CWD의 .env를 자동 로드(로그 마스킹)
a11y-ai fix ~/work/my-app --provider anthropic6. 지원 프레임워크
| 계열 | 소스 매핑 |
| --- | --- |
| React (Vite) | dev 힌트(0.95) / fiber / AST |
| Next.js (Pages/App Router, R18·R19) | fiber / AST |
| Vue (SFC) | @vue/compiler-sfc |
| Angular | HTML(parse5) 어댑터 |
| PHP · JSP · ASP.NET Razor · Django · Thymeleaf | HTML 어댑터(서버 태그 전처리) |
소스 위치 신뢰도 — dev 빌드의 소스 힌트(0.95)나 유일 AST 매칭은 파일:라인을 확정 표기합니다.
반대로 프로덕션 빌드·서버 컴포넌트처럼 힌트가 없고 후보가 모호한 경우(예: 색대비가 흔한 <div>에
걸릴 때)는 추측을 확정처럼 보여주지 않습니다 — 신뢰도 0.7 미만이면 항상 정확한 CSS 선택자를
1순위로 표시하고 파일은 추정으로 표기합니다. 정확한 파일 위치가 필요하면 dev 빌드로 스캔하세요
(React data-a11y-src/fiber 힌트가 붙어 0.95가 됩니다). 프레임워크별로 매칭 소스 종류를 제한하므로
React/Vue 앱이 무관한 docs/*.html로 오귀속되지 않습니다.
7. 안전장치 (§13)
- AI 출력은 zod 스키마 검증 후에만 사용, 패치 앵커 존재를 확인 후 적용.
- 적용 → 빌드 실패·미개선·regression 시 자동 롤백.
- 소스 매핑 신뢰도가
minFixConfidence미만이거나 대체 텍스트를 확정 못하면 자동 적용 보류 (--force로 강제). 규칙 판정·통과 여부는 항상 결정론적 엔진 + 실제 브라우저가 판정합니다.
문제 해결
- dev 서버가 안 뜸: 대상에서
npm run dev가 직접 되는지 확인,.a11y-ai.json의baseUrl·포트 확인. - 소스 위치가
추정으로 표시됨: 힌트 없는(프로덕션 빌드·서버 컴포넌트) 모호한 요소는 파일 위치를 단정하지 않고 정확한 CSS 선택자를 대신 보여줍니다. 확정 위치가 필요하면 dev 빌드로 스캔(힌트 0.95), 자동 수정은--force또는 수동 검토로 진행하세요. - Playwright 브라우저 오류: 준비 단계의
playwright install을 다시 실행. - 일부 경로가 HTTP 500/
렌더 실패로 제외됨: dev 서버(특히 Next--turbopack)가 콜드 부팅 중 여러 경로를 연속 탐색하면 청크 로딩 오류로 500을 내는 경우가 있습니다. 이는 앱의 접근성 문제가 아니라 dev 서버 상태이며, 도구는 렌더되지 않은 페이지(비 2xx)를 판정에서 자동 제외합니다(에러 페이지의 접근성을 앱 결과로 잘못 집계하지 않도록). 안정적인 검사가 필요하면 프로덕션 빌드로 검사하세요:// .a11y-ai.json — dev 대신 프로덕션 빌드/서버로 검사 { "command": "pnpm run start", // ⚠ bare "next start"는 PATH 문제로 실패 → run 스크립트/npx 형태로 "baseUrl": "http://localhost:3000" }
실제 Next 15 프로젝트에서 dev 500 → 프로덕션 빌드 검사로 해결한 사례는pnpm build # 먼저 프로덕션 빌드 (= next build) a11y-ai scan . # command(next start)로 프로덕션 서버 구동 후 검사PILOT.md참고.
데이터 & 프라이버시
a11y-ai는 데이터 수집이 기본 비활성이며, 켜도 로컬 저장이 기본입니다.
- 로컬 수집(opt-in):
scan --ai --collect-data→ 판정을 사용자 머신의.a11y-ai/data/에만 저장. 아무것도 외부로 나가지 않습니다. - 원격 기여(이중 잠금): 중앙 코퍼스로 업로드는 다음을 모두 충족해야만 발생합니다 —
①
.a11y-ai.json에data.remote.endpoint+consent:true, 그리고 ② 그 머신에서a11y-ai data consent로 기록된 명시 동의. 수집 서버는 SaaS의POST /v1/judgments(인증 필요, NDJSON)이며, 설정 예시:
committed된 설정 파일만으로는 절대 전송되지 않습니다(팀원 데이터 무단 유출 방지)."data": { "remote": { "endpoint": "https://<your-host>/v1/judgments", "token": "a11y_…(API 키)", "consent": true, "metadataOnly": true } } - 메타데이터 전용 기본: 원격 전송 시 기본적으로 원문 텍스트를 제외하고 종류·규칙·good/poor만 보냅니다(
data.remote.metadataOnly, 기본 true). 전송 전 경로 해시 + PII/시크릿 스크럽 적용(완벽 보장은 아님). - 사용자 권리:
a11y-ai data stats|export|purge(열람·이동·삭제),a11y-ai data consent --revoke(철회). - 배포 안전장치: 배포 번들은
dist/만 포함하고, 빌드 시 시크릿/고객데이터 스캔을 통과해야 발행됩니다.
사설·상용 코드에서 파생된 데이터를 외부로 보내는 결정은 회사 정책·법적 근거(개인정보보호법/GDPR) 검토가 선행되어야 하며, 그 책임은 사용자에게 있습니다. 권장: 내 프로젝트 + 계약상 동의한 파일럿 고객에서만 원격 수집.
GitHub Action (CI 통합)
스캔을 고객의 CI에서 돌리고 결과를 **PR 요약 + Security 탭(Code Scanning)**에 띄운다 — 서버·샌드박스 불필요(§DEPLOY 1인 전략).
공개 npm 패키지만으로 동작한다(공개 Action 리포 불필요). .github/workflows/a11y.yml:
permissions:
contents: read
security-events: write # SARIF 업로드에 필요
jobs:
a11y:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "22" }
- run: npx -y @a11y-ai/cli ci . --static --fail-on serious --sarif a11y.sarif
- if: always()
uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: a11y.sarif, category: a11y-ai }Maven/Gradle(Java/JSP) 빌드 통합은 JAVA.md 참고 (frontend-maven-plugin / node-gradle가 Node를 자동 관리).
한 줄 편의 Action(
uses: <owner>/a11y-ai@v0)도 있지만, 그건 이 Action 리포가 public일 때만 외부에서 쓸 수 있다. 위npx방식은 리포 공개 여부와 무관하게 동작한다.
- PR 게이팅:
fail-on이상 심각도면 빌드 실패(exit 1). - Step Summary: 점수·심각도 표·상위 이슈가 Actions 요약에 표시.
- Code Scanning: SARIF 2.1.0 업로드 → Security 탭 + PR 인라인 주석.
- 내부적으로
a11y-ai ci --static --sarif …를 실행(= 이 명령을 직접 CI에 넣어도 동일).
