Skip to content

Getting started

This guide scans a first site without a project, then installs cora in a project, sets the project up, and scans it.

  • Linux, macOS or Windows.
  • Node.js 22.18.0 or later. On an older release, cora stops: node.unsupported-version says why, and how to install a later one.
  • Google Chrome, which cora scans with. Without it, run npx playwright install chrome.
  • Playwright 1.51 or later. @vispero/cora declares playwright-core as a peer dependency, which npm and pnpm install with it. With Yarn, add playwright-core yourself. A project that already uses @playwright/test or playwright scans with that copy and its browsers.
  • A CORA account, in an organization with a CORA plan. See Accounts.

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:

Terminal window
npx @vispero/cora auth login
npx @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.

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.

  1. Add @vispero/cora to the project as a devDependency, then check that cora runs. It prints the installed version.

    Terminal window
    npm install -D @vispero/cora
    npx cora --version

    A copy of cora installed globally hands over to the project’s own copy inside a project, so every command runs the project’s version.

  2. Set the project up with cora init:

    Terminal window
    npx cora init

    It 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 your dev script, or your start script where you have no dev, 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.plugins of its nuxt.config or astro.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.

  3. Sign in to your CORA account. You do this once on each machine:

    Terminal window
    npx cora auth login

    cora prints 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.

  4. Scan your app. Where your config sets server, cora starts your dev server, and stops it once the scan ends; otherwise, start your app first:

    Terminal window
    npx cora scan

    cora scans 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 minor
    Targets: 6
    Issues: 2 (2 new)
    Duration: 1.2 s
    Results: .cora/runs/20261026T001255241Z-rzqqlsix.json
    To accept them, run:
    npx 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.

In a Vite app whose dev script runs vite, cora init writes this, with comments that explain each key:

cora.config.ts
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)(?:[/?#.]|$)'],
},
],
});
  • baseUrl is your dev server’s address where cora init sets server. Where it doesn’t, it’s a placeholder, http://localhost:5173: set it to your app’s address.
  • server runs your dev script, or your start script where you have no dev, with your package manager, where it starts a dev server cora init recognizes. 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 init prints the command and URL it wrote: where a variable set outside the script moves the server, such as PORT in 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 maxPages and maxDepth to scan more of the app.
  • exclude keeps the crawl off common sign-out links, such as /logout, /sign-out and /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.

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.