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:

  1. Model name contains copilot-enterprise → Requires GITHUB_COPILOT_KEY
  2. Model name contains copilot → Accepts GITHUB_TOKEN or GH_TOKEN
  3. Other GitHub models → Accepts GITHUB_TOKEN or GH_TOKEN

The second key comment in src/utils/providerValidation.ts at line 445 establishes the enterprise key handling:

"GITHUB_COPILOT_KEY is 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-models profile entry with PAT configuration
  • github-copilot profile entry with optional enterprise key
  • github-copilot-enterprise profile 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.ts identifies available credentials without committing to a route
  • Validation in src/utils/providerValidation.ts enforces 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →