GitHub Enterprise Server (GHES) Setup

This guide walks you through configuring Gru to work with a GitHub Enterprise Server instance. If you're using github.com, see GETTING_STARTED.md instead.

Prerequisites

Complete the basic Getting Started prerequisites first (Rust, Claude Code). Then come back here for GHES-specific setup.

Step 1: Authenticate gh CLI with your GHES host

Gru delegates all GitHub API calls to the gh CLI, so you need gh authenticated against your GHES instance.

gh auth login --hostname github.netflix.com

Follow the prompts to authenticate. When asked about protocol, HTTPS is recommended for GHES.

Verify it worked:

gh auth status --hostname github.netflix.com

You should see output like:

github.netflix.com
  ✓ Logged in to github.netflix.com account yourname

Multi-host authentication

The gh CLI supports being logged into multiple hosts simultaneously. If you use both github.com and a GHES instance:

# Authenticate to both
gh auth login                                  # github.com
gh auth login --hostname github.netflix.com       # GHES

# Verify both
gh auth status

Gru sets GH_HOST on every gh CLI invocation, so the correct host is always targeted — you don't need to worry about which is the "default".

Token scope requirements

Your token needs the following scopes:

ScopeWhy
repoRead/write access to repositories, issues, and PRs
read:orgDiscover repos and check org membership

If you authenticate interactively with gh auth login, the default scopes are usually sufficient. If you're using a personal access token, make sure it includes the scopes above.

To verify your token's scopes without exposing the token value, use the GitHub API — the response headers include X-OAuth-Scopes:

gh api --hostname github.netflix.com /user --include 2>&1 | grep -i x-oauth-scopes

Alternatively, navigate to your GHES instance → Settings → Developer settings → Personal access tokens to view scopes in the UI.

Step 2: Configure ~/.gru/config.toml

Create or edit ~/.gru/config.toml and add a named host entry:

[github_hosts.netflix]
host = "github.netflix.com"

The name (netflix in this example) is your shorthand — you'll use it when referencing repos.

Optional: web_url

If the GHES web UI lives on a different domain than the API/git host (uncommon), set web_url. Note that host is a bare hostname while web_url is a full URL including scheme:

[github_hosts.netflix]
host = "github.netflix.com"
web_url = "https://github-web.netflix.com"

Most GHES installations don't need this.

Step 3: Reference repos using the named host

In your config's daemon.repos, reference GHES repos with the name:owner/repo format (this shorthand is for config files only, not CLI arguments):

[daemon]
repos = [
    "netflix:myteam/myapp",
    "netflix:myteam/mylib",
]

This tells Gru that myteam/myapp lives on the host defined in [github_hosts.netflix].

Repo format reference

FormatExampleResolves to
owner/repomyorg/appgithub.com/myorg/app
name:owner/reponetflix:myteam/myappUses [github_hosts.netflix]
host/owner/repogithub.netflix.com/org/svcLegacy — use name:owner/repo instead

The name:owner/repo format is recommended for GHES.

Step 4: Initialize and run

Initialize your GHES repo. If you're passing owner/repo explicitly, use --host:

gru init myteam/myapp --host github.netflix.com

Alternatively, if you run gru init from inside an already-cloned GHES repository, Gru can infer the host from the git remote automatically — no --host flag needed in that case.

Then use Gru normally:

# Work on a single issue (use the full URL for GHES issues)
gru do https://github.netflix.com/myteam/myapp/issues/42

# Or from within the worktree, just use the issue number
gru do 42

# Run lab mode to poll for gru:todo issues
gru lab

Full config example

Here's a complete config for a team using GHES with two repos:

[github_hosts.netflix]
host = "github.netflix.com"

[daemon]
repos = [
    "netflix:myteam/api-gateway",
    "netflix:myteam/web-ui",
]
poll_interval_secs = 60
max_slots = 4

[agent]
default = "claude"

[merge]
confidence_threshold = 9

See config.example.toml for all available options with explanations.

Troubleshooting

gh auth status fails for GHES host

github.netflix.com
  X Not logged in to github.netflix.com

Fix: Run gh auth login --hostname github.netflix.com and authenticate.

"Unknown host name" error

Unknown host name 'netflix' in repo 'netflix:myteam/myapp'.
Add a [github_hosts.netflix] section to config.toml

Fix: Add the missing host entry to ~/.gru/config.toml:

[github_hosts.netflix]
host = "github.netflix.com"

403 Forbidden on API calls

Your token likely lacks required scopes. Re-authenticate with appropriate scopes:

gh auth login --hostname github.netflix.com --scopes repo,read:org

Or generate a new personal access token in your GHES settings with the scopes listed in Step 1.

SSL/TLS certificate errors

If your GHES instance uses a self-signed or internal CA certificate, the most reliable fix is to add the certificate to your system trust store. The gh CLI uses Go's standard TLS stack, which defers to the OS trust store.

On macOS:

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /path/to/ca-cert.crt

On Linux (Debian/Ubuntu):

sudo cp /path/to/ca-cert.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

For git operations only (does not affect gh API calls):

git config --global http.https://github.netflix.com/.sslCAInfo /path/to/ca-bundle.crt

gru init hangs or times out

Check network connectivity to your GHES host:

gh api --hostname github.netflix.com /meta

If this fails, the issue is network-level (VPN, firewall, DNS).

Issue comments or labels not appearing

Verify your token has repo scope and that you have write access to the repository:

gh api --hostname github.netflix.com repos/myteam/myapp

If you get a 404, you either don't have access or the repo path is wrong.