CLI
Install the v12 command, sign in, run the common commands, and use it in CI.
The v12 command reads and triages findings, starts and follows runs, and manages context documents from your terminal. It calls the REST API, so the same scopes, permissions and errors apply.
Install
npm install -g @v12sh/cli
v12 --versionOr run it without installing: npx @v12sh/cli. Version 1.0 needs Node.js 20.19 or later.
Sign in
v12 auth login
v12 auth statusv12 auth login opens V12's consent page for V12 CLI in your browser, and saves the credentials when you select Authorize V12 CLI. The login acts on the workspace active in V12 at that moment; see Which organization a token reads. The CLI refreshes its access token and finds the workspace's slug for REST paths itself, so no command takes one.
-
--no-browserdoesn't open the browser; open the URL the CLI prints. The login waits up to five minutes. -
--scopeschooses a comma-separated scope list, such as--scopes user:read,findings:read. Without it, the CLI requests every scope except the opt-inruns:share(guest links) andsteers:write(Steer management). Include either explicitly when needed, together with the other scopes your workflow uses. API keys expose them as Share runs and Manage Steers. -
--with-tokenreads an API key from standard input instead of signing in with OAuth:printf '%s\n' "$V12_API_TOKEN" | v12 auth login --with-token
| Command | What it does |
|---|---|
v12 auth status | Shows your user, workspace with its slug, and token scopes |
v12 auth token | Prints a valid access token, refreshing it if needed. Treat the output as a secret. |
v12 auth logout | Revokes the OAuth tokens and deletes the saved credentials. For an API key, it only deletes the key from this machine; revoke the key in Settings → Developer. |
Repository and position
Commands that work on one repository take --repo: the repository's full name, owner/name, or its slug. Without it, the CLI reads the repository from git remote get-url origin when that is a GitHub URL ([email protected]:owner/, https://github.com/ or ssh://[email protected]/). v12 findings list shows the organization inbox when it finds no repository, and always with --org.
--at takes a position, or HEAD, which the CLI turns into your checkout's current commit.
Commands
| Command | What it does |
|---|---|
v12 me, v12 members | Your user and workspace; the workspace's members |
v12 steers list| | Steer documents; list --archived shows only archived ones. Writes require steers:write. |
v12 repos list|show|refs | Repositories, their state, and their branches, pull requests and tags |
v12 repos add | Add a repository to the workspace by owner/name, GitHub link or clone URL; without one, the origin repository. Adding a repository that is already there changes nothing. |
v12 repos create|push | Create a repository V12 hosts, v12/<name>, and push a commit to one of its branches; see Push code to a hosted repository. Admins only; available in CLI 1.2. |
v12 findings list|show | The organization or repository inbox; one finding with its reports, evidence and activity |
v12 findings status| | Triage findings by key, such as F-42, or number. assign takes me, none, or a member's email or username. |
v12 runs list| | Runs, their stages, the findings they added to the inbox, following a run, and cancelling it. A run is named by its number in the workspace, such as 12. |
v12 runs estimate|start | Price a run, or approve and start it |
v12 runs links list| | Guest links that open a run to people outside the organization. Each takes the run's number; update and revoke also take the link's number in the run, such as v12 runs links revoke 12 2. create prints the URL once; update --clear-label removes a link's label. Needs runs:share; create and update also need findings:read, and findings:write for a comment or triage link. |
v12 docs list| | Context documents for runs; list --archived adds archived documents to the active ones. |
v12 findings list --status open --severity critical,high
v12 findings status fixed F-12 F-15
v12 findings assign me F-12
v12 repos add https://github.com/acme/sdkA status change takes no reason; explain a decision with v12 findings comment. CLI 1.1 and older still require --reason, which V12 now refuses, so update with npm install -g @v12sh/.
v12 <command> --help, for example v12 findings list --help, lists every flag.
Members can add public repositories. Only an Admin can add a private repository, and the workspace's GitHub App must be able to read it. Adding a repository doesn't start a run. A run on a repository that isn't in the workspace fails with repository_not_added until you add it.
Manage Steers
Steer writes are available in CLI 1.1 and need the opt-in steers:write scope. Use v12 auth login --scopes repos:read,steers:write, adding any other scopes your workflow needs, or select Manage Steers on an API key.
v12 steers create --title 'Accounting' --emoji '🧮' --file accounting.md
v12 steers edit accounting --file updated-accounting.md
v12 steers archive accounting
v12 steers list --archived
v12 steers restore accounting--instructions 'text' supplies instructions directly, and --file - reads stdin. Edits keep omitted fields and the original slug; --instructions '' clears the document. Repeating create makes another document. Archive and restore are safe to repeat. Archiving detaches Autopilot rules but preserves finding tags and run history; restoring does not reattach rules. See Steers.
Start runs from the CLI
v12 runs start --repo acme/api --at branch:main --scope src/ --max-price 25v12 runs start estimates the run and prints the price and what it covers. In a terminal, it asks you to confirm, then starts the run with that quote. v12 runs estimate takes the same flags and only prices the run.
- What to review:
--atreviews the code at a position.--pr <number>(GitHub repositories only), or--branch <name>with an optional--since <commit>, reviews a change; see Review a change.--sincetakes a full 40-character SHA, or a revision this checkout names, such asHEAD~1or an abbreviated SHA, which the CLI resolves with Git.--also,--steeringand--docadd other repositories, instructions and context documents.--steer <slug>, repeatable up to 5 times, attaches Steers to either kind of review. - What it reads: a review of the code reads only what
--scopenames, with no default: pass each folder (ending in/) or file, repeating the flag.--scope owner/name:pathnames what an--alsorepository reads, and each one needs at least one. A path that names nothing V12 reviews is refused. - Price limit:
--max-price(dollars) or--max-price-centssets the most the run may cost. Without either, the quoted price is the limit. A run that would cost more doesn't start. - Confirmation:
--yesskips the prompt. Outside a terminal,--yesis required; without it, the command exits with code 2. - Follow it:
--watchfollows the run until it ends, then prints its findings.
v12 runs findings <run> lists findings at each repository's analyzed commit, including findings only on a branch or pull request. status and codeState are evaluated at those commits, so a later fix on the default branch leaves the run's finding open. If the finding is present at current defaults, read it without a position for its current state.
With --json:
- Each repository's
position.atiscommit:<sha>, and each finding'swebUrlopens its detail in the repository workspace at that commit. - For later positioned reads, send that
position.atwith itsrepositories[i].repository. It keeps working if the branch moves or disappears. - Without
repository, V12 infers it, and answersrepository_requiredwhen more than one registered repository holds the finding at that position.
For the same flow over REST or MCP, see Start a run within a price limit.
Use in CI
Create an API key with only the scopes the job needs, and store it as a CI secret. Reading findings needs findings:read. Starting runs needs runs:write; --watch adds runs:read and findings:read.
- name: List open critical findings
env:
V12_API_TOKEN: ${{ secrets.V12_API_TOKEN }}
run: npx @v12sh/cli findings list --repo ${{ github.repository }} --status open --severity critical --jsonV12_API_TOKEN takes precedence over saved credentials, so the job needs no login. The CLI takes the API URL from --api-url, then V12_API_URL, then the saved setting, then https://v12.sh.
Output
The CLI prints readable results by default. --json prints the API response as JSON on standard output. Prices, progress, prompts and errors go to standard error, so the JSON stays parseable.
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Any other error, or a watched run that failed or was cancelled |
2 | Usage error, including runs start outside a terminal without --yes, or a declined confirmation |
3 | unauthenticated, insufficient_scope or forbidden |
4 | not_found, repository_not_added or repository_not_visible |
5 | price_exceeds_max, insufficient_credits, spend_cap_reached or quote_stale |
6 | rate_limited, or any HTTP 429 or 503 |
Configuration
The CLI saves credentials in ~/, one entry per API URL, with the slug of the workspace they read. Only your user can read the file.
Upgrading from 0.3
Version 0.3 used /api/v1, which now answers 410. Install version 1.0 or later; v12 repos create and v12 repos push need 1.2. Each keeps an API key that 0.3 saved.
Upgrading from 1.0
The API now refuses a review of the code without a scope. Version 1.1 checks for --scope before it sends the request, and adds --scope owner/name:path for --also repositories, which 1.0 can't scope.