npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

screen-reader-cli

v0.1.0

Published

Screen reader testing CLI — scan pages for accessibility violations with axe-core + Virtual Screen Reader, drive real VoiceOver/NVDA, generate regression tests

Readme

screen-reader-cli

CI License: MIT

A command-line screen reader testing tool. Scan any page for accessibility violations, generate regression tests, or drive a real screen reader (VoiceOver/NVDA) programmatically.

New here, or not a developer? Start with the friendly guide: elizabeth1979.github.io/screen-reader-cli — what the tool does, who it's for, and how to run your first check in three steps.

Powered by Virtual Screen Reader, Guidepup, axe-core, and Playwright.

What it does

  • Scans pages for screen-reader-specific violations (heading skips, missing alt text, missing accessible names, hidden focusable elements, missing landmarks, missing form labels) + axe-core rules
  • Drives real screen readers — VoiceOver on Mac, NVDA on Windows — to hear what gets announced
  • Generates regression tests — Playwright Test or Vitest files from scan results
  • Visual reports — HTML reports with issue tables, heading structure, DOM reading order, and screenshots
  • Navigates by element, heading, landmark, link, or form (virtual mode)
  • Works offline — everything runs locally, no CDN dependencies

Platform support

| Command | macOS | Windows | Linux | | ------------------------------------------------ | ----- | ------- | ----- | | scan, audit, page, nav, speak, repl | ✅ | ✅ | ✅ | | screenshot, --visual reports | ✅ | ✅ | ✅ | | live (real VoiceOver/NVDA) | ✅ | ✅ | ❌ |

Everything except live uses a virtual screen reader in headless Chromium and runs anywhere Node 20+ and Playwright do — including CI. live drives the OS screen reader, which only exists on macOS (VoiceOver) and Windows (NVDA).

Install

# Requires Node.js 20+
git clone https://github.com/Elizabeth1979/screen-reader-cli.git
cd screen-reader-cli
npm install
npx playwright install chromium
npm link

Once the package is published to npm this becomes npm install -g screen-reader-cli (or one-off: npx screen-reader-cli scan <url>), followed by npx playwright install chromium.

Live mode setup (optional — for real screen reader testing)

To use the live command with a real screen reader, run the one-time setup:

npx @guidepup/setup

This grants the OS permissions needed for screen reader automation:

  • macOS: Enables VoiceOver's AppleScript API and adds your terminal to Accessibility permissions
  • Windows: Configures NVDA for programmatic control

You only need to do this once per machine. The scan command (virtual mode) works without this step.

Quick start

# Scan a page for accessibility issues (the main command)
screenreader scan https://example.com

# JSON output (for CI pipelines)
screenreader scan https://example.com --json

# Visual HTML report (opens in browser)
screenreader scan https://example.com --visual

# Generate a Playwright regression test file
screenreader scan https://example.com --test

# Generate Vitest stubs instead
screenreader scan https://example.com --test --framework vitest

# Drive the real screen reader on a page
screenreader live read https://example.com

# Interactive REPL
screenreader

Commands

scan — The main command

Scans a page for screen-reader-specific violations using custom DOM checks + axe-core, then outputs a merged, deduplicated report.

screenreader scan <url>                                    # Text report in terminal
screenreader scan <url> --json                             # JSON (for CI)
screenreader scan <url> --fail-on critical                 # Exit 1 if critical violations (CI gate)
screenreader scan <url> --visual                           # HTML report opens in browser
screenreader scan <url> --test                             # Generate Playwright test file
screenreader scan <url> --test --framework vitest          # Generate Vitest stubs
screenreader scan <url> --test --output my-tests.test.js   # Custom output path
screenreader scan <url> --ai                               # AI analysis of results
screenreader scan <url> --ai --model sonnet                # Use Claude Sonnet
screenreader scan <url> --ai --model gpt-4o                # Use GPT-4o
screenreader scan <url> --ai --provider ollama             # Use local model (free)

AI analysis (--ai)

Get plain-language explanations, prioritized fix suggestions with code examples, and a screen reader experience score. Supports multiple providers:

| Provider | Flag | Models | API Key | | --------- | ---------------------- | -------------------------------------------- | -------------------------------------- | | Gemini | --provider gemini | flash (default), pro | GEMINI_API_KEY (free tier available) | | Anthropic | --provider anthropic | haiku, sonnet (default), opus | ANTHROPIC_API_KEY | | OpenAI | --provider openai | gpt-4o-mini (default), gpt-4o, o3-mini | OPENAI_API_KEY | | Ollama | --provider ollama | Any installed model | None (free, local) |

Auto-detects provider from model name: --model sonnet → Anthropic, --model gpt-4o → OpenAI, --model flash → Gemini. Unknown models default to Ollama. If no provider or model is specified, picks the first available API key (priority: Gemini → Anthropic → OpenAI → Ollama).

