v1 is CLI-only and self-hosted: you run the service container on your own host
with your own GitHub App, model provider key and storage. Nothing is sent to
the authors of this tool (see privacy.md). GitHub.com public repositories
are the only supported forge target in v1; installation rejects anything else.
- Linux or macOS for the CLI (Windows via WSL only)
- An OCI runtime (Linux x86-64 or arm64) for the service, with outbound HTTPS
to
api.github.comand your model provider - A persistent volume for
/data(verdict log, queue state, artifacts) - Bun ≥ 1.3 to run the CLI from the source package
Create a GitHub App on your own account and install it on the target repository. Required permissions — and nothing more:
- Pull requests: read
- Issues (comments): write
- Labels: write
- Contents: none (the app never needs code write access, Actions secrets or organisation scopes)
Download the App private key to your host, e.g. /srv/triage/github-app.pem.
Create the volume and config:
$ mkdir -p /srv/triage/data
$ cat > /srv/triage/data/config.toml <<'EOF'
[service]
port = 8787
data_dir = "/data"
poll_interval_s = 60
[github]
repo = "you/your-repo" # GitHub.com only
app_id = "123456"
private_key_path = "/data/github-app.pem"
[model]
provider = "openai-compatible"
model_id = "your-model"
api_base = "https://api.your-provider.example/v1"
api_key_path = "/data/model-key.txt"
[reconcile]
manual_close = "treat-as-confirmed"
EOF
Secrets stay file-path references on your volume; they are never stored in the
database. Start the immutable version tag — no latest tag exists:
$ docker run -d --name corbits-triage \
-v /srv/triage/data:/data \
-p 127.0.0.1:8787:8787 \
corbits-triage:0.1.0
The admin API binds loopback only. When the CLI runs on a different machine than the container host, forward the port over SSH:
$ ssh -L 8787:127.0.0.1:8787 your-host
The service writes an admin token to the data volume on first start.
$ corbits-triage auth login --from /srv/triage/data/corbits-triage.token
Defaults: config ~/.config/corbits-triage/config.toml, token
~/.config/corbits-triage/corbits-triage.token, API http://127.0.0.1:8787.
$ corbits-triage elicit --cap 2h --corpus decisions.json # interview from past PR decisions
$ corbits-triage policy lint # exits 6 until findings are fixed
Commit policy.json where the service reads it (/data/policy.json): the
service must quote the exact clause text it enforces.
$ corbits-triage calibrate --holdback 60
$ corbits-triage injection run # exits 7 and prints RELEASE GATE: FAIL on any failure
Both are safety gates: do not enable live triage until calibration looks acceptable and the injection suite passes.
Bookmark the pending-label search (also shown by corbits-triage status):
https://github.com/you/your-repo/pulls?q=is%3Apr+is%3Aopen+label%3A%22triage%3A+unconfirmed+verdict%22
Polling intake then runs on its own: no public inbound socket is required.
Daily loop: status → pending → show <pr> → confirm <pr> or
withdraw <pr>.
Default: reconcile.manual_close = "treat-as-confirmed" — if you close a PR
by hand on GitHub while its verdict is unconfirmed, reconciliation treats your
close as confirmation: the existing comment is edited to the confirmed state,
the pending label is removed, the PR stays closed and the outcome is recorded
as confirmed_by_manual_close.
Alternate: manual_close = "leave-unconfirmed" records your hand close and
touches nothing public. Consequence: a closed PR can permanently retain a
public comment that still reads "This verdict is unconfirmed as of yet".
triage: unconfirmed verdict— awaiting your confirm/withdrawtriage: needs your read— routed to you (invalid judge output or provider failure)triage: passed— above bar, no public verdict
These names, the comment templates, clause ids, the verdict record schema and the export format are compatibility surfaces and will not change within a major version.
GPLv2 + AI-modifications exception: LICENSE.md, GPL-2.0.txt,
GPLv2-AI-Exception.md. The image and source package include these texts
and THIRD_PARTY_NOTICES.md.