Equall

API

Programmatic API for embedding the Equall scanner in another Node tool — runScan and the public TypeScript types.

The equall-cli package exposes a small ESM API so you can embed the scanner inside a custom CI script, a pre-commit runner, or a dashboard backend. Everything the CLI does is reachable through runScan().

Looking for the equall binary? Flag-by-flag usage lives on Scanning, suppression comments on Ignore system, and setup on Install. This page is only about the programmatic surface.

Module format

equall-cli is shipped as an ESM-only package with a single root export plus .d.ts declarations. The minimum supported runtime is Node ≥ 20.

package.json (consumer)
{
  "type": "module",
  "dependencies": { "equall-cli": "^0.1.10" }
}

If you must call it from a CommonJS file, use a dynamic await import('equall-cli').

Example

scan.mjs
import { runScan } from 'equall-cli'

const result = await runScan({
  path: './my-project',
  level: 'AA',
})

console.log(`Score: ${result.score} (${result.conformance_level})`)

for (const issue of result.issues) {
  if (issue.ignored) continue
  console.log(
    `${issue.file_path}:${issue.line ?? '?'}  ${issue.scanner_rule_id}  — ${issue.message}`,
  )
}

The full shape of the returned ScanResult document is documented on Output format.

Public exports

runScan(options)

Discovers files, runs every available scanner in parallel, deduplicates findings — including merging equivalent findings from different engines into a single issue (see the scanners field on Output format) — applies equall-ignore comments, and returns a fully scored ScanResult.

function runScan(options?: RunScanOptions): Promise<ScanResult>

interface RunScanOptions {
  path?: string                  // Project root. Default: process.cwd()
  level?: 'A' | 'AA' | 'AAA'     // WCAG target. Default: 'AA'
  standard?: 'wcag22' | 'wcag21' // WCAG version view. Default: 'wcag22'
  include?: string[]             // Glob patterns to include
  exclude?: string[]             // Glob patterns to exclude
  disableScanners?: string[]     // Scanner names to skip, e.g. ['readability']
  files?: FileInput[]            // In-memory input — scan these buffers instead of disk
}

interface FileInput {
  path: string                   // Relative path; the extension drives file-type detection
  content: string                // File contents
}

The path, level, include, and exclude options mirror the CLI flags one-to-one — see Scanning for their semantics. standard selects the conformance viewwcag22 (default) or wcag21 (the public-sector legal bar, WAD/EN 301 549) — and never changes the returned score. Pass files to scan source held in memory instead of discovering files on disk — useful for editor integrations and pre-commit tools. When files is set, on-disk discovery is bypassed.

runScan never throws on individual scanner failures: a crashed scanner is logged to console.warn, its results are dropped, and the run continues with the others. It can throw if the root path is unreadable, so wrap the call in try/catch if you need to surface that as a domain error.

scanBuffer(content, filename, options?)

Scans a single file held in memory and returns a full ScanResult — no disk access. A thin wrapper over runScan({ files: [{ path: filename, content }] }). The filename extension drives file-type detection, so pass a real one (e.g. Button.tsx).

function scanBuffer(
  content: string,
  filename: string,
  options?: Omit<RunScanOptions, 'files' | 'path'>,
): Promise<ScanResult>

runDiffScan(options)

Scans the change between two Git refs and reports only the issues the change introduced — the "only-new" view. New is told from pre-existing by a content fingerprint (not line numbers), so a reformat-only change yields zero false "new".

function runDiffScan(options: DiffScanOptions): Promise<DiffScanResult>

interface DiffScanOptions {
  base: string                   // Git ref to diff against (validated; never shell-interpolated)
  head?: string                  // Git ref for the new state. Default: 'HEAD'
  cwd?: string                   // Repo root. Default: process.cwd()
  level?: 'A' | 'AA' | 'AAA'     // WCAG target. Default: 'AA'
}

interface DiffScanResult {
  base: string                   // Resolved base commit SHA
  head: string                   // Resolved head commit SHA
  merge_base: string             // merge-base(base, head)
  new_issues: EquallIssue[]      // Introduced by the change
  legacy_issues: EquallIssue[]   // Present in changed files but already at base
  not_testable: string[]         // Changed files outside the scannable set
  summary: { files_changed: number; files_scanned: number; new_count: number /* … */ }
}

scanBuffer and runDiffScan are API-only — there is no equall scan flag for diff-aware scanning yet.

Public types

All types are re-exported from the package root and ship with .d.ts declarations:

import type {
  RunScanOptions,
  FileInput,
  DiffScanOptions,
  DiffScanResult,
  ScanResult,
  ScanSummary,
  ScannerInfo,
  EquallIssue,
  CoverageReport,
  CriterionCoverage,
  CoverageStatus,
  ReclassifiedRule,
  CriterionConformance,
  ConformanceVerdict,
  ConfidenceFlag,
  ConformanceLevel,
  Severity,
  WcagLevel,
  WcagStandard,
  PourPrinciple,
  ScannerAdapter,
  ScanContext,
  ScanOptions,
} from 'equall-cli'

The runtime shape of ScanResult, EquallIssue, CriterionConformance, and the union types (ConformanceLevel, ConformanceVerdict, Severity, WcagLevel, WcagStandard, PourPrinciple) is documented on Output format — that page is the canonical contract for both runScan() consumers and --json integrators.

ScannerAdapter, ScanContext, and ScanOptions are the lower-level interfaces the built-in scanners implement. They're exported for tooling that wants to implement its own ScannerAdapter, but they aren't required for typical runScan usage.

Stability

Equall is pre-1.0 (current version 0.1.10). The shape of ScanResult and the signature of runScan are treated as a public contract: fields are added compatibly between minor versions, and any breaking change will be called out explicitly in the release notes. Known intentional limitations are tracked on Known issues.

On this page