What it checks:

  • Heading hierarchy (no skips, e.g. h1 → h3)
  • Missing alt text on images
  • Missing accessible names on buttons and links (including icon-only buttons/links)
  • Missing form labels
  • Missing main landmark
  • Focusable elements inside aria-hidden="true"
  • All axe-core WCAG 2 AA rules

Works with URLs and local files:

screenreader scan test/fixtures/violations.html

CI usage (--fail-on)

--fail-on <severity> makes scan exit with code 1 when violations at or above that severity are found, so it can gate a pipeline:

  • --fail-on critical — fail only on critical violations
  • --fail-on moderate — fail on critical or moderate
  • --fail-on minor — fail on any violation

GitHub Actions example:

jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g screen-reader-cli
      - run: npx playwright install --with-deps chromium
      - name: Accessibility gate
        run: screenreader scan https://staging.example.com --fail-on critical

Combine with --json to also archive the full results as a build artifact.

dashboard — Point-and-click scanning

Prefer buttons over commands? Start the dashboard once and run every scan from your browser:

sr                                  # shortcut — opens the dashboard
screenreader dashboard              # same thing, full command
screenreader dashboard --port 5000  # pick another port

sr is a short alias for the whole CLI: on its own it opens the dashboard, and sr scan <url> works exactly like screenreader scan <url>.

Type a page address, press Scan, and the results appear with a link to the full visual report. A history of past scans is kept while the dashboard is running. Everything stays on your machine — the dashboard only listens on localhost.

live — Real screen reader testing

Drives VoiceOver (macOS) or NVDA (Windows) on a real page. Auto-detects your OS, or override with --reader.

# Read the full page — logs every announcement
screenreader live read <url>
screenreader live read <url> --json
screenreader live read <url> --steps 50        # Limit traversal steps

# Test mode — traverses and detects issues (empty announcements, focus traps)
screenreader live test <url>
screenreader live test <url> --json

# Interactive — opens browser + screen reader, keeps it running
screenreader live open <url>

# Force a specific reader
screenreader live read <url> --reader nvda
screenreader live read <url> --reader voiceover

Requires one-time setup: npx @guidepup/setup (see Install section above).

page — Page navigation

screenreader page open <url>    # Open a URL or local HTML file
screenreader page info          # Show current page title and URL

nav — Navigate elements

screenreader nav next           # Move to next element
screenreader nav previous       # Move to previous element
screenreader nav heading        # Jump to next heading
screenreader nav landmark       # Jump to next landmark
screenreader nav link           # Jump to next link
screenreader nav form           # Jump to next form

All nav commands accept --url <url> to open a page first and --json for structured output.

speak — Query spoken phrases

screenreader speak last                   # Last spoken phrase
screenreader speak log --steps 10         # Navigate 10 steps, show log
screenreader speak find "Sign up" --url https://example.com

audit — Full page traversal

screenreader audit <url>                  # Traverse entire page
screenreader audit <url> --summary        # Include heading/landmark summary
screenreader audit <url> --json           # JSON output
screenreader audit <url> --max 1000       # Increase element limit (default: 500)

screenshot — Capture elements or pages

screenreader screenshot --url <url> --full --output page.png
screenreader screenshot --url <url> --navigate 5 --output element.png

repl — Interactive mode

screenreader        # Enters REPL (default when no command given)
screenreader repl   # Same thing, explicit

In the REPL, navigation state persists across commands. You can also start a real screen reader session:

