Skip to main content
Glama

ShipPilot

Code generation is solved. The nine stages after it are not.

ShipPilot automates the post-code DevSecOps lifecycle — plan, create, verify, package, secure, release, configure, monitor, govern — with one autonomy dial that decides how much control you hand over.

Agents propose. The verifier decides what counts. The gate decides what ships.

Built for Life After Code (the GitLab Transcend Hackathon). Python standard library only — no SDKs, no API keys, no network calls. It runs the same in CI, on a laptop, and inside an air-gapped sandbox.


The dial

Level

What the human approves

What it means in the pipeline

assisted

every action

stops before every single write

supervised

the outcome

clears its own gates, stops once at the end

hands-off

nothing

states intent, walks away, ships if the verifier clears it

One dial, one set of checks. The inspectors never change — only who is in the loop. That is what makes autonomy auditable rather than a matter of taste.

A blocker is not negotiable at any level. hands-off will happily fix nineteen things on its own and still refuse to ship on the twentieth.

Related MCP server: GitHub Security Agent MCP

Quick start

python eval.py                                    # 245 assertions, offline
python -m shippilot audit --root .                # inspect, write nothing
python -m shippilot audit --root . --stage secure # one stage
python -m shippilot ship  --root . --autonomy supervised
python -m shippilot mcp                           # MCP server, stdio
python app.py                                     # web console (needs gradio)

audit exits 2 when blockers remain, 1 when a human decision is pending, 0 when the ship is clean. That makes it a CI gate rather than a report.

What it actually finds

Nine inspectors, each deterministic, each carrying the file and line it came from. Nothing is inferred; a finding without evidence is not emitted.

Stage

Sample rules

plan

PLAN_NO_SPEC, PLAN_THIN_ACCEPTANCE, PLAN_NO_ROLLBACK

create

CREATE_NO_MR_TEMPLATE, CREATE_TEMPLATE_MISSING_SECTION, CREATE_UNDOCUMENTED_CODE

verify

VERIFY_NO_TESTS, VERIFY_NO_COVERAGE_GATE, VERIFY_NO_CI

package

PACKAGE_UNPINNED_DEPS, PACKAGE_NO_SBOM, PACKAGE_NO_IMAGE

secure

SECURE_HARDCODED_SECRET, SECURE_DANGEROUS_CALL, SECURE_NO_POLICY

release

RELEASE_NO_CHANGELOG, RELEASE_NO_VERSION, RELEASE_BAD_VERSION

configure

CONFIGURE_ENV_DRIFT, CONFIGURE_NO_IAC

monitor

MONITOR_NO_HEALTHCHECK, MONITOR_NO_SLO, MONITOR_NO_TELEMETRY

govern

GOVERN_NO_LICENSE, GOVERN_NO_CODEOWNERS, GOVERN_NO_AUDIT_TRAIL

Prove-then-act

Every fix is applied by a deterministic fixer, then the inspector that flagged it is re-run. A fix counts as done only when the check stops flagging it. The receipt records applied and verified as separate numbers on purpose — a run that applied twenty fixes and verified nineteen tells you about the twentieth.

Some findings have no automatic fix. eval() inside application code is not something a pipeline should rewrite on its own, so ShipPilot writes a risk acceptance waiver to .shippilot/waivers.json naming the file, the rule and the reason, and moves on. Waiving one rule never waives another.

GitLab Duo Agent Platform

ShipPilot is wired into the platform three ways, all committed to the repo:

  • MCP client — .gitlab/duo/mcp.json registers the stdio server; Duo calls the seven tools directly (audit_repo, plan_lifecycle, apply_fix, ship_repo, carbon_report, render_receipt, list_lifecycle).

  • Flows — .gitlab/duo/flows/post_code_{assisted,supervised,hands_off}.yml, one per autonomy level, with tool_overrides pinning tool parameters so the model cannot drift from the contract.

  • Agent config — .gitlab/duo/agent-config.yml. The image is python:3.12-slim and the setup script is a print statement, because there is nothing to install.

The repository's own .gitlab-ci.yml has nine stages plus a shippilot-ship job, so the pipeline history the judges look at is the automation running.

Carbon

Every run measures wall-clock seconds per stage and converts them with the SCI formula (E × I) + M, then prices two concrete optimisations: skipping stages that came back clean, and running the dirty stages in parallel. Defaults are published public figures and every coefficient is overridable. See SUSTAINABILITY.md.

Receipts

.shippilot/audit/ gets a JSON receipt per run and a self-contained HTML page: nine stage tiles, the decision, before/after risk score, every action with its verification state, and the carbon numbers. No CDN, no fonts, no tracking — it opens from an artifact folder three weeks later.

Dogfooding

ShipPilot audits itself (shippilot-self-audit in CI). .shippilotignore exempts exactly one path: the deliberately broken fixture the demo and tests run against. Everything else is fair game.

Layout

shippilot/
  model.py         finding/receipt shapes, deterministic file walk
  stages.py        nine inspectors
  remedy.py        twenty deterministic fixers + risk waivers
  autonomy.py      the dial: assisted / supervised / hands-off
  orchestrator.py  PERCEIVE -> PLAN -> GATE -> ACT -> OBSERVE -> VERIFY -> RECEIPT
  carbon.py        SCI accounting
  mcp_server.py    MCP stdio (spec 2025-11-25), seven tools
  cli.py  receipt.py
app.py             Gradio console, also exposes /gradio_api/mcp/
examples/demo_repo a small repository with eighteen planted defects
eval.py            245 assertions
.gitlab/duo/       agent-config.yml, mcp.json, three flows

Tests

python eval.py

245 assertions, no network, no fixtures to download. Includes a real MCP subprocess session, real CLI subprocesses, a lying-fixture check (a clean repository must not trigger any of the nineteen rules), HTML injection escaping, and a rogue-input check for missing repositories.

Definition of done

A change to ShipPilot is shippable when:

  • python eval.py passes with zero failures

  • any new rule has both a positive case and a negative case in eval.py

  • any new fixer is proven by re-running the inspector that flagged it

  • a clean repository still triggers none of the nineteen rules

Rollback

Every release is a tag. Reverting a release is git revert plus a redeploy of the previous tag — receipts are append-only files, so no migration is ever required to roll back. A waiver in .shippilot/waivers.json can be removed on its own without touching code.

Licence

MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables policy-first defensive security operations for MCP, providing repository and web-security analysis with controlled authorization, scoped execution, and auditability.
    9
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Turns any AI coding agent or MCP client into a governed DevOps engineer by exposing policy-enforced tools for Kubernetes, Docker, Jira, Git/PR, CI/CD, AWS, Terraform, and incident response, with approvals, audit logging, secret redaction, and rollback enforced outside the model.
    35 PyPI
    6
    Apache 2.0