Skip to content

Run GitHub Copilot CLI on your Router One key (BYOK)

GitHub Copilot CLI (the copilot command, npm package @github/copilot) can send its model requests to a provider you configure instead of GitHub-hosted models: a few COPILOT_PROVIDER_* environment variables, set before launch, point it at an OpenAI-compatible, Azure OpenAI or Anthropic endpoint. With Router One as an openai-type provider on Chat Completions, one key gives the CLI's agent and its built-in subagents the Claude, GPT, Gemini, Grok and DeepSeek chat models in the catalog, and every turn is a billed request in Dashboard → Logs. Per GitHub's changelog (2026-04-07), GitHub authentication is not required when you use your own model provider. Checked against Copilot CLI 1.0.89 (released 2026-09-28) and GitHub's BYOK documentation on 2026-09-29.

Install Copilot CLI 1.0.89 and create a dedicated key

Install with npm, which needs Node.js 22 or later: npm install -g @github/copilot. GitHub also documents Homebrew (brew install --cask copilot-cli), WinGet (winget install GitHub.Copilot) and an install script for macOS and Linux (curl -fsSL https://gh.io/copilot-install | bash). Version 1.0.89 shipped on 2026-09-28. Then create a key for the CLI alone in Dashboard → API Keys with Create Key and give it a maxSpend cap. The CLI works as an agent, one request per model turn, and its built-in subagents (explore, task and code-review) inherit the same provider configuration, so a single task can bill many requests; the cap is the hard stop, and a dedicated key keeps them together in Logs.

Configure GitHub Copilot CLI to use the Router One base URL

Set the provider variables in the shell that starts the CLI, then run copilot. COPILOT_PROVIDER_BASE_URL is https://api.router.one/v1, the same form as GitHub's OpenAI example. COPILOT_PROVIDER_TYPE can stay unset or be openai, the type GitHub documents for any OpenAI Chat Completions-compatible endpoint. Set COPILOT_PROVIDER_WIRE_API=completions explicitly: GitHub's docs describe the variable but not its default for this type, and third-party reports disagree, so naming the wire keeps every request on POST /v1/chat/completions, which serves every chat model. Put the key in COPILOT_PROVIDER_API_KEY and an exact catalog ID in COPILOT_MODEL, or pass it with --model. Per GitHub's docs, the model must support tool calling and streaming, and a context window of at least 128k tokens gives the best results. If the provider settings are invalid, the CLI reports an error and, per GitHub's changelog, never silently falls back to GitHub-hosted models. For bash or zsh:

COPILOT_PROVIDER_BASE_URL
https://api.router.one/v1
terminal
# GitHub Copilot CLI → Router One (bash / zsh)
export COPILOT_PROVIDER_BASE_URL=https://api.router.one/v1
export COPILOT_PROVIDER_TYPE=openai
export COPILOT_PROVIDER_WIRE_API=completions
export COPILOT_PROVIDER_API_KEY=sk-your-router-one-key
export COPILOT_MODEL=anthropic/claude-sonnet-5
copilot

Provider type and wire API for each Router One model ID

Router One serves every chat model on Chat Completions, so the setup above takes Claude, GPT, Gemini, Grok and DeepSeek IDs. Two other combinations are possible. With COPILOT_PROVIDER_WIRE_API=responses the CLI calls POST /v1/responses, which Router One serves natively for GPT-family, DeepSeek V4 and Grok chat IDs; a Claude ID there is rejected with HTTP 400 before any model runs (model '<id>' must be called via /v1/messages or /v1/chat/completions). With COPILOT_PROVIDER_TYPE=anthropic the base URL is the host root, https://api.router.one, just as GitHub's Anthropic example uses the host root of Anthropic's API, and the CLI uses Anthropic Messages, which Router One serves for Claude-family and DeepSeek V4 IDs; another chat ID gets 400 with must be called via /v1/chat/completions. On every combination, prefer IDs whose model page lists tool calling, and test one tool call before you start a long task.

Provider type and wire API for each Router One model ID
Provider type and wire APICOPILOT_PROVIDER_BASE_URLRouter One model IDs
openai + completions (recommended)https://api.router.one/v1Every chat model in the catalog: Claude, GPT, Gemini, Grok and DeepSeek IDs
openai + responseshttps://api.router.one/v1GPT-family IDs, azure/gpt-… channel IDs included, plus deepseek-v4.1-flash, deepseek-v4-flash and Grok chat IDs
anthropichttps://api.router.oneClaude-family IDs, aws/claude-… and vertex/claude-… channel IDs included, plus deepseek-v4.1-flash and deepseek-v4-flash

Token limits: MODEL_ID, MAX_PROMPT_TOKENS and MAX_OUTPUT_TOKENS

Per GitHub's docs, the CLI identifies a model's capabilities and token limits by a well-known model name, which COPILOT_PROVIDER_MODEL_ID can supply, while the name sent to the provider comes from COPILOT_MODEL, or from COPILOT_PROVIDER_WIRE_MODEL when that is set. The docs do not list which names count as well-known, or say whether a vendor-prefixed Router One ID such as anthropic/claude-sonnet-5 is recognized, so this guide leaves COPILOT_PROVIDER_MODEL_ID unset rather than guessing, and sets the limits directly. GitHub documents COPILOT_PROVIDER_MAX_PROMPT_TOKENS as the maximum number of prompt tokens allowed in a request: keep it at or below the context window on the model's Router One page (1048576 for anthropic/claude-sonnet-5, 1000000 for deepseek-v4.1-flash), and remember that every input token is billed. On IDs whose page lists a long-context price line for the whole request, such as openai/gpt-5.6-sol above 272,000 input tokens, a value below that threshold should keep prompts under it, per GitHub's description; how the CLI enforces the limit is not documented. COPILOT_PROVIDER_MAX_OUTPUT_TOKENS is a cap of your own for each response; which field the CLI sends for it on the completions wire is not documented, and Router One's Chat Completions reference documents max_tokens as the output cap. Leave it unset unless you want a lower one.

terminal
# optional: your own prompt cap, at or below the model page's window
export COPILOT_PROVIDER_MAX_PROMPT_TOKENS=200000

Why this guide keeps the completions wire

Copilot CLI 1.0.64 added WebSocket Responses support for BYOK OpenAI-compatible providers. Router One's /v1/responses streams over HTTP and has no WebSocket mode, and GitHub's docs do not say when the CLI uses WebSocket on the responses wire or whether it falls back to HTTP, so the recommended setup stays on COPILOT_PROVIDER_WIRE_API=completions. If you try the responses wire with a GPT ID and requests fail before any output, switch back to completions. The CLI's changelog says its reasoning effort setting has applied to bring-your-own-model providers since 1.0.13. When a request carries reasoning_effort, Router One does not turn it into a thinking setting for Claude IDs, except on Claude Opus 5.5, where it maps the value to output_config.effort; other models may ignore it or reject the request with 400, so check the status of the next request in Logs after changing it.

What reaches your key, and how to read Logs

With a Router One provider, every model turn of the CLI's agent is a request on your key, including turns by the built-in explore, task and code-review subagents. Signing in to GitHub is optional: it adds GitHub features such as /delegate, GitHub code search and the GitHub MCP server, while the model requests still go to Router One. Per GitHub's changelog, COPILOT_OFFLINE=true stops the CLI from contacting GitHub's servers and turns off its telemetry; your prompts and code context still travel to Router One, which is a remote provider. In Dashboard → Logs, filter by the CLI's key: each record shows the model, tokens, cost, status, total time and, for streamed requests that produced output, time to first token (TTFT). 401 means the key is missing or wrong, 402 means the wallet balance or the key's maxSpend is used up, and 400 with must be called via means the provider type or wire API does not serve that ID.

Which model ID should GitHub Copilot CLI send?

Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in GitHub Copilot CLI. A catalog listing does not mean the client can use every feature of that model. Give each client or application a dedicated API key with a maxSpend cap.

Which API protocol is GitHub Copilot CLI using?

OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.

Verify the GitHub Copilot CLI call in your request trace

Send a simple text request from GitHub Copilot CLI, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, check client configuration and connectivity before attributing the error to the gateway or upstream.

FAQ

Do I need a GitHub account or a Copilot subscription for BYOK?

Not for the model requests. GitHub's changelog (2026-04-07) states that when you use your own model provider, GitHub authentication is not required, so the CLI starts with the provider variables alone and Router One bills the requests on your key. Signing in to GitHub is optional and adds GitHub features such as /delegate, GitHub code search and the GitHub MCP server.

How do I keep these settings across terminals?

Add the export lines to your shell profile (~/.zshrc or ~/.bashrc) and open a new terminal. On Windows, set each variable once with [System.Environment]::SetEnvironmentVariable, for example ("COPILOT_PROVIDER_BASE_URL", "https://api.router.one/v1", "User"), then open a new PowerShell window. The CLI reads the variables when it starts, so a running session keeps its old provider. Keep the key out of shared dotfile repositories.

Can I run Claude through the anthropic provider type instead?

Yes: set COPILOT_PROVIDER_TYPE=anthropic, COPILOT_PROVIDER_BASE_URL=https://api.router.one and a Claude-family or DeepSeek V4 ID. The CLI then uses Anthropic Messages. Its 1.0.66 changelog says it picks a thinking mode per Anthropic model, and how it treats a vendor-prefixed ID it may not recognize is not documented; if requests fail with a 400 that mentions thinking, go back to the openai type, where Router One serves the same Claude IDs on Chat Completions.

The CLI says the model does not support tool calling or streaming. What now?

Copilot CLI needs both and, per GitHub's docs, returns an error when a model lacks either. Pick a chat ID whose page on /models lists tool calling; as of 2026-09-29, every catalog ID that lists tool calling also lists streaming. Image-generation IDs and IDs whose model page lists no capabilities are not suitable for the CLI.

How is this different from the GitHub Copilot guide for VS Code?

That guide covers Copilot Chat in VS Code, where Router One is added as a Custom Endpoint provider. The CLI reads the COPILOT_PROVIDER_* environment variables instead, and the two do not share configuration, so set up each one separately; both can use the same Router One key, or separate keys to tell their costs apart in Logs.

Which models can GitHub Copilot CLI use through the gateway?

Choose a current catalog model that supports both the endpoint and the features GitHub Copilot CLI uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. A client that lists a model has only read the ID, from its own configuration or from GET /v1/models; verify an actual request too.

Models are listed, but requests fail with 400 or 404. What should I check?

Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.

Does this work from Mainland China?

The CLI's model requests to Router One work from Mainland China without a VPN, with the same configuration as elsewhere. Installing the CLI goes through npm, Homebrew, WinGet or GitHub-hosted downloads, and unless COPILOT_OFFLINE=true is set the CLI also contacts GitHub's servers, so those parts depend on your network's access to them.

How do I debug a 401/402/403/429?

Match the request and error message in Dashboard → Logs. For 401, check whether the key was sent and is valid; for 402, check wallet balance and maxSpend; for 403, check key permissions and access restrictions. For 429, distinguish request/token limits from upstream throttling using the error details. Keep the request_id and follow the error-codes reference.