A GitHub ↔ Forgejo translation proxy
Your tools speak GitHub. Your forge speaks Forgejo. Anvil stands between them and translates every blow — so gh, Renovate, and CI scripts work against your own Forgejo, unmodified.
Click anywhere — or press space — to strike
The strike ledger
These are real pairs from Anvil's mappings.toml — not a mockup. Strike again to forge the next one. Watch the method change on the merge.
What rings true
86% of the GitHub endpoints these tools actually hit are mapped — field renames, param renames, path reshuffles, even method changes — all verified against a real Forgejo instance.
List, read, patch, delete. Fields like homepage → website come back renamed and in GitHub's shape.
Create, comment, label, milestone — and merge. GitHub says PUT …/merge; Forgejo says POST. Anvil absorbs the difference.
The CI loop works end to end: report a status from your pipeline, read it from another.
per_page becomes limit, and Link headers are rewritten so clients keep following pages unaware.
Workflow runs, artifacts, secrets, variables — the automation surface, translated.
GET /search/repositories is re-routed to Forgejo's /repos/search — the path reshuffles, the client doesn't notice.
Read and write files — including GET …/readme, which Forgejo doesn't have and Anvil synthesizes from the contents API — plus releases, labels, milestones, webhooks, and collaborators.
The identity surface gh checks on startup — /user, user repos, org membership — answers in GitHub's dialect.
Straight talk
Anvil doesn't improvise. Anything Forgejo genuinely can't do comes back as the same 501 GitHub would send — so your tooling fails fast, loudly, and in a shape it understands. No silent wrong answers.
Under the anvil
Anvil is Shotgun — an OpenAPI-to-OpenAPI translation proxy — wearing a curated, hand-checked GitHub↔Forgejo configuration. The value is the mapping file, the one-command experience, and the testing against a real forge.
The heat gauge
75 of 87 endpoints mapped and verified live against Codeberg — not against fixtures. The rest have no Forgejo equivalent, and Anvil says so rather than guessing.
Quickstart
Clone both repos — Anvil builds its Shotgun engine on first run (needs Rust) — then point it at your instance.
git clone https://github.com/ThatXliner/shotgun shotgun
git clone https://github.com/ThatXliner/anvil anvil
cd anvil
./anvil.sh --forgejo-url https://git.example.com
Point any GitHub-speaking tool at the proxy. That's the whole integration.
# gh, against your own forge:
GH_HOST=127.0.0.1:3000 \
GH_TOKEN=<forgejo-token> \
gh repo list
The Dockerfile builds an image with the proxy and mappings baked in.
docker build -t anvil ..
docker run -p 3000:3000 \
-e FORGEJO_URL=https://git.example.com \
anvil
A note on gh: it insists on HTTPS, and Anvil speaks plain HTTP on localhost. Put any reverse proxy in front (Caddy, nginx, a Cloudflare Tunnel) — or use scripts/dev-tls-proxy.py for a self-signed cert locally. Tools that don't hardcode HTTPS, like curl, Renovate, and most CI scripts, work directly.