# pour

Adopt this skill: https://proskills.md/skills/other/pourdev-pour-cli-plugin-skills-pour

Page: https://proskills.md/skills/other/pourdev-pour-cli-plugin-skills-pour
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: plugin/skills/pour/SKILL.md
size: 6667
sha: e72ec1cbb6822d8436567c20935b1fefe5aa2f57
upstream: https://github.com/pourdev/pour-cli/blob/main/plugin/skills/pour/SKILL.md

````text
---
name: pour
description: Check web pages and UI code for WCAG 2.2 accessibility failures with the pour engine, and fix what it finds. Use when creating or changing HTML, components, templates or styles that render a page; when asked about accessibility, a11y, WCAG, screen readers, keyboard access, focus order, colour contrast or alt text; and before reporting UI work as finished.
license: MIT
compatibility: Needs the pour command (npm install -g pour-cli, or npx -y pour-cli) and an installed Chrome or Chromium for page audits. Uses the pour MCP server (pour mcp) when the client has it.
---

# Checking accessibility with pour

pour checks web pages against WCAG 2.2 Level A and AA with its own engine.
Its results come in two kinds, and they must be kept apart:

- **Violations** are failures the engine can demonstrate from the page. Fix them.
- **Needs review** means the engine abstained: the answer depends on
  something it cannot know, such as whether an image is decorative or
  whether captions match the audio. Do not count these as failures, and do
  not change code to make them go away by guessing. List them for the user
  as things a person needs to look at.

A clean result means pour found no failure it can detect. Automated checks
cover only part of WCAG, so never tell the user that a page is accessible,
compliant or conformant because a pour run came back clean.

## Tools

When the MCP tools from `pour mcp` are available, use them:

| Tool | Use |
| --- | --- |
| `pour_audit` | Audit a page. Takes `url` (a running dev server is fine) or `path` (a file on disk), plus `viewport`, `scroll`, `bestPractices`, `exclude`, `detail` and `maxNodes`. A template or component `path` is read as source. |
| `pour_focus_order` | The order the Tab key visits the page's controls, each with its accessible name, and the controls a `tabindex="-1"` has put out of reach. |
| `pour_screenshot` | A PNG of the page as it is, or through a simulation such as `deuteranopia`, `lowAcuity`, `focusOrder` or `landmarkMap`. |

Otherwise use the command line. If `pour` is not installed, `npx -y pour-cli`
runs the same command.

```sh
pour check src/components/Nav.tsx --format json   # source files, no browser
pour http://localhost:5173/ --format json          # the rendered page
pour dist/index.html --format json                 # a built page on disk
pour http://localhost:5173/ --viewport 390x844     # a phone-width layout
pour http://localhost:5173/ --filter deuteranopia --shot cb.png
pour --filter list                                 # every simulation name
```

Exit codes: 0 nothing found, 1 findings, 2 an error (an address that does not
load, a verification challenge, a sign-in page). Exit code 1 is the normal
result of finding something, not a broken command.

## Workflow

1. **Source first.** After editing markup, run `pour check` on the changed
   files (HTML, JSX, TSX, Vue, Svelte, Liquid, Nunjucks). Findings carry the
   file, line and column. Values that come from code are counted under
   `abstained`, not judged.
2. **Then the rendered page.** Colour contrast, focus order, computed names
   and anything built by script exist only in a browser. Start the project's
   dev server if it is not running, and audit each page the change touches.
3. **Note the state you audited.** Results depend on the viewport width,
   whether the page was scrolled (`scroll`, or `--scroll`, loads lazy
   content) and what was open. Audit at the default width, and at 390x844 as
   well when the change affects a responsive layout.
4. **Fix in the source**, guided by the Fix line the engine gives for each
   element. Make the smallest change that removes the failure.
5. **Audit again** in the same state and compare. Repeat until the
   violations in scope are gone, or explain why one remains.
6. **Check the keyboard path** with `pour_focus_order` after changing
   anything interactive: every control reachable, named, and visited in an
   order that follows the layout.

## Fixing without hiding

- Never make a finding disappear without fixing it. Do not use `exclude`,
  `aria-hidden="true"`, `role="presentation"`, `tabindex="-1"` or
  `display: none` on content or controls that people need.
- Prefer native HTML to ARIA: `<button>` over a `div` with `role="button"`,
  a `<label>` over `aria-label`. Add ARIA only when native HTML cannot
  express the thing.