screenreader> page open https://example.com
Opened: Example Domain (https://example.com/)
screenreader> nav heading
heading, Example Domain, level 1
screenreader> nav next
More information...
screenreader> screenshot element.png
Screenshot saved: element.png

screenreader> live start
VoiceOver started. Use "live next", "live previous", "live log", etc.
screenreader> live next
Example Domain, heading level 1
screenreader> live log
1. Example Domain, heading level 1
screenreader> live stop
VoiceOver stopped.
screenreader> quit

JSON output

All commands support --json for machine-readable output:

screenreader audit https://example.com --summary --json
{
  "phrases": ["document", "heading, Example Domain, level 1", "..."],
  "total": 12,
  "headings": ["heading, Example Domain, level 1"],
  "landmarks": ["main"],
  "links": ["link, More information..."],
  "summary": {
    "totalElements": 12,
    "headingCount": 1,
    "landmarkCount": 1,
    "linkCount": 1
  }
}

How it works

Virtual mode (scan, page, nav, audit, etc.)

  1. Playwright launches a headless Chromium browser
  2. Virtual Screen Reader is injected into the page context for DOM traversal
  3. Custom violation checks run against the DOM (heading hierarchy, accessible names, etc.)
  4. axe-core is injected for comprehensive WCAG 2 AA rule coverage
  5. Results are merged and deduplicated

The Virtual Screen Reader implements the same W3C accessibility specifications that real screen readers follow — ACCNAME, CORE-AAM, HTML-AAM, WAI-ARIA 1.2, and more.

Live mode (live)

  1. Playwright launches a visible browser (screen readers need a real window)
  2. Guidepup starts VoiceOver (macOS) or NVDA (Windows)
  3. The screen reader traverses the page — you hear what it actually announces
  4. Results are captured via guidepup's API (lastSpokenPhrase(), spokenPhraseLog())

Security notes

  • --chrome-profile reuses your real Chrome profile — cookies and logged-in sessions included. Only use it against URLs you trust (your own staging environments); scanning an untrusted site with it exposes your authenticated sessions to that site.
  • Virtual mode disables the target page's Content-Security-Policy (bypassCSP) so the Virtual Screen Reader bundle can be injected. This is required for the tool to work on CSP-strict sites, but it means the page runs with weaker protections during the scan — again, point it at pages you trust.
  • AI analysis (--ai) sends scan results (violation messages, selectors, page title/URL) to the provider you select. Use --provider ollama to keep everything local.

Architecture

flowchart LR
    CLI["bin/cli.js\n(commander)"]

    CLI --> SCAN["scan"]
    CLI --> VIRT["page · nav · speak\naudit · repl"]
    CLI --> LIVE["live"]

    SCAN --> PW["Playwright\nheadless Chromium"]
    PW --> AXE["axe-core\nWCAG 2 AA rules"]
    PW --> STRUCT["headings · landmarks\nDOM reading order"]
    AXE --> MERGE["merge + dedupe\n(scanner.js)"]
    STRUCT --> MERGE
    MERGE --> TEXT["text report"]
    MERGE --> JSON["--json"]
    MERGE --> HTML["--visual HTML report"]
    MERGE --> TESTS["--test generated tests"]
    MERGE --> AI["--ai analysis\nGemini · Claude · GPT · Ollama"]

    VIRT --> BRIDGE["bridge.js\nVirtual Screen Reader"]
    BRIDGE --> PW2["Playwright\nheadless Chromium"]

    LIVE --> GP["Guidepup"]
    GP --> VO["VoiceOver (macOS)"]
    GP --> NVDA["NVDA (Windows)"]

Three engines, one CLI:

  1. Scan — Playwright loads the page, axe-core finds violations, custom code extracts structure, and everything merges into one report (text, JSON, HTML, generated tests, or AI analysis).
  2. Virtual — the Virtual Screen Reader is injected into the page so nav/audit/speak can traverse it the way a screen reader would.
  3. Live — Guidepup drives the real OS screen reader so you hear actual announcements.

Roadmap

Recently shipped:

  • [x] --fail-on <severity> exit-code gate for CI pipelines
  • [x] Cross-platform support for --visual reports (macOS/Windows/Linux)
  • [x] Real assertions in --test generated files
  • [x] Local dashboard (screenreader dashboard) — scan from the browser, no terminal after launch

Planned (roughly in order):

  • [ ] Element screenshots — capture an image of each failing element and embed it in the visual report
  • [ ] Flow capture — screenshot each step of a multi-page/multi-step flow as it's scanned
  • [ ] Violation context — include the DOM path and accessibility-tree node for each violation in reports (today: selector + HTML snippet)
  • [ ] Richer AI fix suggestions — per-violation code-level fixes with the element's full context (today: --ai gives prioritized fixes + a score)
  • [ ] Asset capture — download page images during a scan for audit evidence
  • [ ] Multi-page crawling — scan a whole site from a sitemap or crawl
  • [ ] Baseline & diff — fail CI only on new violations
  • [ ] GitHub Action — a published action wrapping scan --fail-on
  • [ ] Screen reader transcript diff — compare what's announced before vs. after a change

Suggestions welcome — open an issue.

Use cases

  • Accessibility testing — audit any site's screen reader experience from CI/CD
  • AI agents — give agents structured, semantic understanding of web pages
  • Developer workflows — quickly check heading hierarchy, landmark structure, ARIA usage
  • Automated QA — validate accessibility in build pipelines with JSON output

Claude Code companion skill

If you use Claude Code, this repo ships a companion skill + slash command that lets Claude run audits on demand:

/sr-audit https://example.com

Claude runs scan + audit paired, saves text + JSON to disk, and surfaces the top issues in chat. See skills/claude-code/README.md for install instructions and what it does.

Testing

# Run all local tests (headless Chromium, no network needed)
npm test

# E2E tests (requires network — scans https://example.com)
npm run test:e2e

# Individual suites
node --test test/scan.test.js       # Scan command
node --test test/live.test.js       # Live command
node --test test/commands.test.js   # Virtual mode commands
node --test test/bridge.test.js     # VSR bridge
node --test test/audit.test.js      # Audit command
node --test test/daemon.test.js     # Browser lifecycle

Contributions welcome — see CONTRIBUTING.md.

Built with

License

MIT