CI overview

Shipmoor Team
June 27, 2026
5 min read

In CI, Shipmoor is the same binary running the same scan it does on your laptop, installed onto your runner, scoped to the change, exiting with a stable code. CI uses shipmoor scan: one process, one scan, then exit. (The Agent Harness and the IDE’s language server are for the local dev loop, where they run continuously as you edit; CI wants a single deterministic pass instead.) No source is uploaded anywhere; the scan runs in your runner on your infrastructure, and the only thing handed to GitHub is the SARIF evidence you choose to upload.

What CI catches

A CI scan catches the generated-code failure modes a change introduces (phantom imports, hallucinated APIs, stub handlers that return success without doing the work) before they merge. It reports findings against the change, never against legacy code you didn’t touch. On a license, it can also carry Claim Check, which catches changes that did not earn their claim and says so when it has no probe to check a given expectation.

Everything on this page runs locally in your runner and works on any plan, including free.

Three decisions make a good Shipmoor CI gate, regardless of CI provider:

  1. Scope to the change. Scan the merge-base diff (--diff origin/main...HEAD with fetch-depth: 0), or use --changed for staged and unstaged work, so PRs are gated on what they introduce. See Gating & policy.
  2. Pick the threshold deliberately. --fail-on high is the sensible default: hallucinated dependencies block, debug output doesn’t.
  3. Emit evidence either way. Write SARIF (and a markdown summary) on every run, and upload it even when the gate fails the job; that’s what populates code scanning.
shipmoor scan --changed \
  --sarif --output shipmoor.sarif \
  --markdown-summary "$GITHUB_STEP_SUMMARY" \
  --fail-on high

Installation on a runner is the same one-liner as anywhere else (curl -fsSL https://dl.shipmoor.dev/install.sh | bash); the free Community scan needs no account or secret in CI. Verify the version on the runner with shipmoor version (current release: 0.5.1).

The gate: exit codes

The gate is the exit code. The most common CI mistake is treating 1 as a tooling failure; it isn’t. A 1 means the gate worked and a blocking finding got through your threshold.

shipmoor scan --changed --fail-on high
# exit 0 → pass
# exit 1 → a finding met the threshold (or the Claim Check gate blocked, if you opted in)
CodeMeaningCI handling
0Clean; nothing met the thresholdPass
1A blocking finding at the threshold (or the Claim Check gate, when opted in)The gate working. Fail the check; the SARIF/JSON is still complete. Upload it.
2Usage/config errorFix the invocation
3Scan failedReport as a tooling error

See Output formats & exit codes for the full contract.

Output formats

The same scan emits three shapes from the same evidence, so you can read it as a human and feed it to machines in one run:

  • Human: the default grouped, blockers-first console output.
  • scan.v1 JSON (--json): deterministic machine output for your own tooling.
  • SARIF (--sarif): feeds GitHub code scanning so findings land in the Security tab and annotate the PR diff.

Add --markdown-summary "$GITHUB_STEP_SUMMARY" to write a readable summary straight into the GitHub job summary, so reviewers see the verdict without opening the log. See GitHub Actions for the full workflow and SARIF & code scanning for getting findings into the Security tab.

GitHub Actions

Two ready-made options, a copy-paste workflow and a composite action, are covered in GitHub Actions. Any other CI (GitLab, Buildkite, Jenkins, a bare cron) follows the same pattern: install, scan the diff, act on the exit code, keep the SARIF/JSON as an artifact.

Claim Check in CI

On an IC plan, the same CI scan can carry the claim check: pass the task’s intent (--intent, or a .shipmoor/intent.txt your workflow writes) so Shipmoor checks whether the change did what it was asked to do.

By default Claim Check in CI is advisory: it reports the verdict and never changes your exit code. To let it block a merge, opt in with a verdict policy:

shipmoor scan --changed \
  --intent "Add a Stripe webhook handler for failed payments" \
  --verdict-policy .shipmoor/verdict-policy.yaml

Roll it out with --would-block first; that computes the gate as if enabled and prints what would have blocked while still exiting 0, so you can watch its footprint before you enforce. The full opt-in path, what can and cannot block, and the policy file live in Turning on the gate.

Not yet available: Team / server-side gates. Shared baselines, managed team policy, and server-side PR gates are planned for a Team tier built on this same local-first core. They are not released today. Everything on this page works now on any plan, including free.

Next

Last updated on June 27, 2026

Was this article helpful?

Your response is saved on this device.

Related Articles