Docs
Everything below works in the shipped CLI today. Nothing here is planned, aspirational, or coming soon.
Setup, start to finish
Four commands. Two minutes.
login prints a short code and opens your browser. Approve it and the machine is connected — no password is ever typed into a terminal.
init detects your language, package manager and test/build commands, then writes .shipsure/config.json. Commit that file; it is project configuration, and it is meant to be reviewed in a pull request like any CI config.
link attaches the folder to a project you created in the dashboard. The CLI cannot create projects on purpose — an agent token is deliberately not allowed to, so a token lifted off a laptop cannot spin up new ones.
The daily loop
The order matters. baseline records the state of your tests before the agent touches anything. Run it afterwards and a test the agent just broke looks like it was already failing, so the regression goes undetected. If no usable baseline exists, ShipSure says so in the verdict instead of quietly claiming a clean comparison.
verify runs your project’s own commands, compares against the baseline, checks scope and policy, prints a verdict, and uploads the run so it appears in the dashboard.
Commands
| Command | What it does |
|---|---|
shipsure login | Connect this machine via a device code. |
shipsure logout | Revoke this machine server-side, not just locally. |
shipsure whoami | Ask the server who this machine is signed in as. |
shipsure init | Detect the stack and write .shipsure/config.json. |
shipsure link | Attach this folder to a cloud project. |
shipsure project list | List the projects in your organization. |
shipsure baseline | Record the "before" state. |
shipsure verify | Run verification and print a verdict. |
shipsure watch | Verify automatically whenever the tree goes quiet. |
shipsure cancel | Stop a run that is still going. |
shipsure rollback | Restore the tree to the baseline, stashing first. |
shipsure runner | Run this machine as a private runner. |
shipsure doctor | Diagnose the environment; every failure carries a fix. |
Flags
| Flag | Effect |
|---|---|
--json | Machine-readable output for CI. |
--local | Verify with no network at all, and do not upload the run. |
--no-baseline | Skip the comparison. The verdict states regressions were unchecked. |
--force | Overwrite config on init, or baseline a dirty tree. |
--no-browser | On login, print the URL instead of opening a browser. |
--project <id> | On link, name the project instead of choosing interactively. |
--clear, --show | On baseline, clear or print the stored one. |
--quiet-ms <n> | On watch, how still the tree must be before verifying. |
--yes, --dry-run | On rollback, skip the prompt, or show what would change. |
--once | On runner, take one job and exit. |
Exit codes
The CI contract. Separate codes are what let a pipeline treat “needs a human” differently from “the code is broken” — collapsing them into 1 would make ShipSure useless in CI.
| Code | Meaning |
|---|---|
0 | Verified |
1 | Failed — a required check failed |
2 | Blocked — a policy or approval gate |
3 | Inconclusive — could not verify reliably |
4 | Cancelled |
64 | Usage error — bad arguments, or not a ShipSure project |
77 | Authentication error |
Configuration
.shipsure/config.json holds the project id, the detected adapters, your policy and the default task contract. It is committed. Credentials never go near it — tokens live in ~/.shipsure/credentials.json at mode 0600, per machine.
What runs on your machine
- Commands run in a child process with an explicit environment allowlist, so stray credentials in your shell are never handed to a test suite.
- Hard timeouts and output truncation. A runaway process is killed and reported as an error, not a failure — ShipSure does not claim a verdict it cannot support.
- Secrets are redacted before anything is hashed or uploaded.
- Source code is never uploaded. File paths and diff statistics are sent as metadata so the dashboard can show what changed; file contents are not.
- Access tokens are short-lived and rotate on every refresh.
Installing
npm is the primary path and works everywhere Node 20 or newer does.
npm i -g shipsureOn macOS and Linux there is also a Homebrew tap. It depends on node rather than bundling a runtime — anyone verifying a JavaScript project already has one, and embedding it would take a 140 kB download past 100 MB.
brew tap shipsure/shipsurebrew install shipsureWatching a run happen
A verification opens its run before the checks start, so the dashboard follows along live rather than showing nothing until the end. The run page streams over a WebSocket, falls back to polling where one cannot be opened, and shows each check as it lands.
A run that is still going can be stopped — from the run page, or with shipsure cancel, which with no argument stops whatever is currently in flight. A cancelled run records the verdict cancelled and exit code 4, so a pipeline can tell it apart from a failure. Runs whose machine never reports back are closed out automatically after six hours rather than sitting “running” for ever.
Flaky checks
ShipSure watches each check across a project’s recent history and flags one whose result keeps changing direction. A check that has simply failed twenty times running is broken, not flaky, and is deliberately not flagged — letting a real breakage hide behind the word is the failure this exists to prevent.
Quarantining a flagged check, under the project’s Flaky tab, records it as flaky rather than failed so it stops blocking every run while staying visible. If the only failing check in a run is a quarantined one, the run passes and says so in its reasons. Any other failure still fails the run.
Watch and rollback
shipsure watch verifies whenever the tree has been still for a few seconds. An agent edits, goes quiet, and the verdict is on screen before you think to ask. It never runs two verifications at once, and edits arriving mid-run queue exactly one more — not one per file.
shipsure watchshipsure watch --quiet-ms 5000shipsure rollback puts the tree back to the baseline after a bad run. It stashes your current state first with --include-untracked and prints how to get it back, so nothing is destroyed. It refuses if a commit has landed since the baseline — discarding a commit is a different and worse operation, and git revert is the right tool for that.
shipsure rollback --dry-runshipsure rollbackPrivate runners
For code that cannot leave hardware you control. Enrol a machine under Settings → Runners, then run it with the token you are given:
SHIPSURE_RUNNER_TOKEN=ssr_... shipsure runnerThe runner polls outward over HTTPS. Nothing connects to it, so there is no firewall exception and no route into your network to arrange. Each job gets a fresh clone that is deleted when the job ends, two runners can never claim the same job, and a runner killed mid-job releases its lease after fifteen minutes so the work requeues rather than vanishing.
It clones two commits deep and captures the baseline from the parent, so a run answers “did this commit break something that worked before it?” rather than just “do the checks pass right now”. On the first commit in a repository there is nothing to compare against and the verdict is inconclusive, which is the honest answer. The result uploads through the same endpoint every other client uses, so the server’s verdict cross-check applies to runner output exactly as it does to a laptop’s.
GitHub and Slack
Connect them under Settings → Integrations. GitHub posts a commit status — a green tick driven by the check results rather than by what the agent claimed — and optionally a pull-request comment. It needs a fine-grained token with Commit statuses: read and write, and nothing else.
Slack takes an incoming webhook URL and posts to that one channel. It defaults to failed and blocked runs only; posting on every green build is how a channel learns to ignore the bot.
Both credentials are checked against the provider before they are stored, and encrypted at rest. Neither is ever returned by the API after you save it.
API keys and webhooks
Create a key under Settings → API keys. Read keys can list projects and runs; write keys can also create them. Neither can touch members, other keys, or the audit trail.
curl https://api.shipsure.space/v1/runs -H "Authorization: Bearer ssk_..."Webhooks live under Settings → Webhooks. Every delivery carries X-ShipSure-Signature as v1=<hex>, an HMAC-SHA256 over timestamp.rawBody. Compare it in constant time and reject anything older than five minutes — the timestamp is inside the signature precisely so a captured request cannot be replayed later. Failed deliveries retry six times over about two hours, and twenty consecutive failures disables the endpoint rather than hammering a server that is clearly gone.
Your team
Invite people from Settings → Team. They receive a link that works once and expires in seven days, and joining puts them on a seat your plan already covers — an invited teammate does not need their own subscription or card.
A pending invitation holds a seat until it is accepted, revoked or expires, so the count on that page is what you are actually using. Revoking frees the seat immediately and the link stops working.
| Role | Can do |
|---|---|
| Owner | Everything, including billing and deleting the organization. |
| Admin | Projects, integrations, policies and members. Not billing. |
| Developer | Run verifications and read everything in the organization. |
| Viewer | Read-only access to runs, evidence and reports. |
An organization always has at least one owner: the last one cannot be demoted or removed. Ownership is transferred by promoting somebody else first — it is never handed out by invitation.
Signing in with GitHub
Where the deployment has it configured, the sign-in page offers GitHub. Two rules apply, and both are deliberate:
- It signs you in, it does not sign you up. There is no free tier, so an account cannot exist without a plan — an unrecognised identity goes to pricing rather than becoming a dead account.
- It never auto-links on a matching email. If the address already has a password account, you are asked to sign in and link it from Settings. Trusting a provider’s claim about an address is the classic account-takeover route.
Passwords and account recovery
Forgot yours? Use the reset link on the sign-in page. The email arrives in a moment, works once, and expires after an hour. Requesting a new link retires the previous one, so if somebody else triggered a reset on your account, asking for your own immediately kills theirs.
Completing a reset signs the account out on every device, including any CLI session — run shipsure login again on each machine afterwards. To change a password you still know, use Settings instead; that keeps the device you are on signed in and drops the rest.