# CLI reference

> Every Stableship CLI command, from the CLI's own help, with the environment variables and exit codes.

The CLI is Stableship from your terminal and CI. `stableship help <command>` prints the same text as each section below.

## Install

```sh
npm install -g @stableship/cli
```

Or run any command once with `npx --yes @stableship/cli@latest <command>`. It needs Node 22 or newer. This page describes 1.14.1.

## Commands

Most commands take `--json`. Commands about one app take `--project <id>` or `--repo <owner/name>`; without them, the app comes from the repository's `git remote get-url origin`.

### stableship login

```sh
stableship login [--paste]
```

Sign in from the terminal: opens `app.stableship.ai/app/connect` with a code to approve (sign up there if you're new), then saves the token to `~/.config/stableship/config.json` (mode 0600). Uses `STABLESHIP_TOKEN` when it is set. `--paste` asks for a token you made in Settings → Connections.

### stableship connect

```sh
stableship connect claude|cursor|codex|windsurf|gemini|copilot
```

Connect a coding agent. Claude Code gets the Stableship plugin (its MCP server, `/stableship`:gate, the skill and the hooks, which use your saved login), replacing a separate stableship server if there was one. Cursor, Codex, Windsurf, Gemini CLI and GitHub Copilot get the MCP server with your saved token in `~/.cursor/mcp.json`, `~/.codex/config.toml`, Windsurf's (Devin Desktop's) `mcp_config.json`, `~/.gemini/settings.json` or `~/.copilot/mcp-config.json` (Copilot CLI and VS Code). Start a new session of the agent afterwards.

### stableship init

```sh
stableship init [--agent claude|cursor|codex|windsurf|gemini|copilot] [--project <id> | --repo <owner/name>]
```

