CLI
cora [options] [command]cora --help lists the global options and the commands on the command line, and cora <command> --help a command’s description, options and examples. A command that needs an account checks it before it runs, as What needs an account says.
Global options
Section titled “Global options”Global options apply to every command.
| Option | Description |
|---|---|
--version |
print cora’s version |
--log-level <level> |
trace, debug, info, warn, error or silent |
--log-file [path] |
write a JSON Lines log file, to the state directory’s logs/ (.cora/logs/ by default) without a path |
--log-format <format> |
human or json, for stderr |
-v, --verbose |
log at info |
-q, --quiet |
log only errors, and print no progress or summary |
--debug |
log at debug, and write a log file |
--color |
color the output, even where it is not a terminal |
--no-color |
never color the output |
-h, --help |
display help for command |
Commands
Section titled “Commands”| Command | Description |
|---|---|
cora scan |
scan the targets, write a results file, and compare it with the baseline |
cora report merge |
merge results files, compare them with the baseline, and write the report |
cora baseline update |
accept the issues in results files into the baseline |
cora status |
show the account, the project’s newest scans and its fixes’ progress |
cora auth login |
sign in to CORA in the browser, or with an account token from stdin |
cora auth logout |
sign out, removing the credentials file |
cora auth status |
print the account the credential names |
cora auth token |
print the account token, renewing it first when it nears its expiry |
cora init |
set up CORA in the project: its config, CORA’s build plugin or Angular’s source locations, and its coding agents |
cora info |
print the environment a bug report needs |
cora mcp |
run cora’s MCP server for coding agents, at the same version |
cora hook |
answer a coding agent’s hook: read the event on stdin, and write the answer on stdout |
cora help |
display help for command |
cora scan
Section titled “cora scan”Scans each target in a browser, and writes a results file to the state directory’s runs/. Targets and crawls on the command line replace the config’s targets.
When the config names a server, it starts the server first and stops it once the scan ends. It then compares the results with the baseline, and exits 1 when the gate fails. In CI, or with --report, it also writes the report directory.
With --shard or --no-gate, it writes only the results file, which cora report merge compares later.
cora scan [options] [targets...]Needs an account: yes: cora checks it before the command runs, and stops with account.missing when you are not signed in.
| Argument | Description |
|---|---|
targets |
URLs, or paths relative to the base URL; replace the config’s targets |
| Option | Description |
|---|---|
--base-url <url> |
replaces the config’s baseUrl |
--crawl <url> |
crawl from this page, a URL or a path relative to the base URL, following its links that stay on its host; repeatable; with the targets, replaces the config’s targets |
--crawl-max-pages <n> |
the most pages each crawl takes in, its start page included; 25 by default, as a crawl’s maxPages |
--crawl-max-depth <n> |
the most links each crawl follows from its start page, 0 to scan the start page alone; 2 by default, as a crawl’s maxDepth |
--crawl-exclude <pattern> |
a regular expression for links no crawl follows, such as /logout, tested against each link’s absolute URL; repeatable |
--crawl-ignore-robots-txt |
follow links that a site’s robots.txt disallows, as a crawl’s ignoreRobotsTxt does |
--page-timeout <ms> |
bounds each page’s visit, in milliseconds; replaces the config’s page.timeout |
--headed |
shows the browser, to watch the scan; headless in CI, under a coding agent or without a display; replaces browser.headed in your user config |
--only <selectors> |
run only the rules these selectors name, of those the config’s rules select: rule IDs such as axe/region, criteria such as 1.4.3, categories such as forms, or engines such as axe/*, comma-separated; repeatable |
--skip <selectors> |
run none of the rules these selectors name; as --only takes them |
--out <path> |
write the results file here instead of the state directory’s runs/ (.cora/runs/ by default); - for stdout |
--shard <i/n> |
scan only shard i of n; cora report merge compares the shards |
--no-gate |
only write the results file, for a later cora report merge |
--baseline <path> |
compare with this baseline instead of cora.baseline.json |
--report <dir> |
write the report directory here; in CI, the state directory’s report/ (.cora/report/ by default) |
-h, --help |
display help for command |
Examples:
# Scan the config's targets, and compare the results with the baselinecora scan
# Scan one page of the app at localhost:5173cora scan /pricing --base-url http://localhost:5173
# Crawl a site from its home page, taking in up to 50 pagescora scan --crawl https://example.com/ --crawl-max-pages 50
# Scan with the browser shown, to watch itcora scan --headed
# Run only the rules of the forms category and of WCAG's 1.4.3cora scan --only forms,1.4.3
# Scan the second of four shards, for `cora report merge`cora scan --shard 2/4 --out results-2.jsoncora report merge
Section titled “cora report merge”Merges results files, such as the shards of one run, into one run. It compares the merged run with the baseline, writes the report directory, and exits 1 when the gate fails.
Each input is a results file, or a directory whose .json files it reads. Every shard of a sharded run must be there: a missing one stops the merge with exit code 2.
cora report merge [options] <inputs...>Needs an account: yes: cora checks it before the command runs, and stops with account.missing when you are not signed in.
| Argument | Description |
|---|---|
inputs |
results files, or directories of them |
| Option | Description |
|---|---|
--baseline <path> |
compare with this baseline instead of cora.baseline.json |
--report <dir> |
write the report directory here instead of the state directory’s report/ (.cora/report/ by default) |
-h, --help |
display help for command |
Examples:
# Merge every results file in `results/`cora report merge results
# Merge them, and write the report directory to `report/`cora report merge results --report reportcora baseline update
Section titled “cora baseline update”Rewrites the baseline from the latest results. It adds each new violation, and removes each one the results prove fixed. It keeps what they did not verify, such as the violations of a rule the run skipped.
The baseline is cora.baseline.json in the project, unless --baseline names another. Commit it, so each run’s gate compares with it. Each input is a results file, or a directory whose .json files it reads.
cora baseline update [options] <inputs...>Needs an account: yes: cora checks it before the command runs, and stops with account.missing when you are not signed in.
| Argument | Description |
|---|---|
inputs |
results files, or directories of them |
| Option | Description |
|---|---|
--baseline <path> |
rewrite this baseline instead of cora.baseline.json |
-h, --help |
display help for command |
Examples:
# Accept the issues a scan foundcora baseline update results.json
# Accept those of every results file in `results/`, such as the shards of a runcora baseline update resultscora status
Section titled “cora status”Shows whether your account is valid, the project’s newest scans, and where each issue the coding agent’s fixer works on stands. With --json, it prints the same as one JSON object, in a versioned format.
It reports the account rather than requiring one. A coding agent’s subagent status line runs it with --subagent-status-line.
cora status [options]Needs an account: no: the command reports whether you are signed in, and runs without an account.
| Option | Description |
|---|---|
--json |
print one JSON object, in a versioned format |
--subagent-status-line <harness> |
answer a coding agent’s subagent status line: read its rows on stdin, and write the fixer’s progress in the fixer’s row (claude) |
-h, --help |
display help for command |
Examples:
# Show the account, the newest scans and the fixes' progresscora status
# Print the same for a scriptcora status --jsoncora auth login
Section titled “cora auth login”Signs in to your CORA account. It prints a page and a code to enter there, and opens the page in your browser where it can. Once you approve the login, it saves the credential in your per-user config directory.
With --with-token, it saves the account token it reads from stdin instead, without the browser.
cora auth login [options]Needs an account: no.
| Option | Description |
|---|---|
--with-token |
save the account token read from stdin, without the browser |
-h, --help |
display help for command |
Examples:
# Sign in through the browsercora auth login
# Save a token from a file, without the browsercora auth login --with-token < token.txtcora auth logout
Section titled “cora auth logout”Signs out by removing the saved credential. When CORA_TOKEN is set, it says so, since the variable still provides a credential until you unset it.
cora auth logoutNeeds an account: no.
| Option | Description |
|---|---|
-h, --help |
display help for command |
Examples:
# Sign out on this machinecora auth logoutcora auth status
Section titled “cora auth status”Checks the account, then prints the CORA service and your account there: its organization, by ID and name, its plan, when its token expires, and where the credential comes from. Without a credential, it fails with account.missing.
cora auth statusNeeds an account: yes: the command checks it as it runs, and fails with account.missing when you are not signed in.
| Option | Description |
|---|---|
-h, --help |
display help for command |
Examples:
# Show the account and when its token expirescora auth statuscora auth token
Section titled “cora auth token”Prints the account token on stdout, alone, for a script that needs it. It renews a signed-in token first when the token expires within the hour. When CORA_TOKEN is set, it prints that token.
Treat what it prints as a secret: pass it on through a variable or a file, never on a command line.
cora auth tokenNeeds an account: yes: the command checks it as it runs, and fails with account.missing when you are not signed in.
| Option | Description |
|---|---|
-h, --help |
display help for command |
Examples:
# Give the commands this shell starts the token of your loginexport CORA_TOKEN="$(cora auth token)"cora init
Section titled “cora init”Sets CORA up in the project in the working directory. It writes a starter config, unless the project has one: cora.config.ts beside a package.json, and cora.config.json elsewhere. In a Vite project, it registers CORA’s Vite plugin in the Vite config, and in a Nuxt or Astro project in vite.plugins of its nuxt.config or astro.config, where the framework reads Vite’s plugins; in a webpack, Rspack, Rsbuild, Rollup or Rolldown project, it registers that bundler’s plugin in its config’s plugins, so findings name the line to fix. In an Angular CLI workspace on Angular 22.1.4 or later, it turns on Angular’s own template source locations for each application’s development builds: a tsconfig.cora.json beside the application’s tsconfig, and the development configuration in angular.json pointed at it. A project that lists one of these tools without a config of it there is told it was not set up, and where the plugin goes, unless a tool that brings that bundler along is set up there, as Vite does Rollup.
The starter config’s target is a crawl from the home page, of up to 25 pages up to 2 links away, which skips common sign-out links. Where the nearest package.json’s dev script, or its start script where it has no dev, starts the dev server of Vite, Next.js, Nuxt, React Router, Docusaurus, Angular, Create React App, CRACO, webpack, Rspack, Rsbuild or Parcel, it sets server to run that script with the project’s package manager, and baseUrl to the server’s address: the port the script sets, or else the port the dev server’s own config writes out, or else the tool’s default. It reads the script and that config, and runs neither. It prints the command and URL it set, and cora scan then starts the app, and stops it once the scan ends. Where it cannot be sure where the server answers, as for a script that starts two servers, serves HTTPS, listens on an address localhost may not reach, or takes its port from a shell variable such as $PORT, or for a dev server whose own config computes or imports its port, it writes no server, says why, and leaves baseUrl a placeholder. With --base-url, it sets that address and no server.
For Claude Code, it adds CORA’s plugin to the project’s Claude Code settings. For Codex, it sets CORA’s fixer agent up in the project’s .codex/, from the cora the project installed, or as a copy where Codex can read no installed one, as on Yarn’s Plug’n’Play. Where neither is there yet, it prints the run of cora init that does this after the install. It finds the coding agents a project uses from their files in it, such as .claude/ or AGENTS.md, and from their CLIs on PATH, unless --agent names them.
It keeps each file’s own layout, and formats a new file with the project’s Prettier, which reads its config and .editorconfig, or else indented as the nearest package.json is, or with two spaces. It leaves a file it cannot edit as it is, and names the docs page that shows the change to make by hand.
It shows each change as a diff, and asks once before it writes anything. In CI, inside a coding agent, or with --yes, it writes without asking. Elsewhere, where it cannot ask, such as with stdin or stderr redirected, under -q or with --log-format json, it writes nothing and fails with cli.confirmation-required. Running it again changes only what is missing, CORA’s copies nobody has edited, and a fixer declaration whose file is gone.
cora init [options]Needs an account: no: the command reports whether you are signed in, and runs without an account.
| Option | Description |
|---|---|
--base-url <url> |
the address of an app init does not start, such as a staging site or one a backend serves, which a new config sets with no server |
--agent <names...> |
set up these coding agents rather than those detected; repeatable (claude or codex) |
--project-agent |
set up CORA’s fixer for Claude Code as a project agent with an MCP server of its own, so that only the fixer has CORA’s tools |
-y, --yes |
write the changes without asking |
-h, --help |
display help for command |
Examples:
# Set up the project to start and scan the app's dev servercora init
# Set up the project to scan an app it doesn't start, at staging.example.comcora init --base-url https://staging.example.com
# Set up Codex alone, without askingcora init --agent codex --yescora info
Section titled “cora info”Prints what a bug report needs: which cora ran and why, Node.js, the operating system, the project’s config, your user config, the browsers cora would use, and which of the variables it reads are set.
Of the variables it reads, it prints which are set, not their values, and of your user config only whether cora used it. The exceptions are the CORA service, its request timeout, the paths cora uses, such as the state directory, the coding agent that runs cora, by the name its variable gives, and why your user config was ignored, such as a later version’s file. Paste its output into the report, or attach the JSON.
cora info [options]Needs an account: no.
| Option | Description |
|---|---|
--json |
print one JSON object |
-h, --help |
display help for command |
Examples:
# Print the environment for a bug reportcora info
# Save it as JSON, to attachcora info --json > cora-info.jsoncora mcp
Section titled “cora mcp”Runs cora-mcp, CORA’s MCP server for coding agents, at this cora’s version. It fetches that release of @vispero/cora-mcp through npx, then hands over to it. Options after mcp pass to cora-mcp.
A coding agent’s MCP entry runs it as npx --no cora mcp, so the server follows the project’s cora through its upgrades.
cora mcp [cora-mcp options...]Needs an account: yes, for its tools: cora-mcp starts and lists its tools without one, then checks it on each tool call, which it answers with account.missing when you are not signed in.
| Argument | Description |
|---|---|
cora-mcp options |
passed to cora-mcp as they are, such as --headless |
| Option | Description |
|---|---|
-h, --help |
display help for command |
Examples:
# Serve a coding agent on stdio, at this cora's versioncora mcp
# Serve with a browser that opens no windowcora mcp --headlesscora hook
Section titled “cora hook”Answers a coding agent’s hook, as CORA’s plugin runs it: it reads the event on stdin, and writes its answer on stdout. Its answers ask you before an edit of what decides what CORA reports, keep CORA’s tools in the fixer, and start the fixer after UI edits.
It exits 0 whatever happens, since an agent reads another exit code as a block or an error. It writes nothing on stderr, and logs to its agent session’s file in the state directory’s logs/. Its stdout holds only its answer, so cora hook --help prints nothing; cora help hook prints this help.
cora hook [options] <event>Needs an account: partly: without an account, the command says why, as a warning, then does only the work that needs none, such as asking you before an edit of what decides what CORA reports.
| Argument | Description |
|---|---|
event |
the hook’s event: user-prompt, when the person submits a prompt to the coding agent; pre-tool-use, before the coding agent runs a tool; post-tool-use, after a tool the coding agent ran succeeds; stop, when the coding agent is about to end its turn; subagent-start, when the coding agent starts a subagent; subagent-stop, when a subagent is about to stop; session-end, when the coding agent’s session ends |
| Option | Description |
|---|---|
--harness <harness> |
the coding agent that runs the hook (claude or codex) |
Examples:
# Answer Claude Code's event before a tool runs, saved in `event.json`cora hook pre-tool-use --harness claude < event.jsoncora help
Section titled “cora help”display help for command
cora help [command]Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
| 0 | The gate passed, or a command that gives no verdict finished: cora scan with --shard or --no-gate, cora baseline update, cora auth login, cora auth logout, cora auth status, cora auth token, cora init, cora info or cora hook |
| 1 | The gate failed: new issues at or above policy.failOn |
| 2 | No verdict: a target or file was not scanned, such as a failed load or a redirect to a page the run did not scan, and nothing failed, or an error stopped the command: any code in the error reference |
Exit code 2 covers both a run that gives no verdict and an error. A CI script that starts from an empty report directory tells them apart by whether results.json was written there: an incomplete run is reported in full, with results.json written last, and an error stops before it. A command that needs an account, such as cora scan, checks it before anything else: without a valid credential it fails with an account.* error, and with a service.* error when the CORA service does not answer as the check renews the credential or fetches the signing keys. cora hook exits 0 whatever happens, since a coding agent reads any other exit code from a hook as a block or an error: it reports an error, a missing account among them, as its answer on stdout. A signal ends a command by that signal, which a shell reports as 128 plus its number: 130 for Ctrl+C, 143 for SIGTERM. cora scan, cora auth login and cora init stop first and write no file from then on, so an interrupted scan writes no results, and cora mcp ends by the signal once the npx or the release it runs has ended.