# Forge support

jjpr auto-detects the forge from your remote URL and talks directly to
the forge's API. Neither `gh` nor `glab` is required, but
jjpr picks up their stored credentials when they're present.

| Forge | Token env var | CLI fallback |
|---|---|---|
| GitHub | `GITHUB_TOKEN` or `GH_TOKEN` | `gh auth login` (reads stored credentials) |
| GitLab | `GITLAB_TOKEN` | `glab auth login` (reads stored credentials) |
| Forgejo / Codeberg | `FORGEJO_TOKEN` | none |

Auto-detection recognizes `github.com`, `gitlab.com`, and
`codeberg.org`, plus Enterprise subdomains for GitHub and GitLab. For
self-hosted instances, set `forge` in `.jj/jjpr.toml`. See
[Repo-local config](configuration.md#repo-local-config).

## GitHub

If you already use `gh`, jjpr finds your credentials automatically.
Otherwise, export `GITHUB_TOKEN` (or `GH_TOKEN`) with at least `repo`
scope.

GitHub Enterprise is auto-detected from the host
(`*.github.enterprise.example.com`). Credentials come from `gh` if it's
configured for that host.

`status` reads a whole stack's PR state in one GraphQL query. If your
token cannot use GraphQL, jjpr asks per PR over REST instead and reports
the same thing, using more requests. A fine-grained token needs the
pull-requests permission read; organizations with SAML enforcement need
the token authorized for the org. Neither is required, and nothing needs
configuring either way.

GitHub's own stacked pull requests are a separate feature from jjpr's stacks,
and jjpr recognizes them rather than fighting them. A PR that belongs to a
native stack cannot be merged through the API jjpr uses, and its base cannot be
retargeted, so `status` flags it, `merge` and `watch` stop and name
`gh stack merge`, and `submit` refuses a reshape it cannot apply. Pushing,
creating PRs, and updating descriptions all work normally on a stacked PR. See
[GitHub native stacks](commands/merge.md#github-native-stacks).

This applies to GitHub only. GitLab and Forgejo have no equivalent feature, and
nothing in jjpr changes for them.

## GitLab

If you use `glab`, jjpr picks up your credentials. It asks glab for the
token of the host in your remote URL, so if you are logged in to more
than one GitLab instance, it uses the one the repo lives on. For a
self-hosted instance, log in with `glab auth login --hostname <host>`.
Otherwise, export `GITLAB_TOKEN` with `api` scope.

Self-hosted GitLab is auto-detected from the host. No extra config is
needed for gitlab.com or for any GitLab instance with a recognizable
URL pattern.

## Forgejo and Codeberg

Generate an API token with `repo` scope from your instance's settings.
For Codeberg, that's at
`https://codeberg.org/user/settings/applications`. Export it:

```
export FORGEJO_TOKEN=your_token_here
```

For self-hosted Forgejo, set the forge type in `.jj/jjpr.toml`:

```toml
forge = "forgejo"
```

Auto-detection only recognizes `codeberg.org`. Other Forgejo hosts
need the explicit `forge` setting.

## Verifying

```
jjpr auth test
```

Reports the detected forge, the token source, and the authenticated
user. See the [auth command](commands/auth.md) for details.
