magpie
Self-hosted GitHub code-review bot — any organisation can stand up its own instance on its own Linux host (single-host, single-tenant per deployment; see the platform matrix below).
Supported platforms
| Requirement | Detail |
|---|---|
| OS | Any Linux host with systemd |
| Container runtime | Rootless Podman (default; any docker-compatible CLI works) — runs the reviewer at the hardened crun floor tier by default, with an opt-in micro-VM (KVM) tier for stronger isolation; see ARCHITECTURE.md |
| Architecture | amd64 and arm64 |
| Ingress | Pluggable — reverse proxy, Cloudflare Tunnel, or another outbound tunnel; see docs/ingress.md |
New to Magpie? Start with QUICKSTART.md for the end-to-end install, or INSTALL.md for install-script details.
Prerequisites
- Node.js 22+ and npm
- Podman — the review agent runs in a container/micro-VM launched by rootless Podman:
no root daemon, no
docker/root group membership needed, just themagpieuser's own subuid/subgid ranges and a lingering session (seeINSTALL.md). Any docker-compatible CLI can be substituted viaconfig.toml'scontainer.docker_bin. The isolation tier actually launching reviews (hardened crun floor by default, or an opt-in micro-VM) is resolved at startup — see ARCHITECTURE.md's isolation-tier ladder. - git
Setup
npm install
npm run build
To run the unit tests across all workspaces:
npm test
Configuration
Non-secret settings live in config.toml at the repo root — copy
config.example.toml to config.toml and fill it in.
Secrets are read from the environment. Copy
.env.example to .env (also git-ignored) and set:
MAGPIE_WEBHOOK_SECRET— the GitHub App webhook secretMAGPIE_GATEWAY_MASTER_KEY— bearer token authenticating this orchestrator to the LLM gateway's (packages/gateway) management plane when minting/revoking each job's short-lived virtual key. There is no separate LLM provider API key here — the real key lives only in the gateway process's own environment; seepackages/gateway/README.md.
The GitHub App private key stays a .pem file on disk; point
github.private_key_path in config.toml at it (don't put it in .env).
The dev and start scripts load .env automatically via Node's built-in
--env-file-if-exists, so no dotenv dependency is required and the file is
optional — in production, supply these vars via a systemd EnvironmentFile=
instead.
An individual allowlisted repo can additionally tune a small, pre-approved
slice of review behaviour (model, diff-size cap, reviewer guidance, ignored
paths) by committing a .magpie.toml file to its own default branch — see
docs/repo-config.md.
Usage
Magpie will review PRs when opened, ready_for_review, reopened, synchronize. You can also request a fresh review at any time by commenting
@magpie review on a PR.
Running
npm run dev # run the orchestrator directly from TypeScript source (tsx)
npm run start # run the compiled output (after `npm run build`)
Both scripts boot the full pipeline (packages/orchestrator/src/index.ts): a webhook server
(server.ts) verifies and forwards pull_request deliveries through the repo-allowlist/event
filter (filter.ts) into an in-process job queue (queue.ts), which runs each accepted PR
through the review pipeline (pipeline.ts) — mint a GitHub App installation token, clone the
PR head credential-free (workspace.ts), fetch the diff (diff.ts), mint a per-job gateway
virtual key (gateway.ts), run the Pi reviewer (reviewer.ts) at the isolation tier resolved
for this host — the hardened, --network none, rootless-Podman crun floor by default, or an
opt-in micro-VM tier where configured (see ARCHITECTURE.md's isolation-tier ladder) — parse its
structured report_findings output (findings.ts,
anchor.ts), and publish exactly one COMMENT review with diff-anchored inline comments back
to the PR (publisher.ts) — incremental and deduped on re-push (rereview.ts). The process
shuts down gracefully on SIGINT/SIGTERM. Running from source this way still requires the
gateway (packages/gateway) to be up and the reviewer image available; for a production
install use the release tarball instead (see QUICKSTART.md /
INSTALL.md).
Reproducing an end-to-end review
- Configure
.env(MAGPIE_WEBHOOK_SECRET,MAGPIE_GATEWAY_MASTER_KEY) andconfig.toml(add the test repo torepo_allowlist) as described above, and startpackages/gateway(see its README) with the real provider key. - Expose the webhook endpoint and point the GitHub App's webhook URL at it, using
whichever ingress you run: a dashboard-managed Cloudflare Tunnel for the real/production
path (see docs/ingress.md) or a smee.io channel for local dev
(set
MAGPIE_SMEE_URLin.env; see docs/smee.md). - Start the orchestrator with
npm run dev. For the smee path, also runnpm run dev:smeein a second shell; a Cloudflare Tunnel needs no local relay process. - Open a non-draft pull request on the allowlisted repo (or push a commit to an existing one).
- Magpie mints an installation token, clones the PR head, mints a per-job gateway virtual
key, runs the reviewer with no network egress path at whichever isolation tier this host
resolved (the hardened crun floor's
--network nonecontainer by default), and posts one## 🐦 Magpie review(COMMENT-type) review — with diff-anchored inline comments — on the PR.
Webhook ingress (production)
For exposing the orchestrator's webhook endpoint to GitHub via an outbound-only, dashboard-managed Cloudflare Tunnel (no inbound ports, no ingress config committed to this repo), see docs/ingress.md.