- A control's accessible name must contain its visible text (WCAG 2.5.3).
  Do not give a button an `aria-label` that differs from the words on it.
- Alt text says what an image is for in its context. Use `alt=""` only for
  images that add nothing. When you cannot tell what an image shows, ask
  the user rather than invent a description.
- For contrast, change the colour where it is defined (a design token or a
  custom property), then audit again. Quote the ratio pour reports rather
  than estimating one.
- When a fix needs a decision only the user can make (wording, a brand
  colour, whether content is decorative), ask.

## Reading results

- `pour <page> --format json` gives the engine's full results. `violations`
  and `incomplete` (needs review) hold one entry per rule, with `id`,
  `impact`, `tags`, `help`, `helpUrl` and `nodes`. Each node has `target` (a
  CSS path), `html` and `failureSummary`, where the text after `Fix:` is
  the fix.
- `pour_audit` returns a compact form: `totals`, then `violations` and
  `needsReview`, each rule with its `wcag` criteria and up to `maxNodes`
  elements, each with `target`, `html`, `message` and `fix`. Pass
  `detail: "summary"` for the counts alone.
- `pour check --format json` gives `files[].findings[]`, each with `kind`
  (`violation` or `review`), `rule`, `impact`, `sc`, `message`, `fix`,
  `file`, `line` and `col`.

## Reporting to the user

Say what was audited (the address or the files), the viewport, and whether
the page was scrolled. Give the violations before and after, by rule, with
what changed. List the needs-review items separately, as things for a
person to check. Close with what pour cannot check, such as whether alt
text is accurate or whether the page makes sense read aloud, not with a
claim of compliance.

## When pour cannot run

- **No browser:** page audits need Chrome or Chromium; `--browser <path>`
  names one. `pour check` needs no browser.
- **A verification challenge or a sign-in page:** pour will not audit it and
  exits with 2. Tell the user. `--login` opens a window for them to sign in;
  it needs a person, so never use it unattended.
- **A dev server with a self-signed certificate:** `--insecure`.
- **A slow page:** `--wait <ms>` adds settle time after load.
````

## File: README.md
upstream: https://github.com/pourdev/pour-cli/blob/main/README.md

````text
# pour-cli

