Getting started with thfg
thfg is a gh-style command-line interface for Forgejo, designed to work with the
Forgejo API Proxy.
This guide walks you through installation, configuration, and your first commands.
Already installed? Jump to Common first commands or read the thfg vs thfg api vs curl decision guide to understand when to reach for each tool.
Installation
Section titled “Installation”1. Clone the repository
Section titled “1. Clone the repository”git clone https://pastoral-oyster.pikapod.net/forgejo-proxy/forgejo-proxy-cli.gitcd forgejo-proxy-cli2. Configure the private npm registry
Section titled “2. Configure the private npm registry”The CLI depends on @forgejo-proxy/sdk, published to a private registry protected by
Authelia. Obtain a read token from the team Bitwarden vault (entry:
npm.registry.hochguertel.work), then:
cp .npmrc.example .npmrc# Edit .npmrc — replace YOUR_TOKEN_HERE with your tokenYour .npmrc should look like:
@forgejo-proxy:registry=https://npm.registry.hochguertel.work///npm.registry.hochguertel.work/:_authToken=<your-token>3. Install and link
Section titled “3. Install and link”Option A — global install (recommended):
task cli:global:installThis builds the CLI and installs it globally so that thfg is available anywhere in
your terminal. This is the easiest approach for daily use.
Option B — manual link:
bun installcd packages/cli && bun linkVerify the install:
thfg --helpAuthentication
Section titled “Authentication”# Log in with a Forgejo API tokenthfg auth login --token <YOUR_FORGEJO_TOKEN>
# Also store WebUI credentials (needed for project and log commands)thfg auth login --username <your-username> --password <your-password>
# Check your auth statethfg auth statusConfig file format
Section titled “Config file format”The config is stored at ~/.config/thfg/config.json. The top-level key is hosts,
an array of HostEntry objects — one per Forgejo instance.
{ "hosts": [ { "name": "my-forgejo", "host": "https://forgejo.example.com", "proxyUrl": "https://forgejo-proxy.example.com", "token": "your-api-token", "username": "your-forgejo-username", "password": "your-forgejo-password", "remotes": [ "git@forgejo.example.com", "https://forgejo.example.com" ] } ], "defaultOrg": "my-org", "defaultRepo": "my-org/my-repo"}| Field | Required | Description |
|---|---|---|
name | yes | Unique identifier for this host entry |
host | yes | Forgejo instance base URL |
proxyUrl | no | Forgejo API Proxy URL — routes API calls through the proxy |
token | no | Forgejo API token (set via thfg auth login) |
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 used to auto-detect this host |
Multi-host setup
Section titled “Multi-host setup”Add multiple entries to hosts to work with more than one Forgejo instance. thfg
selects the active host by matching your git remote URL against the remotes
prefixes in each entry. When working outside a git repo, the first host in the array
is used as the default.
{ "hosts": [ { "name": "personal", "host": "https://forgejo.personal.example.com", "remotes": ["git@forgejo.personal.example.com"] }, { "name": "work", "host": "https://forgejo.work.example.com", "proxyUrl": "https://proxy.work.example.com", "remotes": ["git@forgejo.work.example.com", "https://forgejo.work.example.com"] } ]}Environment variable overrides
Section titled “Environment variable overrides”| Variable | Description |
|---|---|
FORGEJO_HOST | Override Forgejo host URL (creates a transient entry, never written to disk) |
FORGEJO_TOKEN / FORGEJO_API_TOKEN | Override the API token |
FORGEJO_PROXY_URL | Override the proxy URL |
FORGEJO_WEBUI_USERNAME | WebUI username — used when FORGEJO_HOST is active (CI/CD) |
FORGEJO_WEBUI_PASSWORD | WebUI password — used when FORGEJO_HOST is active (CI/CD) |
Common first commands
Section titled “Common first commands”# List repositories in your default orgthfg repo list
# List issues detected from the current git repothfg issue list
# Dispatch a workflowthfg workflow run deploy.yml --repo myorg/myrepo
# List workflow runs (newest first)thfg run list --repo myorg/myrepo
# List projects for an org (requires WebUI credentials)thfg project list --org myorg
# Show configthfg config list
# Output in JSON or YAMLthfg repo list --output-format jsonthfg run list --output-format yamlCommands overview
Section titled “Commands overview”Repositories
Section titled “Repositories”thfg repo listthfg repo view myorg/myrepothfg repo create my-new-repo --description "..." --privatethfg repo clone myorg/myrepoIssues & PRs
Section titled “Issues & PRs”thfg issue list --repo myorg/myrepo --state openthfg issue list --me # issues assigned to you across all reposthfg issue view 42 --repo myorg/myrepothfg pr list --repo myorg/myrepothfg pr merge 7 --repo myorg/myrepoFile browsing
Section titled “File browsing”# List files in a repository directorythfg repo file list myorg/myrepothfg repo file list myorg/myrepo --path src/
# Read a file's contents from a repositorythfg repo file get myorg/myrepo --path README.mdthfg repo file get myorg/myrepo --path src/main.py --ref v1.2.0 # specific branch/tag/commitWorkflows & runs
Section titled “Workflows & runs”thfg workflow list --repo myorg/myrepothfg workflow run deploy.yml --repo myorg/myrepothfg run list --repo myorg/myrepothfg run logs --repo myorg/myrepo --job failedthfg run watch 123 --repo myorg/myrepoSecrets & variables
Section titled “Secrets & variables”thfg secret list --repo myorg/myrepothfg secret set MY_SECRET=value --repo myorg/myrepothfg variable list --repo myorg/myrepothfg variable set MY_VAR=value --repo myorg/myrepoWhen thfg doesn’t have the command you need
Section titled “When thfg doesn’t have the command you need”Use the built-in escape hatch for endpoints under the normalized /api/v1 surface:
# Send an authenticated request to an /api/v1 endpointthfg api /repos/myorg/myrepo/topics
# PATCH with JSON fieldsthfg api /repos/myorg/myrepo --method PATCH --field description="New desc"
# Inspect the merged proxy contractthfg api specRoot-path exceptions stay separate:
# Health stays at the rootcurl "$FORGEJO_PROXY_URL/health"
# ActivityPub uses dedicated commandsthfg activitypub repo actor myorg/myrepoRead the full decision guide: thfg vs thfg api vs curl
If you are updating older scripts, follow Migrate to the normalized /api/v1 API surface.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
thfg: command not found | Run task cli:global:install from the repo root, or cd packages/cli && bun link |
401 Unauthorized | Check token with thfg auth status |
401 on project list | Add WebUI credentials: thfg auth login --username u --password p |
invalid repo format | Run from a git repo or set a default: thfg repo set-default owner/repo |
| Connection errors | Check proxyUrl in thfg config list |