Everything to get going, one step at a time: sign in (as login), connect your coding agent (as connect; when you don't name one, the agent you run it from, else Claude Code when the claude command is installed), then say what this repository still needs in Stableship, with the link for the next step.

### stableship logout

```sh
stableship logout
```

Delete the saved token. `STABLESHIP_TOKEN`, if set, still applies.

### stableship status

```sh
stableship status [--json]
```

Each project with its latest release verdict and open and blocking finding counts.

### stableship findings

```sh
stableship findings [--blocking] [--project <id> | --repo <owner/name>] [--status open|fixed|dismissed|all]
[--limit <n>] [--since <time>] [--json]
stableship findings --sarif [--project <id> | --repo <owner/name>] [--run <runId>] > stableship.sarif
```

List findings (default: open ones). Only findings marked BLOCKS hold a release. `--since` keeps findings first seen at or after a date or time. `--sarif` prints SARIF 2.1.0 for GitHub code scanning (`github/codeql-action/upload-sarif`).

### stableship brief

```sh
stableship brief <findingId> [--prompt] [--json]
```

Print the fix brief for a finding. `--prompt` prints only the copy-paste prompt for a coding agent, e.g. stableship brief `<id>` `--prompt` | pbcopy

### stableship check

```sh
stableship check [--ref <sha|branch>] [--branch <name>] [--project <id> | --repo <owner/name>]
[--scope auto|quick|security|qa|full|skip] [--flow <key>] [--as <role>]
[--endpoint <path>] [--reason <text>] [--finding <id>]...
[--wait] [--timeout <seconds>] [--json]
```

Start a check. A ref of 7-40 hex characters is a commit (add `--branch` to say which branch it is on), anything else a branch. Without `--ref`, in the app's repository, the commit you are on is checked once it is pushed (if not, the branch as pushed, and it says so). Without `--project` or `--repo` the repo is read from `git remote get-url origin`. `--scope` defaults to auto (the change decides). Asking for less than the project's minimum for the change runs at the minimum and says so. `--flow`, `--as` (or `--role`) and `--endpoint` narrow the check. Each check started here (narrowed or not, unless skipped) counts as one of the app's deep checks this month; with none left it replays saved flows only. `--finding` re-checks those findings only, as a fix verification, which is not counted (nor are the checks every push gets). `--wait` polls until the check is done and sets the exit code from the verdict. `--timeout` defaults to 900 seconds.

### stableship skip

```sh
stableship skip "<reason>" [--ref <sha|branch>] [--branch <name>] [--project <id> | --repo <owner/name>] [--json]
```

Record that nothing in this commit needs checking (docs, copy). A change Stableship's path rules cover (sign-in, data, money) runs its minimum check instead, and says so.

### stableship audit

```sh
stableship audit [--project <id> | --repo <owner/name>] [--wait] [--timeout <seconds>] [--json]
```

Start a full audit of the default branch: every role, every critical flow, on a private copy. Uses one of the app's full audits this month (Essentials and Protect), then a purchased one. When they are used, it offers to open the purchase page and waits for the payment: the audit starts by itself once it goes through. If an audit is already running, `--wait` follows it. Audits take up to 60 minutes; `--timeout` defaults to 5400 seconds. Needs a token with the run scope.

### stableship verify

```sh
stableship verify <findingId>... [--project <id> | --repo <owner/name>] [--ref <sha|branch>] [--wait] [--timeout <seconds>] [--json]
```

Re-run just the check that found this finding, to confirm a fix. Pass every finding one fix closes (up to 20) to re-check them in one run. Without `--ref`, it re-checks the commit you are on once it is pushed (if not, the branch as pushed).

### stableship rerun

```sh
stableship rerun <runId> [--wait] [--timeout <seconds>] [--json]
```

Run a check again with the same scope, narrowing, commit and branch (or the same findings, for a verification). Use it after a run ends in failed_infra or timed_out.

### stableship why

```sh
stableship why <findingId|runId> [--json]
```

Why a finding blocks (or does not): confidence, the policy reason, the rule it breaks, repro, the verifier's notes, how often it was seen, known-issue status and evidence links. For a run: the scope it ran at, what was narrowed, each blocker and what was not covered.

### stableship rules

```sh
stableship rules [--project <id> | --repo <owner/name>] [--area access|data|money|auth|flow|other] [--path <file>] [--json]
```

The project's rules as sentences, and the flows Stableship tests. `--path` shows only the rules that concern one file.

### stableship context

```sh
stableship context [--project <id> | --repo <owner/name>] [--json]
```

Rules, kinds of user (role keys), the founder's product notes and what the last test copy could not test.

### stableship note

```sh
stableship note "<fact>" [--remove] [--project <id> | --repo <owner/name>] [--json]
```

Save one lasting product fact (under 600 characters, no secrets) to the product notes. `--remove` takes a note out instead: its words, or the whole line. Needs a token with the run scope.

### stableship propose

```sh
stableship propose --resource <thing> --action see|create|change|delete
--allowed <role,role> --reason <text> [--area access|data|money]
[--text <sentence>] [--project <id> | --repo <owner/name>] [--json]
```

Propose who may do what, instead of changing access in code. The founder accepts it under Access; a rule that only adds a check may apply at once. Needs the run scope.

### stableship flow

```sh
stableship flow --title <what people do> --reason <text> [--start </path>]
[--roles <role,role>] [--steps <text>] [--success <text>] [--critical]
[--project <id> | --repo <owner/name>] [--json]
```

Add something people do that every check clicks through. It only adds a check, so it may apply at once; otherwise the founder accepts it under Flows. Needs the run scope.

### stableship known-issues

```sh
stableship known-issues [--project <id> | --repo <owner/name>] [--json]
```

Accepted risks, false positives, won't-fix and in-progress items, and dismissed findings.

### stableship fix-plan

```sh
stableship fix-plan [--project <id> | --repo <owner/name>] [--run <auditRunId>] [--out STABLESHIP_FIXES.md] [--json]
```

Every open finding as ordered tasks (blocking first), as markdown. `--out` writes a file.

### stableship report

```sh
stableship report [--project <id> | --repo <owner/name>] [--run <auditRunId>] [--json]
```

The plain-English audit report: verdict, steps, problems and what was not tested. Without `--run`, the project's latest finished audit.

### stableship setup

```sh
stableship setup [--write CLAUDE.md] [--json]
```

The Stableship block for `CLAUDE.md`, `AGENTS.md` or Cursor rules. `--write` adds it to the file (or replaces the Stableship section already there), keeping everything else.

### stableship wait

```sh
stableship wait [--sha <commit>] [--project <id> | --repo <owner/name>] [--timeout <seconds>] [--no-run-timeout <seconds>] [--json]
```

For CI before a deploy (Railway, Fly, anything deployed from GitHub Actions): waits until Stableship has decided whether this commit may deploy. Exit 0: it may (passed, shipped anyway, nothing risky changed, or Stableship could not finish a low-risk change). Exit 1: held (a blocking problem, or Stableship could not finish a change to sign-in, data or payments). `--sha` defaults to `GITHUB_SHA`, `CI_COMMIT_SHA` or HEAD; `--timeout` to 6600 seconds. When no check starts for the commit within `--no-run-timeout` (1200 seconds) the deploy goes ahead.

### stableship hook

```sh
stableship hook install [--strict] [--force]
stableship hook uninstall
```

A git pre-push hook for this repository. Pushing to the default branch while Stableship has open blocking findings prints them; with `--strict` the push is refused unless the commit has a `Gate: <scope>` trailer. It lets the push through when Stableship is slow or unreachable. `git push --no-verify` skips it. Checks still run on GitHub.

### stableship whoami

```sh
stableship whoami [--json]
```

The workspace, the projects this token can see, its scopes (read, run, manage) and the role of the person who made it.

### stableship next

```sh
stableship next [--project <id> | --repo <owner/name>] [--json]
```

The latest audit as a plan: how it went, what was covered, what to fix first (grouped by cause, ranked) and the one next step. Start here after an audit.

### stableship activity

```sh
stableship activity [--project <id> | --repo <owner/name>] [--limit <n>] [--json]
```

What changed recently and who did it: findings dismissed, rules changed, fixes verified, settings.

### stableship map

```sh
stableship map [--project <id> | --repo <owner/name>] [--run <runId>] [--json]
```

The map of the app from the latest audit: the pages each kind of user reached and how each went, the endpoints the API checks called, and what changed since the last map.

### stableship approval

```sh
stableship approval <approvalId> [--json]
```

Whether a person approved an action you asked for, and whether Stableship carried it out.

### stableship do

```sh
stableship do <action> [--key value]... [--json]
```

Run Stableship from your terminal or coding agent. Needs a token with the manage scope. Actions:

```text
triage_finding --finding-id <id> --status false_positive|accepted|fixed|open --reason <text>
reanalyze
resume_held_audit --run-id <id>          ship_anyway --run-id <id> --reason <text>
decide_rule_suggestion --suggestion-id <id> --accept true|false
set_policy --type blocking|fail_open|schedule|notifications --settings '<json>'
set_autonomy --level hands_on|guided|autopilot
set_role --key <key> --name <name>       set_role_reach --key <key> --reach all|related
remove_role --key <key>                  remove_rule --rule-id <id> --reason <text>
share_report --run-id <id>               unshare_report --run-id <id>
set_notifications --events block|approval_needed|audit_complete|digest [--events …] --email true|false
create_app --repos <owner/name> [--repos <owner/name>]... [--name <name>]   (the first repository is the main one)
link_repo --add <owner/name>             set_service --service-id <id> [--kind <kind>] [--start <cmd>] [--port <n>] [--ignored true|false] [--reset]
```

Project actions take `--project-id` or `--repo` (default: the git remote). Anything that lowers protection (letting a blocking problem through, shipping anyway, loosening a policy) asks you here when you run it in a terminal; run by an agent without a terminal, it asks a person in Stableship instead (email, Slack, the app) and prints how to follow the approval.

## Environment

```text
STABLESHIP_TOKEN    API token. Takes precedence over the saved login (use this in CI).
STABLESHIP_API_URL  API base URL (default https://api.stableship.ai).
XDG_CONFIG_HOME     Where the config directory lives (default ~/.config).
```

## Exit codes

```text
0  Success. For check, verify and rerun: the release passed, passed with warnings, was
   skipped or shipped anyway. Also 0 when Stableship itself failed (failed_infra,
   timed_out, cancelled): Stableship never blocks a release on its own infrastructure
   failure, so it prints a warning and lets you through.
1  Blocked. The verdict is "block": at least one finding blocks this release (for verify:
   the finding was found again; for the strict pre-push hook: the push was refused). A verify
   that could not reach the finding prints "Could not check" and exits 0.
2  Could not run. Usage error, not logged in, token rejected or missing a scope, API
   error, or --wait ran past --timeout.
```
