Multi-Forgejo-Instance Support
The thfg CLI supports multiple Forgejo-compatible instances simultaneously. This guide explains the configuration model, host auto-detection from git remote, compatibility with public instances like Codeberg, and the architectural role of X-Forgejo-Host header routing through the proxy.
Configuration model
Section titled “Configuration model”thfg resolves the active host using the hosts array in ~/.config/thfg/config.json. Each entry is a HostEntry:
{ "hosts": [ { "name": "pikapods", "host": "https://pastoral-oyster.pikapod.net", "proxyUrl": "https://proxy.example.com", "token": "YOUR_TOKEN", "username": "your-username", "password": "your-password", "remotes": [ "git@pastoral-oyster.pikapod.net", "https://pastoral-oyster.pikapod.net" ] }, { "name": "codeberg", "host": "https://codeberg.org", "token": "YOUR_CODEBERG_TOKEN", "remotes": [ "git@codeberg.org", "https://codeberg.org" ] }, { "name": "work", "host": "https://git.mycompany.com", "proxyUrl": "https://forgejo-proxy.mycompany.com", "remotes": [ "git@git.mycompany.com", "https://git.mycompany.com" ] } ], "defaultOrg": "my-default-org"}HostEntry fields
Section titled “HostEntry fields”| Field | Required | Description |
|---|---|---|
name | yes | Unique identifier for this entry |
host | yes | Forgejo instance base URL (no trailing slash) |
proxyUrl | no | Forgejo API Proxy URL — enables proxy-only features |
token | no | Forgejo API token (prefer thfg auth login --token) |
username | no | WebUI username — required for project and log commands |
password | no | WebUI password — required for project and log commands |
remotes | no | Git remote URL prefixes for auto-detection |
Host auto-detection from git remote
Section titled “Host auto-detection from git remote”When you run thfg inside a git repository, the CLI calls git remote -v and matches each remote URL against the remotes prefixes in your hosts array. The first match wins.
# Working in ~/projects/forgejo-proxy (cloned from pastoral-oyster.pikapod.net)$ thfg issue list# → automatically resolves to the "pikapods" host entry
# Working in ~/projects/some-codeberg-repo (cloned from codeberg.org)$ thfg issue list# → automatically resolves to the "codeberg" host entryIf no remote matches any configured host, thfg falls back to the first entry in the hosts array and emits a warning to stderr. You can override host resolution by setting FORGEJO_HOST or by passing --repo owner/repo explicitly.
Remote URL matching rules
Section titled “Remote URL matching rules”- Matching is prefix-based:
"git@codeberg.org"matchesgit@codeberg.org:alice/myrepo.git - HTTPS and SSH remotes are handled separately; add both if you use both
- Shorter prefixes match more broadly; be specific to avoid false matches
Working with Codeberg
Section titled “Working with Codeberg”Codeberg runs Forgejo, so the standard Forgejo REST API is fully available. To configure a Codeberg host entry:
- Generate a Codeberg API token at https://codeberg.org/user/settings/applications
- Add a host entry:
{ "name": "codeberg", "host": "https://codeberg.org", "token": "YOUR_CODEBERG_TOKEN", "remotes": ["git@codeberg.org", "https://codeberg.org"]}- Run
thfg auth statusto verify the connection.
Most thfg commands work against Codeberg without any proxy. Commands that require proxyUrl (proxy-specific features) are listed in the next section.
Working with gitea.io and other self-hosted instances
Section titled “Working with gitea.io and other self-hosted instances”Any instance running Forgejo or Gitea is compatible. The API surface may differ slightly across versions; thfg targets the Forgejo 15.x API surface. Older or newer Gitea instances should work for most commands but may return errors on newer endpoints.
Feature availability per host type
Section titled “Feature availability per host type”| Feature | Direct Forgejo (no proxy) | With proxy (proxyUrl) |
|---|---|---|
thfg issue list/view/create/edit/close | ✅ | ✅ |
thfg repo list/view/create | ✅ | ✅ |
thfg pr list/view/merge | ✅ | ✅ |
thfg run list/view | ✅ | ✅ |
thfg run logs (streaming) | ❌ requires proxy | ✅ |
thfg project list --org | ❌ requires proxy | ✅ |
thfg project create/edit/close | ❌ requires proxy | ✅ |
thfg run diagnose | ❌ requires proxy | ✅ |
thfg issue list --me (cross-repo) | ✅ | ✅ |
thfg repo file get/list | ✅ | ✅ |
For commands marked requires proxy, the CLI routes the request through the proxy’s WebUI-backed endpoints which are not available in the standard Forgejo API.
X-Forgejo-Host header routing (advanced)
Section titled “X-Forgejo-Host header routing (advanced)”When the forgejo-proxy is configured with ALLOW_EXTERNAL_HOST_OVERRIDE=true, any request can carry an X-Forgejo-Host header to override which upstream Forgejo instance the proxy routes to. This allows a single proxy deployment to fan out to multiple upstream Forgejo hosts.
The proxy validates the header against an allowlist when ALLOW_EXTERNAL_HOST_OVERRIDE=true is set.
The CLI currently does not automatically add X-Forgejo-Host on all requests — it always uses the host in the matched HostEntry as the direct API target, and proxyUrl for proxy-specific commands. This is intentional: sending all traffic through a shared proxy is an opt-in scenario. Canonical alias calls such as thfg api /activitypub/actor follow the same rule: they only fan out through a shared proxy when you explicitly route them there.
To manually route a request through the proxy to a different upstream, add the header to thfg api:
thfg api /repos/myorg/myrepo \ --header "X-Forgejo-Host: https://other-forgejo.example.com"Or with curl:
curl -s -H "Authorization: token $TOKEN" \ -H "X-Forgejo-Host: https://other-forgejo.example.com" \ "$PROXY_URL/api/v1/repos/myorg/myrepo"Enabling external host override on the proxy
Section titled “Enabling external host override on the proxy”If you operate a shared proxy and want to allow callers to specify an upstream at request time, set:
ALLOW_EXTERNAL_HOST_OVERRIDE=trueSetting up quickly with thfg config
Section titled “Setting up quickly with thfg config”# Initialize a new configthfg config init
# Add a second host entrythfg config set hosts[1].name codebergthfg config set hosts[1].host https://codeberg.orgthfg config set hosts[1].token YOUR_TOKEN
# Verifythfg auth statusthfg doctorTroubleshooting
Section titled “Troubleshooting”thfg picks the wrong host
Make sure the remotes prefixes are specific enough and that your git remote URL matches exactly. Run git remote -v and compare with your config.
Commands that work on host A fail on host B
Check that both host entries have a valid token. For proxy-backed commands, verify that the proxyUrl is set on the correct entry and the proxy is reachable.
Authentication errors on Codeberg
Codeberg tokens are scoped — ensure your token has repository, issue, and user read/write scopes depending on which commands you use.
The shared proxy host is asleep before FastAPI starts The proxy cannot normalize provider HTML until the request reaches the app. Keep client-side retry logic in place for this case; the deferred availability gap is tracked in forgejo-proxy#18.