Audit any URL against WCAG 2.2 from your terminal, powered by the
[pour engine](https://github.com/pourdev/pour-engine): a clean-room WCAG
engine written from the W3C specifications, the same engine behind
[pour.dev](https://pour.dev).

```sh
npm install -g pour-cli
pour example.com
```

The page is loaded in headless Chrome, the engine runs against the live DOM,
and the findings land on stdout: rule, severity, WCAG success criterion, the
exact failing elements as CSS paths, and what to fix. Findings the engine
cannot judge conclusively are reported as "needs review" rather than guessed
at, and the exit code makes it a CI gate out of the box.

## Requirements

Node 18+, and an installed Chrome (or Chromium, or Edge). The CLI drives the
browser you already have via puppeteer-core, so installing it never
downloads one. Point `--browser` (or `PUPPETEER_EXECUTABLE_PATH`) at a
binary to use something else.

## Usage

```
pour <url | file.html> [options]        one page
pour report <url | list.csv> [options]  a site, or a list of domains (see below)
pour check <files, folders or globs>    files on disk, no browser (see below)
pour mcp                                browser tools for an AI agent (see below)
pour skill [install]                    teach a coding agent to use pour (see below)

One page
  --viewport WxH       viewport (default 1440x900); a bare width implies x900
  --scroll             scroll through the page before auditing (lazy content)
  --wait <ms>          extra settle delay after load (default 0)
  --timeout <ms>       navigation timeout (default 30000)
  --exclude <sel>      CSS selector excluded from every rule
  --bp                 include best-practice rules alongside WCAG A+AA
  --root <dir>         with a local .html file: the folder served as the site
                       root, for assets addressed from there (/css/site.css);
                       default the file's own folder

Output
  --format <what>      terminal (default) | json | markdown (a pull-request
                       comment); pour check adds github (annotations on the
                       changed lines) and sarif (GitHub code scanning)
  --level <detail>     quiet (the totals line) | rules (one line per rule) |
                       max (default: everything)
  --max-nodes <n>      element details shown per rule (default 5, 0 = all)
  --json               the full engine results as JSON
  --fail-on <what>     violations (default) | incomplete | none

Screenshots
  --filter <name>      screenshot the page through a vision/sensory simulation
                       instead of auditing (--filter list shows them all)
  --shot [file]        save a PNG (default name from the URL and filter);
                       no audit runs
  --full               the full page height, not just the viewport

Signed-in sites (pour and pour report)
  --login              a browser window opens at the address; sign in there,
                       press Enter here, and the run continues signed in.
                       The session lives in memory for this run only:
                       nothing is written to disk
  --basic user:pass    HTTP authentication (a staging site behind a wall),
                       the one thing a sign-in window cannot hand over

Browser
  --browser <path>     Chrome/Chromium binary to drive
  --headful            run the browser with a visible window
  --insecure           ignore TLS certificate errors
```

Exit codes: 0 clean, 1 findings (per `--fail-on`), 2 error.

A scheme-less URL is tried over https first and falls back to http when the
TLS handshake fails, the same way a browser address bar behaves.

## Vision simulations

`--filter` renders the page as someone with a particular vision or sensory
condition experiences it and saves the result as a PNG:

```sh
pour example.com --filter deuteranopia
pour example.com --filter glaucoma --shot tunnel.png
pour --filter list
```

Color-vision filters use the Brettel/Vienot/Mollon and Machado matrices (via
[DaltonLens](https://daltonlens.org/cvd-simulation-svg-filters/)), the same
simulations the pour extension ships. Filters and audits are exclusive modes:
some simulations restyle the page, so auditing through one would audit the
simulation rather than the site.

## The numbers depend on the page state

Responsive pages serve different content per breakpoint, and the engine
measures what is actually rendered, so the viewport is part of the result:
the report header echoes it, and comparing two runs only makes sense at the
same width. `--scroll` walks the page first so lazy-loaded content is in
the DOM; that changes the numbers too, by design.

## A page on disk

A target that names an `.html` file is audited as the page it is, in the
browser, with every rule that needs layout and paint:

```sh
pour index.html
pour build/about.html --root build   # assets addressed from the site root
```

The file is served from a loopback port for the length of the audit, so its
relative and root-relative assets load the way they will in production.
Opening it as a `file://` URL instead would leave a stylesheet at
`/css/site.css` unfetched, and the audit would report an unstyled page as if
it were the real one, usually as a clean result. `--root` says which folder
is the site root when the page addresses its assets from there rather than
from its own folder.

`file://` URLs still work if you type one, and carry that caveat with them.

## Checking files

`pour check` reads HTML, JSX, TSX, Vue, Svelte, Angular, Liquid and Nunjucks
files and runs the engine's markup rules over them with no browser, the same
lane the pour extension for VS Code runs as you type. Every finding comes
with its file, line and column.

```sh
pour check src/                      # every file the lane can read, under src
pour check "src/**/*.html" --level rules
pour check src --format sarif > pour.sarif
```

Values that come from code (`alt={name}`), script-built markup and anything
a template tag leaves unknowable are left unjudged and counted rather than
guessed. Colour contrast, target size, focus and motion need the page in a
browser, so those stay with `pour <url>`. `--bp`, `--fail-on`, `--level`,
`--max-nodes` and `--format` apply; `--no-css` skips reading the local
stylesheets a page links.

## Reports over many pages

`pour report` crawls a site breadth first from the address given (or audits
the home page of every domain in a list file), with a live progress screen
in the browser and one standalone HTML report at the end. Ctrl+C stops
cleanly; the same command resumes.

```sh
pour report yoursite.com --max 200 --report reports/yoursite.html
pour report https://yoursite.com/help        # /help and the pages under it, nothing above
pour report https://help.yoursite.com/       # help.yoursite.com and below, not www.yoursite.com
```

An address with a path keeps the crawl under that path; `--whole-site`
follows links above it too. An address on a subdomain keeps the crawl on
that subdomain and its own; a start on the main host covers the whole site
and its subdomains, and `--same-host` narrows it to the one host.

```
  --max <n>            pages (default 100)
  --depth <n>          links deep from the start
  --same-host          this host only, not its subdomains
  --query              keep query strings: /list?page=2 is its own page
                       (by default a page is its path, and ?page=2 is not)
  --whole-site         follow links above the path given too
  --workers <n>        parallel pages (4 for a site, 8 for a list)
  --pause <ms>         gap between pages per worker
  --load <ms>          time to let a page load (default 10000)
  --timeout <ms>       for the whole page (default 20000)
  --viewport WxH       as above
  --report <file.html> where the finished report goes
  --out <dir>          where the run itself lives (default pour-reports)
  --port <n>           the progress screen's port
  --no-open         
````
