Go library and CLI for working with git forges. Supports GitHub, GitLab, Gitea/Forgejo, and Bitbucket Cloud through a single interface.
brew install git-pkgs/git-pkgs/forge
Or with Go:
go install github.com/git-pkgs/forge/cmd/forge@latest
The CLI detects which forge to use from your git remote, or you can set it with --forge-type.
forge repo view
forge issue list --state open
forge pr create --title "Fix bug" --head fix-branch
forge pr review approve 42
forge pr reviewer request 42 alice bob
forge release list
forge ci list
forge ci log 67890
forge branch list
forge label list
forge notification list --unread
forge notification read --id 123
forge api repos/{owner}/{repo}
Run forge --help for the full command list.
Store tokens with forge auth login:
forge auth login # interactive: asks domain + token
forge auth login --domain github.com --token ghp_abc123
forge auth login --domain gitea.example.com --token abc123 --type gitea
Check what's configured with forge auth status.
Tokens are resolved in this order: CLI flags, environment variables (FORGE_TOKEN, GITHUB_TOKEN/GH_TOKEN, GITLAB_TOKEN, GITEA_TOKEN, BITBUCKET_TOKEN), then the config file at ~/.config/forge/config.
Two config files, both INI-style:
~/.config/forge/config stores tokens and user preferences (respects XDG_CONFIG_HOME):
[default]
output = json
[github.com]
token = ghp_abc123
[gitea.example.com]
type = gitea
token = abc123.forge in the repo root is for per-project settings, committed to the repo, no tokens:
[default]
forge-type = gitlab
[gitlab.internal.dev]
type = gitlabThis tells forge that the project uses GitLab and that gitlab.internal.dev is a GitLab instance, so contributors don't each need --forge-type or FORGE_HOST.
Precedence from highest to lowest: CLI flags, environment variables, .forge, ~/.config/forge/config, built-in defaults.
import "github.com/git-pkgs/forge"client := forges.NewClient(
forges.WithToken("github.com", os.Getenv("GITHUB_TOKEN")),
forges.WithToken("gitlab.com", os.Getenv("GITLAB_TOKEN")),
)
repo, err := client.FetchRepository(ctx, "https://github.com/octocat/hello-world")The Forge interface exposes services for repos, issues, pull requests, reviews, releases, CI, branches, labels, milestones, deploy keys, secrets, and notifications. Each backend implements these using its native SDK.
f, _ := client.ForgeFor("github.com")
issues, _ := f.Issues().List(ctx, "octocat", "hello-world", forges.ListIssueOpts{State: "open"})
pr, _ := f.PullRequests().Get(ctx, "octocat", "hello-world", 42)Self-hosted instances can be registered explicitly or detected automatically:
import (
"github.com/git-pkgs/forge/gitea"
"github.com/git-pkgs/forge/gitlab"
)
client := forges.NewClient(
forges.WithForge("gitea.example.com", gitea.New("https://gitea.example.com", token, nil)),
forges.WithForge("gitlab.internal.dev", gitlab.New("https://gitlab.internal.dev", token, nil)),
)
// or auto-detect the forge type
err := client.RegisterDomain(ctx, "git.example.com", token, forges.ForgeBuilders{
GitHub: github.NewWithBase,
GitLab: gitlab.New,
Gitea: gitea.New,
})PURL support via github.com/git-pkgs/purl:
p, _ := purl.Parse("pkg:npm/lodash?repository_url=https://github.com/lodash/lodash")
repo, err := client.FetchRepositoryFromPURL(ctx, p)