Skip to content

Scanning without a project

cora scans any site you can reach, from any folder, such as a public site you want to try CORA on, or a customer’s site you audit. You need no project and no config: cora keeps each scan’s results in the folder you run it in.

A folder is outside a project when neither it nor any folder above it holds a CORA config or a package.json that lists @vispero/cora. What a project adds lists what you gain by setting one up.

  • Node.js 22.18.0 or later, and its npx, or pnpm’s pnpm dlx.
  • Google Chrome. Without it, run npx playwright install chrome.
  • A CORA account, in an organization with a CORA plan. See Accounts.

npx and pnpm dlx install @vispero/cora, and the Playwright it scans with, in their own cache, never in the folder.

  1. Make a folder for the site, and go into it:

    Terminal window
    mkdir example-audit
    cd example-audit
  2. Sign in to your CORA account. You do this once on each machine, and every folder uses the login:

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

  3. Scan the pages you want, by their URLs:

    Terminal window
    npx @vispero/cora scan https://example.com/ https://example.com/pricing

    With pnpm, run pnpm dlx @vispero/cora in place of npx @vispero/cora. To name pages by their paths, give the site’s address once with --base-url:

    Terminal window
    npx @vispero/cora scan / /pricing --base-url https://example.com

    Give a folder’s runs the same base URL, or none, every time. An issue on a page under the base URL is identified by its path alone, and an issue on any other page keeps the site’s host, so a folder that switches between the two reads its issues as new (One issue on two sites).

cora prints a summary, as Results describes, and writes the run’s results file to .cora/runs/ in the folder:

Gate failed: 3 new issues at or above minor
Targets: 2
Issues: 3 (3 new)
Duration: 4.1 s
Results: .cora/runs/20261110T214403123Z-k3j9x2ab.json
To accept them, run:
npx @vispero/cora baseline update .cora/runs/20261110T214403123Z-k3j9x2ab.json

The first scan reports every violation as new, so the gate fails and cora scan exits with code 1, as in a project. The CLI reference lists each exit code.

To scan a site’s pages without listing them, crawl it from a start page with --crawl:

Terminal window
npx @vispero/cora scan --crawl https://example.com/ --crawl-max-pages 50
  • The crawl follows each page’s links that stay on its host, up to --crawl-max-pages pages and --crawl-max-depth links from the start, each with a default. --crawl-exclude keeps it off links that match a pattern, such as /logout. Targets says more.
  • It reads the site’s robots.txt, and follows no link it disallows for CORA, listing each such page as not scanned. --base-url with the site’s address also marks the site as yours, so the crawl reads no robots.txt there, and --crawl-ignore-robots-txt reads none anywhere. Use either only on a site you own (Crawls and robots.txt).

Outside a project, the folder you run cora in takes the project root’s place. Its .cora/ holds what a project’s does:

  • Directoryexample-audit/
    • Directory.cora/
      • Directoryruns/ one results file per scan
        • …
      • Directoryreport/ the report directory, which a scan in CI and cora report merge write
        • …
      • Directorylogs/ log files you ask for, and crash files
        • …
    • cora.baseline.json the issues you accepted
  • .cora/ ignores itself in git, so a folder you commit keeps it out.
  • cora creates .cora/ once it first writes there. cora status and cora info alone create none.
  • In a folder you cannot write, cora scan stops before it scans with cli.state-unwritable, naming the state directory. Run it in a folder you can write, or move .cora/ with stateDirectory.
  • Each folder keeps its own .cora/. So keep a folder for each site, and cora status there lists that site’s scans alone.
  • Your user config’s stateDirectory, or CORA_STATE_DIRECTORY, moves .cora/, as in a project. A relative path is relative to the folder you run cora in, and it is never that folder, or one that holds it. An absolute path gives every folder the one directory.

The commands that read results work in the folder as they do in a project:

  • cora baseline update accepts a run’s issues into cora.baseline.json in the folder, as the summary’s last line shows. The next scan from the folder compares with it, and fails only on new issues. Baselines and the gate says how the baseline matches.
  • cora status lists the folder’s newest scans, under Project: not found.
  • cora report merge merges results files into the report directory, .cora/report/, with a Markdown summary and a SARIF log, as The report directory describes.

Without a config file, a scan takes the defaults. Flags, environment variables and your user config still set what holds a single value:

  • --page-timeout, or CORA_PAGE_TIMEOUT, gives a slow site’s pages longer;
  • CORA_POLICY_FAIL_ON sets the severity at which the gate fails;
  • CORA_BROWSER_STORAGE_STATE names a Playwright storage-state file that signs the scan in to the site, relative to the folder.

Environment variables says which settings have one. --only and --skip narrow the rules of one run, without a config (Narrowing a run). A saved list of targets, a lasting choice of rules, how each page is waited for, a sign-in script and the app’s server need a config file: see What a project adds.

cora-mcp started outside a project keeps its state in .cora/ in the folder its client started it in, which is the folder you opened in the agent. It creates .cora/ only once it writes something there: a tool that writes state, such as a scan, verify_fix, summarize_fixes or a browser tool, a log file you ask for, or a crash file. Listing its tools, and the tools that only read, such as list_rules and get_fix_guidance, write nothing.

In a folder cora-mcp cannot write, a tool that writes state fails with mcp.state-unwritable, naming the directory. The tools that only read still work there. In a folder cora-mcp cannot write gives the fixes.

To give the folder a config, add cora.config.json, or install cora and run cora init, as Getting started shows. The folder then is the project root, and its .cora/ and baseline stay where they are. If the config’s baseUrl names the site while the folder’s runs gave no base URL, its issues read as new once, since a page under the base URL is identified by its path alone.