How OpenClaude Handles the GitHub Dual-Mode Provider Exception
OpenClaude handles GitHub's dual-mode route by detecting environment variables, selecting the appropriate API endpoint based on credential type, and validating that PATs work with GitHub Models but not the Copilot Enterprise API.
Implementing GitHub provider support presents a unique challenge: the same GITHUB_TOKEN can authenticate with two distinct services—GitHub Models for public model access and GitHub Copilot for code completion—while GitHub Copilot Enterprise requires a separate credential type. The OpenClaude codebase implements explicit branching logic to manage this provider exception cleanly.
Understanding GitHub's Dual-Mode Architecture
GitHub offers two primary AI provider pathways with incompatible authentication mechanisms:
| Provider | API Endpoint | Required Credential | Supported By |
|---|---|---|---|
| GitHub Models | https://api.github.com/v1/models |
Classic PAT (GITHUB_TOKEN) |
All GitHub users |
| GitHub Copilot | https://api.github.com/v1/copilot |
Same PAT or enterprise key | Copilot subscribers |
| GitHub Copilot Enterprise | Enterprise endpoint | GITHUB_COPILOT_KEY |
Enterprise customers |
This creates a three-way split where the same environment variable name behaves differently depending on the target service, requiring explicit route detection in OpenClaude's provider pipeline.
Phase 1: Environment Variable Auto-Detection
The entry point for GitHub provider handling resides in src/utils/providerAutoDetect.ts. This module scans available credentials and builds a preliminary ProviderInfo object without yet committing to a specific API route.
// src/utils/providerAutoDetect.ts
if (process.env.GITHUB_TOKEN) // GitHub Copilot (public) or GitHub Models
source = `${githubKey} set (GitHub Copilot)`;
else if (process.env.GH_TOKEN) // Alias for the same token
source = `${githubKey} set (GitHub Copilot)`;
else
source = undefined;
The auto-detector intentionally remains ambiguous at this stage—it identifies that some GitHub credential exists without determining which service to call. The actual routing decision happens downstream during validation.
Phase 2: Provider Validation and Dual-Mode Routing
The critical dual-mode logic executes in src/utils/providerValidation.ts. Two implementation comments explicitly define the exception handling behavior:
"PATs work with GitHub Models but not with the Copilot API"
This constraint means the validator must cross-reference the detected credential against the requested model type. The validation flow follows this branch logic:
- Model name contains
copilot-enterprise→ RequiresGITHUB_COPILOT_KEY - Model name contains
copilot→ AcceptsGITHUB_TOKENorGH_TOKEN - Other GitHub models → Accepts
GITHUB_TOKENorGH_TOKEN
The second key comment in src/utils/providerValidation.ts at line 445 establishes the enterprise key handling:
"
GITHUB_COPILOT_KEYis a direct API key for GitHub Copilot Enterprise"
When this environment variable is present, the validator bypasses the PAT compatibility check entirely and routes to the enterprise endpoint.
Phase 3: Error Handling for Mismatched Credentials
OpenClaude produces actionable error messages when users attempt incompatible combinations. The test suite in src/utils/providerValidation.test.ts documents the expected failure mode at lines 721-722:
GitHub Copilot Enterprise authentication required.
Run /onboard-github in the CLI to sign in with your GitHub account.
This error surfaces when a user supplies GITHUB_TOKEN (classic PAT) but requests a Copilot Enterprise model. The validation layer catches the mismatch before any network request occurs, preventing confusing API failures.
Practical Usage Examples
The following commands demonstrate correct dual-mode configuration:
GitHub Models with Classic PAT
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXX
openclaude chat --model github:gpt-4o-mini
The validator accepts this combination and routes to the GitHub Models endpoint.
Public GitHub Copilot with Same PAT
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXX
openclaude chat --model github:copilot
Despite using the same credential, the model name triggers Copilot routing rather than Models routing.
GitHub Copilot Enterprise with Enterprise Key
export GITHUB_COPILOT_KEY=gc_e_XXXXXXXXXXXXXXXX
openclaude chat --model github:copilot-enterprise
The presence of GITHUB_COPILOT_KEY overrides PAT detection entirely.
Failing Case: PAT with Enterprise Model
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXX
openclaude chat --model github:copilot-enterprise
# Error: GitHub Copilot Enterprise authentication required.
The validator rejects this combination and prompts for enterprise onboarding.
How Profile Persistence Handles Mode Switching
The src/utils/providerProfiles.test.ts file demonstrates that OpenClaude preserves explicit GitHub settings when users switch between modes. Profile definitions maintain distinct entries for:
github-modelsprofile entry with PAT configurationgithub-copilotprofile entry with optional enterprise keygithub-copilot-enterpriseprofile entry requiring enterprise key
This prevents credential leakage between modes and ensures that auto-detected defaults don't override intentionally configured enterprise settings.
Summary
OpenClaude's GitHub dual-mode exception handling operates through three coordinated layers:
- Auto-detection in
src/utils/providerAutoDetect.tsidentifies available credentials without committing to a route - Validation in
src/utils/providerValidation.tsenforces credential-model compatibility using explicit mode-specific rules - Error messaging provides clear remediation steps when incompatible combinations are detected
The architecture deliberately separates detection from routing decisions, allowing the same GITHUB_TOKEN value to serve multiple endpoints while preventing accidental misuse with enterprise features.
Frequently Asked Questions
What happens if I set both GITHUB_TOKEN and GITHUB_COPILOT_KEY?
OpenClaude prioritizes GITHUB_COPILOT_KEY when present, routing all Copilot-related requests to the enterprise endpoint. For GitHub Models requests, the system still uses GITHUB_TOKEN as the GITHUB_COPILOT_KEY is not valid for that service.
Can I use GH_TOKEN instead of GITHUB_TOKEN?
Yes. The auto-detector in src/utils/providerAutoDetect.ts treats GH_TOKEN as an alias for GITHUB_TOKEN and applies identical routing logic. Both variables trigger the same provider detection path.
Why does my PAT work with some GitHub models but not others?
GitHub Models (public model access) and GitHub Copilot (code completion) accept classic PATs, while GitHub Copilot Enterprise requires a separate enterprise key issued through organization settings. The validator explicitly checks model names for copilot-enterprise and rejects PAT-only authentication for those endpoints.
How do I migrate from personal Copilot to Enterprise Copilot in OpenClaude?
Set GITHUB_COPILOT_KEY with your enterprise key and either unset GITHUB_TOKEN or ensure your model selection includes the enterprise suffix. Run /onboard-github from the CLI if you encounter authentication errors, as recommended by the validation error handler in providerValidation.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →