# Copilot Byok

> Configure and switch between BYOK (Bring Your Own Key) LLM providers for both GitHub Copilot CLI and VS Code Chat. Use when setting up OpenAI, Azure OpenAI, Anthropic, Ollama, Moonshot, OpenCode Go, OpenRouter, or other OpenAI-compatible endpoints; creating or switching reusable provider profiles for CLI; switching between multiple accounts (API keys) for the same provider; configuring chatLanguageModels.json for VS Code; calculating max prompt or output token overrides; configuring wire API and reasoning effort; or troubleshooting COPILOT_PROVIDER_BASE_URL, COPILOT_PROVIDER_TYPE, COPILOT_PROVIDER_API_KEY, COPILOT_MODEL, COPILOT_PROVIDER_WIRE_API, COPILOT_PROVIDER_MAX_PROMPT_TOKENS, COPILOT_PROVIDER_MAX_OUTPUT_TOKENS, COPILOT_OFFLINE, and VS Code language model settings.

- Skill: `arisng/copilot-byok` (Agent Skill, multi-file: 22 files)
- Install (CLI): `npx skillmds@latest add arisng/copilot-byok`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arisng/copilot-byok/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: arisng (https://skillmd.com/u/arisng)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arisng/copilot-byok

---


# Copilot BYOK Provider Configuration

Use this skill to configure BYOK (Bring Your Own Key) LLM providers for **both GitHub Copilot CLI and VS Code Chat**. Manage repeatable CLI provider profiles and VS Code `chatLanguageModels.json` from a single source of truth.

## Follow this workflow

1. Determine the **provider** (OpenCode Go, OpenRouter, …) and the **harness** (Copilot CLI or VS Code Chat) the user needs.
2. Read the reference file that matches the current need:
   - Provider-specific content is grouped by LLM provider under `references/provider/<provider>/` (each provider has harness-specific files).
   - Universal/shared mechanisms (env vars, API-key storage, VS Code file rules, reasoning-effort lookup, CLI account switching) live under `references/shared/`.
3. For CLI, prefer `scripts/byok-profile.ps1` for repeated use or quick switching between providers.
4. For VS Code, use the **Chat: Manage Language Models** UI command (see the provider's `vs-code.md`).
5. Keep secrets out of files. Prefer `${ENV_VAR}` placeholders and user-scoped environment variables.

## Choose the path

### Provider + harness matrix

Read the provider file first, then the harness file:

| Provider | Copilot CLI | VS Code Chat |
|----------|-------------|--------------|
| OpenCode Go | [`references/provider/opencode-go/cli.md`](references/provider/opencode-go/cli.md) | [`references/provider/opencode-go/vs-code.md`](references/provider/opencode-go/vs-code.md) |
| OpenRouter | [`references/provider/openrouter/cli.md`](references/provider/openrouter/cli.md) | [`references/provider/openrouter/vs-code.md`](references/provider/openrouter/vs-code.md) |

### Shared references (any provider, any harness)

- **Env-var semantics / provider types / wire-format rules**: `references/shared/environment-variables.md` — read for manual one-off CLI setup or token-limit sizing.
- **API key storage or rotation**: `references/shared/api-key-storage.md`.
- **`chatLanguageModels.json` mechanism** (secret storage, per-agent model pinning, quick start, troubleshooting): `references/shared/chat-language-models-json.md` — read for VS Code BYOK setup.
- **Reasoning-level configuration**: read the grounded per-model lookup `references/shared/reasoning-effort-lookup.md`, then apply `--reasoning-effort` per invocation. Cross-surface mapping (CLI flag ↔ env var ↔ SDK API ↔ VS Code) lives in the `copilot-cli-subsession` skill's [`copilot-sdk-parity-matrix.md`](../copilot-cli-subsession/references/copilot-sdk-parity-matrix.md).
- **Multiple accounts for one provider (CLI)**: `references/shared/copilot-cli-accounts.md`.

> VS Code uses `chatLanguageModels.json` and **ignores** `COPILOT_PROVIDER_*` env vars.

### Other scenarios

- **New provider not yet documented**: create `references/provider/<provider>/` with `cli.md` + `vs-code.md` (mirroring `opencode-go/`), reuse `references/shared/*`, and register it in the matrix above. Keep the provider's model/reasoning-effort rows in the provider file, not in `shared/reasoning-effort-lookup.md`.

## Use the profile manager first

Use `scripts/byok-profile.ps1` when the user wants repeatable setup, named profiles, or quick switching.

Run the following commands from the installed `copilot-byok` skill folder (the folder that contains this `SKILL.md`).

Common commands:

```powershell
# List profiles
.\scripts\byok-profile.ps1 list

# Add a profile interactively
.\scripts\byok-profile.ps1 add

# Inspect a stored profile
.\scripts\byok-profile.ps1 show openai

# Run Copilot CLI with a profile for one session
.\scripts\byok-profile.ps1 run ollama

# Apply a profile to the current shell
. .\scripts\byok-profile.ps1 set-env openai
```

Pass extra Copilot CLI arguments through `run` (do not pass `--model`; model is sourced from the profile):

```powershell
.\scripts\byok-profile.ps1 run openai --help
```

Profiles are stored in `~/.copilot/byok-profiles.json` or `$env:COPILOT_HOME\byok-profiles.json`.

## Switch between multiple provider accounts

When you have multiple subscriptions for the same provider (for example, **two OpenCode Zen accounts** with separate API keys), register the accounts once and switch per session — no profile edits needed.

### 1. Register accounts in `~/.copilot/byok-profiles.json`

```json
{
  "accounts": {
    "opencode-home": { "keyEnv": "OPENCODE_API_KEY_HOME", "label": "OpenCode Zen (Home)" },
    "opencode-work": { "keyEnv": "OPENCODE_API_KEY_WORK", "label": "OpenCode Zen (Work)" }
  },
  "activeAccount": "opencode-home"
}
```

`keyEnv` holds the **name** of an environment variable with that account's key — never the raw key. `activeAccount` sets the default.

### 2. Opt profiles in with `accountGroup`

Add `"accountGroup": "opencode"` to each profile that should use the registry (the `add` wizard sets it automatically for the OpenCode Go preset). Profiles without `accountGroup` never participate.

### 3. Manage and switch accounts

```powershell
.\scripts\byok-profile.ps1 accounts
.\scripts\byok-profile.ps1 use opencode-work
.\scripts\byok-profile.ps1 run opencode-go-deepseek-v4-flash
.\scripts\byok-profile.ps1 run opencode-go-deepseek-v4-flash --account opencode-work
```

Resolution order: `--account` flag → profile `account` pin → `activeAccount`. If nothing resolves, the profile falls back to its legacy `apiKey` with a warning. For sub-sessions, pass `-ByokAccount opencode-work` to `Invoke-CopilotCliSubSession.ps1`.

### 4. Add the second account in VS Code Chat

VS Code ignores the CLI `accounts` registry — each account is a **separate provider entry** with its own key in secret storage. To add the second account:

1. **Chat: Manage Language Models → Add Models → Custom Endpoint**, name it `OpenCode Go (Work, OpenAI)`, paste the work key, API Type *Chat Completions*. This stores the key and writes a `${input:chat.lm.secret.*}` reference.
2. Run the helper from the skill's `scripts/` folder — it renames the existing `OpenCode Go (OpenAI|Responses|Anthropic)` providers to `(Home, …)` and clones them as `(Work, …)` using the new secret reference:

```powershell
.\scripts\opencode-vscode-add-work-account.ps1
```

3. Reload the window (**Developer: Reload Window**); both accounts appear in the model picker.

See `references/provider/opencode-go/vs-code.md` for the full manual table when you need more than two accounts, and `references/shared/copilot-cli-accounts.md` for the CLI registry semantics.

## Reference index

References are grouped by **provider** (under `references/provider/`) and by **universal/shared aspects** (under `references/shared/`).

- `references/provider/opencode-go/cli.md`
  - Read when configuring **OpenCode Go** for **Copilot CLI**: prerequisites and keys, base URL + endpoint per family, available-models table with reasoning-effort support, manual env-var examples, GPT-5.6 Luna wire-format matrix + grounded token overrides, profile-based setup.
- `references/provider/opencode-go/vs-code.md`
  - Read when configuring **OpenCode Go** for **VS Code Chat** (`chatLanguageModels.json`): full provider JSON per model family (chat-completions / responses / messages), multiple OpenCode Zen accounts (Home/Work) incl. the `opencode-vscode-add-work-account.ps1` helper.
- `references/provider/openrouter/cli.md`
  - Read when configuring **OpenRouter** for **Copilot CLI**. Covers environment variables, `:floor` / `:nitro` routing suffixes, CLI profile, manual env-var setup, and the empirical per-model audit.
- `references/provider/openrouter/vs-code.md`
  - Read when configuring **OpenRouter** for **VS Code Chat** (`chatLanguageModels.json`). Covers the UI quick-add path and the ready-to-use provider JSON.
- `references/provider/openrouter/README.md`
  - OpenRouter provider index: harness router + key provider facts.
- `references/shared/environment-variables.md`
  - Read when you need CLI env-var semantics, provider types, wire-format rules, model requirements, token-override calculation, or offline-mode notes (any provider).
- `references/shared/api-key-storage.md`
  - Read when the user needs secure key storage, persistent Windows environment variables, key rotation, or `${ENV_VAR}` placeholder guidance.
- `references/shared/chat-language-models-json.md`
  - Read when the user wants to configure BYOK models in **VS Code Chat**. Covers the config file, secret storage, shared model-configuration rules, per-agent model pinning via `.agent.md` frontmatter, agent-specific model settings, quick start, and troubleshooting.
- `references/shared/reasoning-effort-lookup.md`
  - Read when you need the per-model `--reasoning-effort` support lookup and verification workflow (the authoritative source that `copilot-cli-subsession` defers to).
- `references/shared/copilot-cli-accounts.md`
  - Read when the user holds multiple accounts for the same provider (CLI registry, `accounts`/`use`/`--account`, resolution order).
- `references/provider/opencode-go/README.md`
  - Provider index: harness router + key provider facts + usage limits.

## Apply these operating rules

- Prefer `${ENV_VAR}` placeholders over raw API keys in JSON.
- Treat `openai` as the default provider type for OpenAI-compatible endpoints such as Ollama, vLLM, Foundry Local, and Moonshot.
- Set `COPILOT_PROVIDER_TYPE=azure` only for Azure OpenAI and `anthropic` only for Anthropic.
- **OpenCode Go** serves all models from the single base URL `https://opencode.ai/zen/go/v1`. Live probe (2026-08-03, CLI 1.0.77): DeepSeek, GLM, Kimi, MiMo, **Qwen3.x and MiniMax all work via `COPILOT_PROVIDER_TYPE=openai` (chat/completions)** — the `anthropic` path is not required. `gpt-5.6-luna` also responds via chat/completions, so the documented "Responses-API only" constraint no longer holds for this gateway (both wire formats work). Store the personal OpenCode key as `OPENCODE_API_KEY_HOME` and the work key as `OPENCODE_API_KEY_WORK` — both at **User scope** (never Machine scope).
- **CRITICAL: `COPILOT_MODEL` must use the bare model ID** (e.g., `deepseek-v4-flash`), **not** the `opencode-go/` prefix. The prefix is only used in OpenCode TUI config and in Copilot CLI profile names — never in `COPILOT_MODEL`.
- For GPT-5 class OpenAI models, prefer `COPILOT_PROVIDER_WIRE_API=responses`. On OpenCode Go both `completions` and `responses` work for `gpt-5.6-luna` (probe 2026-08-03); `responses` remains the recommended default for GPT-5-class.
- Use `COPILOT_OFFLINE=true` only when the user explicitly wants Copilot CLI isolated from GitHub services; note that full isolation still depends on the provider endpoint being local or private.
- If the model is not in Copilot CLI's built-in catalog, set explicit prompt and output token overrides instead of assuming Copilot will infer them correctly.
- **Profile `proxyPort` field**: For Kimi models from `https://api.moonshot.ai` (which require `top_p=0.95`), add `"proxyPort": 443` to the profile and the `run` command will auto-start the local proxy and route through `https://moonshot.local/v1`. The proxy strips `top_p` to `0.95` before forwarding to Moonshot.

## Configure reasoning effort correctly

Use Copilot CLI's `--reasoning-effort` option for model reasoning level control. The authoritative per-model lookup — which levels a specific model supports and the recommended default — is `references/shared/reasoning-effort-lookup.md` (OpenCode Go focus; method applies to any BYOK model).

- Supported levels: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` (per-model subset may vary — e.g., DeepSeek V4 models on OpenCode Go only support `low`, `medium`, `high`; `minimal` is newer, verified in CLI 1.0.77).
- Apply it per run, for example:

```powershell
.\scripts\byok-profile.ps1 run dprocess-openai-gpt-54 --reasoning-effort medium
```

For OpenAI models, you may also enable summaries:

```powershell
.\scripts\byok-profile.ps1 run dprocess-openai-gpt-54 --reasoning-effort high --enable-reasoning-summaries
```

### Model compatibility warning

Not all models support Copilot CLI's `--reasoning-effort` levels. If you get:

```
Model "glm-5.2" does not support reasoning effort configuration (requested: "high").
```

it means the model's API does not expose controllable reasoning effort levels. Known families **without** reasoning-effort support:

- **GLM** (`glm-5`, `glm-5.1`, `glm-5.2`) — Zhipu AI / OpenCode Go (no controllable levels)
- **GLM-5.3-Flash** (`glm-5.3-flash`) — Zhipu AI / OpenCode Go (thinking always-on, defaults to `max`; model supports `low`/`high`/`max` but gateway may not expose)
- **MiMo** (`mimo-v2.5`, `mimo-v2.5-pro`, `mimo-v2-pro`, `mimo-v2-omni`) — Xiaomi / OpenCode Go
- **Kimi K2.x** (`kimi-k2.7-code`, `kimi-k2.6`, `kimi-k2.5`) — Moonshot AI / OpenCode Go (thinking is implicit / always-on)
- **Qwen3.x** (`qwen3.7-plus`, `qwen3.7-max`, `qwen3.6-plus`, `qwen3.5-plus`) — Alibaba / OpenCode Go (implicit thinking; `anthropic` type per OpenCode Go docs)
- **Qwen3.8-Flash** (`qwen3.8-flash`) — Alibaba / OpenCode Go (`anthropic` type; may support reasoning effort `low`/`medium`/`high`/`xhigh` — verify on gateway)
- **MiniMax** (`minimax-m3`, `minimax-m2.7`, `minimax-m2.5`) — MiniMax / OpenCode Go (implicit thinking; `openai` type per 2026-08-03 probe)

When using these models, omit `--reasoning-effort` entirely. The model will use its built-in default reasoning behavior.

To check whether a model supports it, try `--reasoning-effort none` (the least demanding level). If that also fails, the model simply doesn't support the feature.

The profile system tracks this per model. Profiles for models that do not support reasoning effort set `"reasoningEffortSupported": false`. The `run` command detects incompatible `--reasoning-effort`/`--effort` arguments, **strips them before forwarding to Copilot CLI**, and displays a clear notice. This prevents the API error. Support is derived from the shared no-support model list when the profile flag is absent (hand-added profiles), so `run`/`set-env`/`show` and `Invoke-CopilotCliSubSession.ps1` stay consistent.

Do not claim a dedicated `COPILOT_*` environment variable exists for reasoning effort unless `copilot help environment` in the user's installed CLI version explicitly lists one.

## Grounding and evidence standard

When answering questions in this domain, always separate grounded facts from inference:

1. Cite authoritative evidence used (for example, `copilot --help`, `copilot help environment`, provider model docs).
2. State what is directly evidenced versus inferred operational guidance.
3. End with an explicit conclusion:
  - `Grounding status: evidence-backed` when all key claims are directly supported.
  - `Grounding status: mixed (evidence + inference)` when any recommendation is inferred.

Do not present inferred workarounds (for example wrapper aliases for sticky defaults) as first-class documented product features.

## Calculate token overrides conservatively

When the user asks for `COPILOT_PROVIDER_MAX_PROMPT_TOKENS` or `COPILOT_PROVIDER_MAX_OUTPUT_TOKENS`:

1. Get the model's documented context window.
2. Pick a realistic max output budget for the workload.
3. Reserve a safety buffer for tool calls, system instructions, and multi-turn variance.
4. Compute:

`maxPromptTokens = contextWindow - plannedMaxOutput - safetyBuffer`

Prefer stable values over theoretical maximums. If the user reports context-limit failures, reduce prompt tokens by 5-10% and retry.

### Provider-enforced limits vs theoretical context windows

Some gateway providers (notably **OpenCode Go**) enforce per-request token limits **lower than the model's theoretical context window**. The native DeepSeek V4 Flash model supports 1M context, but OpenCode Go's gateway enforces an effective limit around ~300K for prompt tokens. Using the theoretical 1M to calculate maxPromptTokens (840K) will cause compaction failures with `400 Error from provider (Console Go): Upstream request failed`.

**Empirical approach**: Test compaction at increasing context-usage levels. When compaction fails, derive the provider's effective limit:

```
maxPromptTokens = successfulCompactionTokens / 0.78
```

For OpenCode Go's DeepSeek V4 models, the empirically validated safe values are:
- `maxPromptTokens`: 325,000
- `maxOutputTokens`: 64,000

This same limit discovery process applies to any provider whose gateway enforces stricter limits than the model's published context window.

## Troubleshoot in this order

1. Confirm the base URL, provider type, model name, and API key source.
2. Confirm the model supports streaming and tool calling.
3. If using a stored profile, run `show` or `list` to verify the saved values.
4. If `${ENV_VAR}` placeholders are used, confirm the environment variable actually exists.
5. If long-context models fail, add or lower explicit max prompt and output token overrides.

## OpenCode Go session-header proxy

**Problem:** OpenCode Go requires an `x-opencode-session` header (one stable UUID per conversation) on all API requests. Without it, requests error. Copilot CLI and VS Code Chat do not natively support custom headers.

**Solution:** A local HTTPS proxy that injects the `x-opencode-session` header before forwarding. Scripts live in the skill's `scripts/` folder; runtime cert data is shared with the Moonshot proxy at `~/.copilot/moonshot-proxy/`.

| File | Location | Purpose |
|------|----------|---------|
| `opencode-proxy.js` | `scripts/opencode-proxy.js` | HTTPS proxy server (Node.js) — dual-port: 3001 (always) + 443 (elevated). Generates UUID v4 at startup, injects as `x-opencode-session`. |
| `start-opencode-proxy.ps1` | `scripts/start-opencode-proxy.ps1` | Auto-elevates admin, kills old proxy, starts via `node opencode-proxy.js` |
| `setup-opencode-proxy-dns.ps1` | `scripts/setup-opencode-proxy-dns.ps1` | One-time admin setup: adds `127.0.0.1 opencode-go.local` to hosts + trusted cert |
| Certs | `~/.copilot/moonshot-proxy/` | Shared with Moonshot proxy (moonshot.pfx, cert.pfx) |

### How to use

```powershell
# One-time setup (run once, elevated):
.\scripts\setup-opencode-proxy-dns.ps1

# Start proxy (after every reboot):
.\scripts\start-opencode-proxy.ps1

# Or from published skill location:
pwsh -NoProfile "~\.copilot\skills\copilot-byok\scripts\start-opencode-proxy.ps1"

# Check status:
curl -s https://opencode-go.local/health
```

### Profile integration

Profiles with `"opencodeSessionHeader": true` automatically start the proxy and rewrite `baseUrl` to `https://opencode-go.local/v1`. Existing profiles pointing to `https://opencode.ai/zen/go/v1` are auto-migrated on first access. See [`references/provider/opencode-go/cli.md`](references/provider/opencode-go/cli.md) for details.

### VS Code integration

Use the automation scripts to set up VS Code:

```powershell
# Migrate existing chatLanguageModels.json URLs:
.\scripts\opencode-vscode-migrate-urls.ps1

# Add auto-start task to .vscode/tasks.json:
.\scripts\opencode-vscode-add-proxy-task.ps1
```

The URL migration script creates a timestamped backup before modifying. The task script creates `tasks.json` if missing, skips if the task already exists. After running, reload VS Code (**Developer: Reload Window**).

### Limitation

The proxy generates one session ID per proxy lifetime. Multiple CLI invocations during one proxy lifetime share the same session ID (same cache behavior as a static ID). This is the best available workaround until Copilot CLI adds native custom-header support ([github/copilot-cli#3399](https://github.com/github/copilot-cli/issues/3399)).

## Moonshot proxy (top_p workaround)

**Problem:** Kimi models from `https://api.moonshot.ai` only accepts `top_p=0.95`, but VS Code Copilot BYOK always sends `top_p=1.0` and the `chatLanguageModels.json` schema doesn't support per-model parameter overrides.

**Solution:** A local HTTPS proxy that strips `top_p` before forwarding. Scripts live in the skill's `scripts/` folder; runtime cert data is stored at `~/.copilot/moonshot-proxy/`.

| File | Location | Purpose |
|------|----------|---------|
| `proxy.js` | `scripts/proxy.js` | HTTPS proxy server (Node.js) — dual-port: 3002 (always) + 443 (elevated) |
| `start-proxy.ps1` | `scripts/start-proxy.ps1` | Auto-elevates admin, kills old proxy, starts via `node proxy.js` |
| `setup-dns.ps1` | `scripts/setup-dns.ps1` | One-time admin setup: adds `127.0.0.1 moonshot.local` to hosts + trusted cert |
| Certs | `~/.copilot/moonshot-proxy/` | Runtime cert data (moonshot.pfx, cert.pfx) |

### How to use

```powershell
# One-time setup (run once, elevated):
.\scripts\setup-dns.ps1

# Start proxy (after every reboot):
.\scripts\start-proxy.ps1

# Or from published skill location:
pwsh -NoProfile "~\.copilot\skills\copilot-byok\scripts\start-proxy.ps1"

# Check status:
curl -s https://moonshot.local/health
```

### Profile integration

Add `"proxyPort": 443` to any `byok-profiles.json` profile that needs the proxy. The `run` command auto-starts the proxy and routes through `https://moonshot.local/v1`.

### VS Code integration

Configure the Moonshot provider's `url` to `https://moonshot.local/v1/chat/completions` in `chatLanguageModels.json`. The `.vscode/tasks.json` background task with `runOn: "folderOpen"` auto-starts the proxy, or run **Terminal → Run Task → "Moonshot Proxy"**.

## Moonshot/Kimi AI credentials

Use `MOONSHOT_API_KEY` for the Kimi AI Platform (`api.moonshot.ai/v1`). All models use OpenAI-compatible format, 262K context, and support tool calling and streaming.

## Related skill

For MCP server configuration rather than model-provider configuration, read `../copilot-cli-mcp-config/SKILL.md`.

