Getting started
This guide scans a first site without a project, then installs cora in a project, sets the project up, and scans it.
Requirements
Section titled “Requirements”- Linux, macOS or Windows.
- Node.js 22.18.0 or later. On an older release,
corastops:node.unsupported-versionsays why, and how to install a later one. - Google Chrome, which
corascans with. Without it, runnpx playwright install chrome. - Playwright 1.51 or later.
@vispero/coradeclaresplaywright-coreas a peer dependency, which npm and pnpm install with it. With Yarn, addplaywright-coreyourself. A project that already uses@playwright/testorplaywrightscans with that copy and its browsers. - A CORA account, in an organization with a CORA plan. See Accounts.
Scan a site without a project
Section titled “Scan a site without a project”To try CORA on any site before you add it to a project, run it with npx or pnpm dlx. They install @vispero/cora, and the Playwright it scans with, in their own cache, so nothing is installed in a project. Sign in once, then scan:
npx @vispero/cora auth loginnpx @vispero/cora scan https://example.com/pnpm dlx @vispero/cora auth loginpnpm dlx @vispero/cora scan https://example.com/cora keeps the run’s results in .cora/ in the folder you run it in, so give each site a folder of its own. Scanning without a project shows what else works there, and What a project adds what a project gives you beyond it.
Scan a first page
Section titled “Scan a first page”If you use a screen reader, turn on CORA’s screen-reader setting before you run cora init, so its question is asked line by line and progress prints as new lines.
-
Add
@vispero/corato the project as a devDependency, then check thatcoraruns. It prints the installed version.Terminal window npm install -D @vispero/coranpx cora --versionTerminal window pnpm add -D @vispero/corapnpm cora --versionTerminal window yarn add -D @vispero/corayarn cora --versionA copy of
corainstalled globally hands over to the project’s own copy inside a project, so every command runs the project’s version. -
Set the project up with
cora init:Terminal window npx cora initTerminal window pnpm cora initTerminal window yarn cora initIt shows each change as a diff, and asks once before it writes:
- a starter config,
cora.config.ts, which crawls the app’s pages from/and, where yourdevscript, or yourstartscript where you have nodev, runs your app’s dev server, starts it, as The starter config describes; - in a Vite project, CORA’s Vite plugin in the Vite config, in a Nuxt or Astro project in
vite.pluginsof itsnuxt.configorastro.config, and in a webpack, Rspack, Rsbuild, Rollup or Rolldown project, that bundler’s plugin in its config (webpack, Rspack and Rsbuild, Rollup and Rolldown), so findings name the line to fix (a project that lists one of these without a config of it there is told it was not set up, and where the plugin goes); - in an Angular CLI workspace, Angular’s own template source locations, turned on for its development builds;
- where the project uses Claude Code, CORA’s plugin in the project’s
.claude/settings.json; - where it uses Codex, CORA’s fixer agent in the project’s
.codex/.
It then prints the commands that install the plugin in each coding agent, as Installing the plugin describes.
Its CLI reference entry says how it finds your coding agents, how it formats what it writes, and what it does with a file it cannot edit.
- a starter config,
-
Sign in to your CORA account. You do this once on each machine:
Terminal window npx cora auth loginTerminal window pnpm cora auth loginTerminal window yarn cora auth logincoraprints a page and a code, and opens the page in your browser where it can. Sign in there and approve the login. CI signs in with a CI token instead, as Accounts describes. -
Scan your app. Where your config sets
server,corastarts your dev server, and stops it once the scan ends; otherwise, start your app first:Terminal window npx cora scanTerminal window pnpm cora scanTerminal window yarn cora scancorascans the targets in your config. It prints a summary on stderr, and writes the full results to.cora/runs/in the project:Gate failed: 2 new issues at or above minorTargets: 6Issues: 2 (2 new)Duration: 1.2 sResults: .cora/runs/20261026T001255241Z-rzqqlsix.jsonTo accept them, run:npx cora baseline update .cora/runs/20261026T001255241Z-rzqqlsix.jsonGate failed: 2 new issues at or above minorTargets: 6Issues: 2 (2 new)Duration: 1.2 sResults: .cora/runs/20261026T001255241Z-rzqqlsix.jsonTo accept them, run:npx cora baseline update .cora/runs/20261026T001255241Z-rzqqlsix.jsonGate failed: 2 new issues at or above minorTargets: 6Issues: 2 (2 new)Duration: 1.2 sResults: .cora/runs/20261026T001255241Z-rzqqlsix.jsonTo accept them, run:yarn cora baseline update .cora/runs/20261026T001255241Z-rzqqlsix.json
The first scan of a project reports every violation as new. When one is at or above policy.failOn, the gate fails, and cora scan exits with code 1, as above. The CLI reference lists each exit code. Baselines and the gate shows how to accept what is there today.
The starter config
Section titled “The starter config”In a Vite app whose dev script runs vite, cora init writes this, with comments that explain each key:
import { defineConfig } from '@vispero/cora/config';
export default defineConfig({ baseUrl: 'http://localhost:5173', server: { command: 'npm run dev', url: 'http://localhost:5173', }, targets: [ { crawl: '/', maxPages: 25, maxDepth: 2, exclude: ['(?<!/)/(?:[Ll]og|[Ss]ign)[-_]?(?:[Oo]ut|[Oo]ff)(?:[/?#.]|$)'], }, ],});baseUrlis your dev server’s address wherecora initsetsserver. Where it doesn’t, it’s a placeholder,http://localhost:5173: set it to your app’s address.serverruns yourdevscript, or yourstartscript where you have nodev, with your package manager, where it starts a dev servercora initrecognizes. Its port is the one the script sets, or else the one your dev server’s own config sets, or else the tool’s default.cora initprints the command and URL it wrote: where a variable set outside the script moves the server, such asPORTin a CI job, set that address. The app’s server says how it works.- The crawl starts at your home page and follows the links on its host, up to 25 pages and 2 links away. Raise
maxPagesandmaxDepthto scan more of the app. excludekeeps the crawl off common sign-out links, such as/logout,/sign-outand/logout.php. Its patterns are case-sensitive and tested against each link’s absolute URL. Add your app’s own sign-out link where it differs, such as/auth/end-session, or the crawl may sign itself out.
Where cora init can’t be sure where your dev server listens, such as for a script that takes its port from $PORT, or a dev server whose own config computes its port or serves HTTPS, it writes no server and says why: start your app before you scan, or add server yourself. For an app cora init doesn’t start, such as a staging site or a backend’s, give its address with --base-url.
To scan a dev server you keep running, turn on server.reuseExistingServer in your user config, as The app’s server says.
Coding agents
Section titled “Coding agents”cora init adds CORA’s plugin to the project’s Claude Code settings, and prints the commands that install it in each coding agent. The plugin installs from CORA’s plugin marketplace on GitHub: Installing the plugin says how to reach it.
Next steps
Section titled “Next steps”- Accept what is there today: Baselines and the gate
- Scan any site from any folder: Scanning without a project
- Choose what to scan: Scanning with cora scan
- Configure the project: Configuration
- Gate pull requests: Running in CI
- Fix issues with an agent: Coding agents
- Look up a command: CLI reference