# How OpenClaude Handles the GitHub Dual-Mode Provider Exception

> Discover how OpenClaude manages the GitHub dual-mode provider exception by intelligently detecting environment variables and selecting the correct API endpoint for seamless integration.

- Repository: [Gitlawb/openclaude](https://github.com/Gitlawb/openclaude)
- Tags: internals
- Published: 2026-09-02

---

**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`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/providerAutoDetect.ts). This module scans available credentials and builds a preliminary `ProviderInfo` object without yet committing to a specific API route.

```typescript
// 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`](https://github.com/Gitlawb/openclaude/blob/main/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`](https://github.com/Gitlawb/openclaude/blob/main/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`](https://github.com/Gitlawb/openclaude/blob/main/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

```bash
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

```bash
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

```bash
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

```bash
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`](https://github.com/Gitlawb/openclaude/blob/main/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`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/providerAutoDetect.ts) identifies available credentials without committing to a route
- **Validation** in [`src/utils/providerValidation.ts`](https://github.com/Gitlawb/openclaude/blob/main/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`](https://github.com/Gitlawb/openclaude/blob/main/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`](https://github.com/Gitlawb/openclaude/blob/main/providerValidation.ts).