Portable quality-gate orchestrator for developer tools
Project description
shipgate
You start a Python project and quickly realize you need a pile of tools — linters, formatters, type checkers, secret scanners — each with its own config, install story, and CI glue. Before you write much code, you are maintaining a toolchain.
ShipGate is here. One policy, one catalog, three commands:
shipgate install
shipgate format
shipgate check
What's in the name?
Ship — move code out the door quickly. Gate — nothing merges until it passes the checklist.
ShipGate is fast to set up and especially strong with AI agents: pair
shipgate with pre-commit so every commit (human or agent) hits the same
gates. No bad code skips the gate.
Quick start
1. Activate your environment
Use whatever virtualenv or project env you already prefer:
source .venv/bin/activate
# or: uv sync && source .venv/bin/activate
2. Install ShipGate from PyPI
pip install shipgate
# or: uv add --dev shipgate
Optional report UI extras: pip install 'shipgate[server]'.
Requires Python 3.11–3.14 (prefer 3.13 for the full suite; Semgrep does not support 3.14 yet).
3. Initialize project policy
shipgate init
# or: shipgate init pyproject
This scaffolds everything needed to run the gates: .shipgate/shipgate.yaml (or
[tool.shipgate]), plus .shipgate/configs/, .shipgate/catalog/,
.shipgate/gates/, and cache metadata.
4. Install suite tools
shipgate install
Downloads and wires the tools for your configured suite (env: managed keeps
them under .shipgate/tools/).
5. Hook up pre-commit (optional)
Add a local hook that runs ShipGate on commit, then install hooks:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: shipgate-format
name: shipgate format
entry: shipgate format --target .
language: system
pass_filenames: false
- id: shipgate-check
name: shipgate check
entry: shipgate check --target .
language: system
pass_filenames: false
pre-commit install
6. Run the report UI (optional)
pip install 'shipgate[server]'
shipgate serve --open
Browse suite runs and findings at http://127.0.0.1:8765/.
Check example
Report-only quality run (does not rewrite files). Success is silent; failures
exit 1, print findings, and write under .shipgate/reports/.
Error format is configurable. Set error-format in .shipgate/shipgate.yaml
(or [tool.shipgate]), or override per run with --error-format. Built-ins:
compact, text, log, json, and github (PR annotations).
shipgate check --check ruff.lint --target app.py --error-format compact
Example failure output (compact):
app.py:1: error: E401 Multiple imports on one line
app.py:1: error: I001 Import block is un-sorted or un-formatted
app.py:1: error: F401 `os` imported but unused
app.py:1: error: F401 `sys` imported but unused
app.py:3: error: E302 Expected 2 blank lines, found 1
app.py:3: error: E201 Whitespace after '('
app.py:3: error: E202 Whitespace before ')'
app.py:4: error: E111 Indentation is not a multiple of 4
app.py:4: error: F841 Local variable `unused` is assigned to but never used
app.py:5: error: E111 Indentation is not a multiple of 4
app.py:5: error: E201 Whitespace after '('
app.py:5: error: E202 Whitespace before ')'
app.py:6: error: E111 Indentation is not a multiple of 4
app.py:6: error: E226 Missing whitespace around arithmetic operator
Same findings as text:
shipgate check --check ruff.lint --target app.py --error-format text
[ruff.lint]
- [error] E401: Multiple imports on one line (app.py:1)
- [error] I001: Import block is un-sorted or un-formatted (app.py:1)
- [error] F401: `os` imported but unused (app.py:1)
- [error] F401: `sys` imported but unused (app.py:1)
- [error] E302: Expected 2 blank lines, found 1 (app.py:3)
- [error] E201: Whitespace after '(' (app.py:3)
- [error] E202: Whitespace before ')' (app.py:3)
- [error] E111: Indentation is not a multiple of 4 (app.py:4)
- [error] F841: Local variable `unused` is assigned to but never used (app.py:4)
- [error] E111: Indentation is not a multiple of 4 (app.py:5)
- [error] E201: Whitespace after '(' (app.py:5)
- [error] E202: Whitespace before ')' (app.py:5)
- [error] E111: Indentation is not a multiple of 4 (app.py:6)
- [error] E226: Missing whitespace around arithmetic operator (app.py:6)
shipgate check
shipgate check --suite security
shipgate check --target src
shipgate check --error-format github # CI / PR annotations
Format example
Apply formatters / autofix tools from the format suite (success is silent):
shipgate format --target .
When files need formatting, a report-only format check surfaces the drift:
shipgate check --check ruff.format --target app.py --error-format compact
ruff.format: error: TOOL_EXIT Would reformat: app.py
1 file would be reformatted
With --display-cli, ShipGate prints the tool command it runs:
shipgate format --check ruff.format --target . --display-cli
ruff.format: .shipgate/tools/python/bin/ruff format --config .shipgate/configs/ruff.toml .
Features
- Policy-first — suite, scopes, and thresholds in
.shipgate/or[tool.shipgate]; catalog metadata owns how each tool runs - Three verbs —
install,format(writes),check(report-only) - Suites — named checklists instead of hand-rolled CI scripts
- Quiet success — exit
0with no noise; structured failures otherwise - Managed tools — optional installs under
.shipgate/tools/ - Gitignore-aware path delivery
- Extensible project-local catalog entries and policy gates
- Report UI via
shipgate[server]
Docs
| Doc | Contents |
|---|---|
| Usage guide | Suites, config, error formats, CI, gates, tools |
| Architecture | Layers and design decisions |
| Check flow | Tool YAML → shipgate check |
Contributing
See the contributing guide. Maintainers: AGENTS.md.
License
See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shipgate-0.1.2.tar.gz.
File metadata
- Download URL: shipgate-0.1.2.tar.gz
- Upload date:
- Size: 122.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
772de4b0f227c857fa5cb816ab61298078506658b3f3cb49b6972ca2543d205e
|
|
| MD5 |
699ad2da5b66895c43656934fcd1d557
|
|
| BLAKE2b-256 |
64e2b6b8d5998bcae588b4578f6f447fadc82a0623286354908aec6dfe881035
|
File details
Details for the file shipgate-0.1.2-py3-none-any.whl.
File metadata
- Download URL: shipgate-0.1.2-py3-none-any.whl
- Upload date:
- Size: 203.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f79fb7cdc5527094a6ea7f3930043d8d30745e0bb85981a0931fff04ae52776
|
|
| MD5 |
59e8714082ebfd7892c1ad498346d0f7
|
|
| BLAKE2b-256 |
0815904ac51f2418563207a4195ae1ea2efec44cc9104edbc895b7d199ededc1
|