Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

English | 简体中文

BYOKEY

Bring Your Own Keys
Run ChatGPT.app / Codex and Claude clients through a local gateway.
Responses supports your ChatGPT subscription, GitHub Copilot and custom upstreams; Anthropic Messages supports Copilot, Cursor, Claude and custom upstreams.

ci   crates.io   license   rust

[!IMPORTANT] BYOKEY is no longer archived. The Responses gateway and native Codex HTTP forwarding are available on master.

The latest published release, v3.0.0, does not include these features. Build from source to use the ChatGPT.app / Codex quick start.

[!NOTE] Direct Copilot access is an alternative for Claude clients that only need Copilot. Its /v1/messages endpoint accepts Claude Code's requests without BYOKEY. The Cursor backend drives Cursor's private agent protocol, which Cursor does not allow outside its own clients, and it does not hold up in Claude Code's tool loops.

To use Copilot directly (GitHub does not document this endpoint), sign in with the GitHub CLI and configure:

Claude Code — ~/.claude/settings.json

{
  "env": { "ANTHROPIC_BASE_URL": "https://api.githubcopilot.com" },
  "apiKeyHelper": "gh auth token"
}

Claude Desktop — third-party inference with the gateway provider. Copilot serves no /v1/models, so list the models by full id:

{
  "inferenceProvider": "gateway",
  "inferenceGatewayBaseUrl": "https://api.githubcopilot.com",
  "inferenceGatewayAuthScheme": "bearer",
  "inferenceCredentialKind": "helper-script",
  "inferenceCredentialHelper": "/opt/homebrew/bin/gh",
  "inferenceCredentialHelperArgs": ["auth", "token"],
  "modelDiscoveryEnabled": false,
  "inferenceModels": ["claude-opus-5-5", "claude-fable-5-1", "claude-sonnet-5", "claude-haiku-4-5"]
}

The Anthropic Messages path is shown below. Responses uses the same server with separate model routing.

Subscriptions                                     Clients

GitHub Copilot ─┐                            ┌──  Claude Code
Cursor         ─┼──  byokey serve  ──────────┼──  Claude Desktop
Claude Pro/Max ─┘                            └──  any Anthropic Messages client

Features

  • Responses API — /v1/responses and /codex/responses for ChatGPT.app / Codex, with model aliases, custom upstreams, and Codex model discovery at /codex/models
  • Native Codex HTTP forwarding — unmatched /codex/* paths go to the configured ChatGPT backend, including image generation and editing endpoints; no WebSocket support
  • Anthropic Messages API — /v1/messages, /v1/messages/count_tokens and /v1/models, as Claude Code and Claude Desktop expect them; [1m] long-context ids included
  • Copilot as a Claude backend — Copilot's Anthropic-format endpoint, with quota-aware account selection and unsupported request fields stripped; model selection and server tools stay under client control
  • Cursor as a Claude backend — every model on your Cursor plan, driven through Cursor's agent protocol
  • Claude Code and Claude Desktop wiring — byokey claude start, byokey claude inject, byokey claude desktop; byokey doctor checks it all
  • OAuth login and token persistence — device-code and PKCE flows; SQLite at ~/.byokey/tokens.db, tokens refreshed in the background
  • Runs as a service — launchd / systemd / Windows SCM registration, hot-reloaded config

Supported Providers

Responses supports ChatGPT with client-owned credentials, Copilot with stored accounts or a configured API key, and custom Responses-compatible upstreams. The providers below serve the Anthropic Messages API.

GitHub Copilot
Copilot
Device code
claude-fable-5.1
claude-opus-5.5
claude-sonnet-5
…every Claude model on your plan
Cursor
Cursor
OAuth · API key
claude-opus-5-5
claude-opus-5-5-low-fast
composer-2.5
…every model on your plan
Claude
Claude
OAuth · API key
claude-fable-5-1
claude-opus-5-5
claude-sonnet-5
claude-haiku-4-5

Installation

For Responses and native Codex HTTP forwarding, build from master using the source instructions below. These features are not yet in the published packages or release binaries.

Homebrew (macOS / Linux)

brew install AprilNEA/tap/byokey

Install script (Linux / macOS)

curl -fsSL https://raw.githubusercontent.com/AprilNEA/BYOKEY/master/install.sh | sh

Downloads the latest release binary into ~/.byokey/bin/. Pin a version with BYOKEY_VERSION=v1.2.0 or override the install location with BYOKEY_INSTALL_DIR=/usr/local/bin.

From crates.io

cargo install byokey

From source

git clone https://github.com/AprilNEA/BYOKEY
cd BYOKEY
cargo install --path .

Requirements: Rust 1.91+ (edition 2024), a C compiler for SQLite, and protoc for ConnectRPC code generation (brew install protobuf, apt-get install protobuf-compiler, or choco install protoc).

Quick Start

ChatGPT.app / Codex

This connects the Codex functionality in the ChatGPT desktop app, not the legacy ChatGPT conversation API. Keep the client signed in to ChatGPT: the client supplies its access token and account header and remains responsible for token refresh. BYOKEY does not import or store that login.

After installing from source, run byokey serve. Alternatively, with Nix and devenv installed, build and start this checkout:

devenv shell cargo run -- serve

Merge these settings into ~/.codex/config.toml, keeping top-level keys before any TOML table, then restart the client:

model = "gpt-6-sol"
model_provider = "byokey"
web_search = "disabled"

[model_providers.byokey]
name = "BYOKEY"
base_url = "http://127.0.0.1:8018/codex"
wire_api = "responses"
requires_openai_auth = true
supports_websockets = false

[features]
enable_request_compression = false

Use a model available to your account. With a ChatGPT login, Codex discovers the catalog at base_url/models. Leave model_catalog_url unset: explicitly configured catalog URLs have a 1 MiB limit, which a combined multi-provider catalog can exceed. This setup uses HTTP SSE and local compaction; WebSocket transport and compressed Responses request bodies are not supported. Keep web search disabled until the selected upstream supports the client's search tools.

Unmatched /codex/* HTTP paths, including images/generations and images/edits, go directly to providers.chatgpt.base_url (default https://chatgpt.com/backend-api/codex) with the client's ChatGPT credentials. This fallback is independent of the selected inference provider. It preserves the method, path suffix, query, body bytes, upstream status and end-to-end headers; cookies and connection-specific request headers are removed. Request and response bodies stream without JSON parsing or automatic decompression. Redirects and retries are disabled. Native requests are logged but do not contribute to Responses token usage statistics. The fallback does not enable client-side features or translate model aliases for native endpoints.

With no Responses configuration, inference requests go to ChatGPT. To add Copilot and a custom gateway, sign in with byokey login copilot and merge the following into the BYOKEY config passed to serve --config:

providers:
  company:
    base_url: https://gateway.example.com/team/v1
    models_url: https://gateway.example.com/team/v1/models
    display_name: Company
    api_key: { env: COMPANY_API_KEY }
    headers:
      X-Tenant: engineering
      X-Special-Token: { env: COMPANY_GATEWAY_TOKEN }
      X-Request-UID: { uuid_prefix: "byokey-" }
    model_overrides:
      my-deployment:
        catalog_model: gpt-5.4-mini

responses:
  routes:
    default: chatgpt
    models:
      copilot-fast: { provider: copilot, model: gpt-5.4-mini }
      company-fast: { provider: company, model: my-deployment }

providers is one flat map for both protocols. claude, copilot, cursor and chatgpt are reserved built-in names. Custom Responses connections require base_url; custom Messages connections use a separate anthropic block described below. A provider may support either or both protocols. Connection settings and model metadata belong to the provider, so a Responses route alias holds only provider and the model ID sent to it.

api_key and header values accept a literal string or an explicit environment reference { env: NAME }; BYOKEY never interprets a literal string as a variable or command. Export the referenced variables in the BYOKEY server process, not just the client. Missing variables fail the request. A configured Authorization header overrides api_key. models_url, headers and service_tier are accepted only on custom providers. /responses is appended to each base_url; custom providers must implement the Responses API themselves.

providers.<name>.model_overrides is keyed by the actual model ID sent to that provider, never by an alias. Each entry may set name (display name), catalog_model (a ChatGPT Codex catalog slug whose metadata matches this model) or catalog (a complete Codex ModelInfo object). Without catalog_model or catalog, the model borrows the ChatGPT catalog entry with the same ID. In the example, company-fast assumes that my-deployment serves the same model as gpt-5.4-mini; choose matching metadata for the actual deployment.

Set models_url to an OpenAI-compatible {"data":[{"id":"..."}]} endpoint to discover multiple models without defining each alias. BYOKEY lists every ID that also has ChatGPT Codex metadata as <provider>/<model>, displayed by default as <model display name> (<display_name>). The provider label defaults to the provider name. Models without matching metadata need a complete model_overrides.<model>.catalog; BYOKEY does not fabricate their instructions or capabilities. A model list does not guarantee current account access or Responses support. The model list URL receives the same configured credentials and headers as the Responses URL, never the client's ChatGPT credentials. Configure only trusted URLs. Catalog errors are returned to the client. Explicit aliases override discovered entries with the same slug. Omit models_url to keep manual aliases only.

All catalog entries default to <model name> (<provider>), including native models. Configure presentation separately from routing:

providers:
  copilot:
    display_name: GitHub Copilot
    model_overrides:
      gpt-6-astra:
        name: GPT-6 Astra

responses:
  catalog:
    name_format: "{{ model }} ({{ provider }})"
    hidden_aliases: ["LLM Router"]

name_format uses MiniJinja with two plain-text variables: model and provider. For example, "{{ provider }} / {{ model }}" puts the source first. Built-in filters such as upper and replace are available; template imports and filesystem access are not. providers.<name>.display_name sets the provider label in both the Responses and Anthropic catalogs. The labels default to ChatGPT, Copilot, Claude (Anthropic) and Cursor; a custom provider defaults to its name. model_overrides.<model ID>.name renames that provider's actual model ID, not an alias or catalog_model. Without an override, BYOKEY preserves the shared ChatGPT or explicit catalog.display_name verbatim, falling back to the model ID when metadata has no name. It does not rewrite hyphens or strip provider suffixes. Route IDs, instructions and capabilities are unaffected.

Enabled Copilot credentials, from a stored login or providers.copilot.api_key, enable discovery without a model alias. The picker shows at most one visible entry per provider and model, preferring the default provider's unqualified ID, then a provider-prefixed ID, then a configured alias. hidden_aliases hides exact catalog slugs before that selection; hiding one alias does not hide other aliases for the same model. Duplicate and explicitly hidden aliases retain their metadata with visibility: hide, so existing sessions and explicit model IDs still work. Upstream-hidden models remain hidden.

These settings hot-reload. The next catalog request uses the new settings; the client may need to refresh its cached model list. Syntax errors, unknown variables and failed validation renders reject the configuration. Failed reloads retain the last valid configuration and log the error. Render errors with actual model data fail the catalog request rather than silently substituting a name; names must be nonempty.

uuid_prefix generates a fresh lowercase UUID v4 for each upstream request, preceded by the configured prefix. Set a custom provider's optional service_tier to override the client's top-level service_tier, for example service_tier: fast when that upstream supports it. Without an override, BYOKEY preserves the client's value. Do not wrap Responses parameters in extra_body; send them at the top level.

Select a provider-labelled model in the client, or set a model ID such as copilot-fast or company-fast explicitly. Exact aliases take priority, followed by chatgpt/<model>, copilot/<model> or <provider>/<model>, followed by responses.routes.default for unqualified names. Copilot models must advertise /responses; BYOKEY does not translate Chat Completions or Anthropic requests on this path. Copilot uses BYOKEY's stored accounts or providers.copilot.api_key, never the client's ChatGPT credential.

To make Codex automatic approval reviews use the selected non-ChatGPT model and its provider credentials, enable this setting in the BYOKEY config:

responses:
  auto_review_follow_provider: true

The default is false, which preserves upstream reviewer metadata. When enabled, /codex/models sets each non-ChatGPT entry's auto_review_model_override to its own slug. This also applies to aliases and unqualified IDs routed to a non-ChatGPT provider. ChatGPT entries retain their upstream reviewer selection. Codex must support this metadata field and refresh its model catalog; restart the client after changing the setting. The setting does not enable automatic approval by itself: keep approvals_reviewer = "auto_review" in the Codex configuration.

Codex still supplies its approval policy, read-only reviewer tools and structured-output schema. The selected model must support these requests; its review quality may differ from the official reviewer, and review requests consume that provider's quota. BYOKEY does not convert review failures into approvals or retry them through ChatGPT. Multi-agent V2 metadata, actual quota data and error responses remain unchanged. This setting does not hide the desktop client's official-account quota banner.

Optional: hide the Codex Desktop quota banner. The Surge for Mac module hides the workspace-member usage-limit banner for all models, including official ChatGPT models, without changing real quotas or errors. It requires HTTPS interception; Surge Logbook can retain authentication headers even with debugging disabled. Read the security and installation instructions before enabling it. BYOKEY does not install or enable the module.

Copilot can change an output item's ID between stream events. BYOKEY retains the first ID for each output index so Codex updates one message instead of displaying a duplicate. Response IDs and tool call_id values remain unchanged. ChatGPT and custom providers retain their original stream payloads.

The catalog borrows actual ChatGPT model metadata, including instructions and capabilities. When model_messages.instructions_template is present, BYOKEY omits the ignored legacy base_instructions copy to reduce catalog size. Each routed model needs a ChatGPT catalog entry with its ID or its catalog_model, or a complete Codex ModelInfo object in model_overrides.<model>.catalog. A missing match is an error. A custom default with complete catalog objects, no models_url, and no enabled Copilot credentials or routes needs no ChatGPT catalog access; otherwise catalog discovery needs the client's ChatGPT login. Alias upgrades are disabled so the client does not migrate an alias to a different route. The existing /v1/models, byokey route, and TUI route list remain Anthropic-only.

Send Reply with exactly: gateway-ok and check the gateway log for the intended upstream and model. Then test a tool call and a follow-up. Upstream errors and retry-after are preserved. Normal Responses streams end with response.completed; failed, incomplete and truncated streams are recorded as failures, while client cancellation is recorded as abandoned.

Keep the listener on 127.0.0.1. BYOKEY has no inbound authentication for its stored Copilot/custom credentials; do not expose this port to an untrusted network. Only the configured ChatGPT backend receives the client's ChatGPT auth headers; configure only a trusted providers.chatgpt.base_url. The client owns ChatGPT login and refresh, so providers.chatgpt rejects api_key and headers. Redirects are not followed. Responses routes are excluded from BYOKEY_DUMP, and their request headers are removed from Sentry events.

Local logs and usage records retain account identifiers. Local error logs can contain text quoted by the upstream. Account identifiers and upstream error text are removed from Sentry event fields, trace data and breadcrumbs.

Claude Code / Claude Desktop

# 1. Sign in (opens a browser or shows a device code)
byokey login copilot           # as OpenCode; `--client vscode` to log in as VS Code
byokey login cursor            # or `byokey add-api-key cursor crsr_…`

# 2. Send Claude models to Copilot, and start the proxy
byokey route set --default copilot
byokey serve

# 3. Run Claude Code on it
byokey claude start

byokey claude start [claude args…] launches Claude Code against BYOKEY; plain claude keeps using your own login. To make BYOKEY the default instead, run byokey claude inject. byokey claude desktop does the same for Claude Desktop (macOS). byokey doctor checks the whole setup. Any other Anthropic Messages client works with ANTHROPIC_BASE_URL=http://127.0.0.1:8018.

Copilot alongside a custom Messages gateway

Keep Copilot as the default and add an independent Messages connection to the shared provider map:

anthropic:
  routes:
    default: copilot

providers:
  llm-router:
    display_name: LLM Router
    anthropic:
      base_url: https://router.example/api
      enabled_models:
        - claude-opus-5-5
        - claude-sonnet-4-6
      headers:
        x-request-resource-group: your-group
        x-request-task-type: claude
        x-request-task-uid: { uuid_prefix: "byokey-" }
        x-request-product-name: your-product
        x-request-options: '{"account_details":"1"}'

Replace the URL and header values with your gateway's settings. This base URL sends generation requests to /api/v1/messages. Without models_url, anthropic.enabled_models supplies a fixed catalog without contacting the gateway. List exact upstream Claude IDs without BYOKEY provider qualifiers. BYOKEY does not verify account access while listing these models. If both fields are absent, the custom provider adds no picker entries, but explicit requests still work.

For automatic discovery, set anthropic.models_url to an endpoint such as https://router.example/v1/models returning {"data":[{"id":"claude-sonnet-4-6"}]}; entries may include display_name. When discovery is configured, enabled_models filters the discovered IDs rather than supplying entries. Omit enabled_models to list all discovered Claude models. Discovery failures are returned to the client, not hidden behind a partial or fixed catalog.

Both catalog modes retain claude- IDs, including provider-specific variants, and ignore other models. Use enabled_models: [] to hide all entries from that provider. Catalog settings do not restrict explicit requests or change routes. BYOKEY neither rewrites effort-suffixed aliases nor derives effort parameters from them.

The picker lists claude-sonnet-4-6 as Claude Sonnet 4.6 · Copilot when Copilot offers it, and claude-sonnet-4-6[llm-router] as Claude Sonnet 4.6 · LLM Router. Desktop 2.31226.0 recognizes the base model's Effort capabilities through the bracket tag while keeping both entries and their effort selections distinct. Unrecognized upstream aliases do not gain Effort support from a tag.

Explicit <model>[<provider>] IDs select that provider, as do existing <provider>/<model> IDs. A custom provider uses bare IDs when a model, family or default route selects that provider and the upstream ID has no provider qualifier. Custom variants retain their upstream spelling; IDs containing / keep the prefix form to avoid ambiguity. Messages provider names must not be 1m or contain [ or ]. The reserved [1m] suffix still requests long context and may appear before or after the provider tag. Tagged custom entries do not advertise an additional 1M picker variant.

anthropic.headers applies to discovery, generation and token counting. Values accept literals, { env: NAME } and { uuid_prefix: "prefix-" }. Optional anthropic.api_key sends x-api-key; an explicitly configured x-api-key header takes precedence. Messages never inherits the provider's Responses credentials or headers, stored Claude credentials, or client auth headers. Keep Responses settings such as x-specified-llm-provider-name: openai outside the anthropic block. Configure only trusted upstream URLs.

The custom Messages path preserves native request fields, thinking signatures, tools, response JSON and SSE; it strips the provider qualifier and applies BYOKEY's thinking and beta normalization. It does not translate through Chat Completions or apply Claude OAuth tool-name remapping. /v1/messages/count_tokens is appended to the Messages base URL; if the gateway does not implement counting, its error is returned without an estimate or provider fallback.

Custom Messages requests forward only explicitly requested betas: the client's anthropic-beta header, its JSON betas array and the [1m] suffix. BYOKEY does not inject Claude Code's default beta list into custom upstreams. Without requested betas, BYOKEY omits the header. A configured anthropic.headers.anthropic-beta replaces the requested list for both generation and token counting; use only beta values your gateway supports.

byokey claude start --model 'claude-sonnet-4-6[llm-router]'

CLI Reference

byokey <COMMAND>

Commands:
  serve         Start the proxy server (foreground)
  start         Start the proxy server in the background
  stop          Stop the background proxy server
  restart       Restart the background proxy server
  reload        Reload the running server's configuration without restarting
  service       Manage OS-level service registration (launchd / systemd / Windows SCM)
  login         Authenticate with a provider (claude, copilot, cursor)
  add-api-key   Store a static API key as a provider account
  import-claude-code
                Import the local Claude Code CLI's login as a Claude account
  logout        Remove stored credentials for a provider
  status        Show authentication status for all providers
  doctor        Check the server, provider logins, Claude Code and Claude Desktop wiring
  tui           Launch the interactive terminal UI
  accounts      List all accounts for a provider
  switch        Switch the active account for a provider
  claude        Run Claude Code or Claude Desktop against BYOKEY (alias: claude-code)
  completions   Generate shell completions
  help          Print help
Command details

byokey serve

Options:
  -c, --config <FILE>   Config file (JSON or YAML) [default: ~/.config/byokey/settings.json]
  -p, --port <PORT>     Listen port     [default: 8018]
      --host <HOST>     Listen address  [default: 127.0.0.1]
      --db <PATH>       SQLite DB path  [default: ~/.byokey/tokens.db]
      --log-file <PATH> Log file with daily rotation (default: stdout)

serve also binds a Unix control socket at ~/.byokey/control.sock used by stop / reload. If the process is launched with a pre-opened socket via systemfd, systemd, or launchd, the inherited fd is adopted in place of a fresh bind.

byokey start — Same options as serve. Runs the server in the background and writes logs to ~/.byokey/server.log by default.

byokey reload — Triggers a hot config reload on the running server via the control socket. No process restart, no dropped connections.

byokey login <PROVIDER>

Runs the appropriate OAuth flow for the given provider: claude (PKCE in the browser), copilot (GitHub device code) or cursor (Cursor's browser login).

Options:
      --account <NAME>  Account identifier (default: `default`)
      --client <CLIENT> Client to log in as; Copilot: `opencode` (default) or `vscode`
      --db <PATH>       SQLite DB path [default: ~/.byokey/tokens.db]

byokey logout <PROVIDER> — Deletes the stored token for the given provider.

byokey status — Prints authentication status for every known provider.

byokey doctor — Checks that the server answers, /v1/models and /v1/messages/count_tokens work, each configured provider is signed in, whether plain claude points at BYOKEY, and whether Claude Desktop's third-party profile does (macOS). Each failing line says what to run. Exits non-zero when a check fails.

byokey route — Lists each Claude model, the provider serving it, the route that picked it, and the signed-in providers that offer it. byokey route set <TARGET> <PROVIDER> routes a target to claude (Anthropic), copilot, cursor or a configured Messages provider, and byokey route unset <TARGET> removes that route. The target is one of:

  • --model <MODEL>: one model, by Anthropic's id (claude-opus-5-5)
  • --family <FAMILY>: fable (or mythos), opus, sonnet or haiku
  • --default: every model without a model or family route

A model's route beats its family's, which beats the default; without any, the model goes to Anthropic. Claude Code's incidental requests (titles, summaries) use the Haiku model, so --family haiku decides where those go. The routes are saved to anthropic.routes in the config file, which the running server reloads, also when byokey route creates it. byokey route set warns when the provider is not signed in, and byokey doctor checks every routed provider.

byokey tui — Opens the terminal management UI. It connects to the ConnectRPC management API at http://127.0.0.1:8018 by default; override with --url <URL>.

byokey accounts <PROVIDER> — Lists all accounts for a provider.

byokey switch <PROVIDER> <ACCOUNT> — Switches the active account for a provider.

byokey service <install|uninstall|start|stop|status> — Registers byokey as an OS-managed service. Uses launchd on macOS, systemd on Linux, and Windows SCM on Windows. install takes the serve options; the service logs to ~/.byokey/server.log unless --log-file says otherwise.

byokey claude start [ARGS]… — Runs claude with ANTHROPIC_BASE_URL pointing at BYOKEY, passing ARGS through. A claude.ai login stays in effect, keeping features such as connectors; without any login, a placeholder ANTHROPIC_AUTH_TOKEN is set so Claude Code can start, along with gateway model discovery, which lists the Claude models your routes serve in /model.

byokey claude inject — Writes the same settings, plus any claude_code.settings from your byokey config, into ~/.claude/settings.json, keeping its other settings. Override the target with --settings <FILE>.

byokey claude desktop — Opens a second Claude Desktop in its third-party mode against BYOKEY, next to the official one, whose profile is never modified. Before launch, the command fetches BYOKEY's model catalog and writes an explicit inferenceModels list. Each built-in entry keeps its standard Anthropic ID, with a provider-labelled labelOverride such as Claude Opus 5.5 · Copilot. Models documented as native 1M, including Opus 5.5 and Fable 5/5.1, appear once by default without an additional 1M entry. Other models retain the optional 1M entry when the upstream advertises support. This changes the picker, not the upstream model's context limit. Custom Messages entries use [provider] tags to preserve base-model Effort recognition and separate provider choices; see custom Messages gateways. After changing routes, display settings or available models, quit the BYOKEY Desktop instance and run the command again to refresh its list and labels. Server-side routes still hot-reload; labels describe the routes at the last launch through this command. If the catalog request fails or lists no models, Desktop settings stay unchanged. By default, the generated profile sets coworkEgressAllowedHosts: ["*"], allowing tool connections to any outbound host in Cowork and Code. This removes Desktop's default network policy that locks Local sandbox on; it does not turn the sandbox off or override other managed policies. To apply this to an existing profile, quit the BYOKEY Desktop instance and run the command again. While the BYOKEY instance runs it can switch Desktop's saved mode, so a cold launch from the Dock may open it instead of the official one; the command warns about this. macOS only.

Configure native Desktop third-party settings in the BYOKEY config:

claude_desktop:
  settings:
    coworkEgressAllowedHosts: ["*"]

claude_desktop.settings overrides generated behavior defaults by top-level key. Arrays and nested objects are copied unchanged; an explicit empty list replaces the default list. Restricting outbound hosts can lock Local sandbox on again. Use Desktop's native setting names and value types; BYOKEY does not validate the Desktop schema. These settings are separate from claude_code.settings.

BYOKEY reserves inferenceProvider, inferenceGatewayBaseUrl, inferenceCredentialKind, inferenceGatewayApiKey, inferenceGatewayAuthScheme, modelDiscoveryEnabled, and inferenceModels. Defining any of these in claude_desktop.settings fails configuration loading before Desktop files change. Use --url for the gateway address and BYOKEY routes for model selection.

After editing the config, quit the BYOKEY Desktop instance and run byokey claude desktop --config path/to/settings.yaml (JSON also works). Server hot reload does not apply Desktop settings. The command rebuilds its profile entry each launch, so keep overrides in the BYOKEY config rather than editing the generated entry.

All three accept --url <URL> to use a BYOKEY other than the configured one.

Configuration

Create a config file (JSON or YAML, e.g. ~/.config/byokey/settings.json) and pass it with --config:

port: 8018
host: 127.0.0.1

providers:
  # Use Anthropic with a raw API key instead of a login
  # claude:
  #   api_key: "sk-ant-..."

  # A `crsr_…` key from cursor.com/dashboard, or `byokey login cursor`
  cursor:
    api_key: { env: CURSOR_API_KEY }

anthropic:
  # Which provider serves each Claude model; `byokey route` edits this.
  # A model's route beats its family's, which beats the default. Without
  # any, models go to Anthropic.
  routes:
    default: copilot
    families:
      opus: cursor
    models:
      claude-opus-5-5: copilot

Unspecified built-in providers are enabled by default and use the login stored in the database. Unknown fields fail configuration loading, except for native client settings inside claude_code.settings and claude_desktop.settings. providers is the single provider map for both protocols; see ChatGPT.app / Codex for custom Responses providers. Anthropic routes accept claude, copilot, cursor and custom providers with an anthropic connection. Setting providers.<name>.enabled: false hides that provider's models and rejects Messages and token-count requests routed to it with HTTP 400, including explicit provider prefixes and suffixes. Requests do not fall back to another provider.

/v1/models lists each routed built-in Claude model once, under Anthropic's id (claude-opus-5-5), when the provider its route names offers it. Display names identify the routed provider. Standard IDs preserve Claude Desktop's model and effort recognition; provider labels do not change request routing. Custom providers add separately selectable entries, as described above.

Provider and model display names live under providers; the Claude client name format in anthropic.catalog is independent of responses.catalog:

providers:
  claude:
    display_name: Anthropic
  copilot:
    display_name: GitHub Copilot
    model_overrides:
      claude-opus-5-5:
        name: Opus 5.5

anthropic:
  catalog:
    name_format: "{{ model }} · {{ provider }}"
    merge_native_1m: true

name_format reuses the Responses catalog's MiniJinja syntax and validation, with the plain-text variables model and provider. Filters work here too: "{{ provider | upper }} / {{ model }}" puts the provider first. The default format is "{{ model }} · {{ provider }}". providers.<name>.display_name is shared with the Responses catalog; labels default to Claude (Anthropic), Copilot and Cursor. For built-ins, Anthropic model_overrides keys are canonical standard Anthropic IDs such as claude-opus-5-5. For custom Messages providers, keys are the exact upstream IDs, without BYOKEY provider qualifiers. The override applies when that provider serves the model. Without an override, built-ins use the standard friendly name; custom providers use the discovered display name, standard friendly name or raw ID. These naming settings change only display_name and Desktop's labelOverride, not IDs, routing, effort or context capabilities.

anthropic.catalog.merge_native_1m defaults to true: native 1M models keep only their standard picker entry. Set it to false to offer an additional 1M entry when the upstream advertises support, including for native 1M models. This setting does not change model IDs, routing, effort, upstream context limits or the Responses catalog.

The server hot-reloads these settings. Invalid templates or empty names reject configuration loading; failed reloads retain the last valid configuration. A template that fails with actual model data fails the catalog request rather than substituting a name. After changing catalog settings, quit the BYOKEY Desktop instance and rerun byokey claude desktop to refresh its saved model list and labels.

Copilot requests keep the client-selected model, including ordinary chat without tools and compaction. Select Claude Code's background model in the client:

ANTHROPIC_DEFAULT_HAIKU_MODEL=copilot/claude-haiku-4-5 byokey claude start

To persist the choice, set this variable in the env object of Claude Code's user settings. The variable controls both the haiku alias and background functionality; see Claude Code's model configuration. Choose a model available to your Copilot account on the Messages endpoint. Claude Desktop continues to use the model selected in its picker.

A Copilot organisation can turn off Anthropic's web_search and web_fetch server tools by policy. BYOKEY returns the upstream error without removing tools or retrying a modified request. Later generation and token-count requests also retain their tools. Enable the tools in the organisation's policy or explicitly disable them in the client.

The effort Claude Code or Claude Desktop picks (output_config.effort) reaches every provider. Cursor takes it as the model's effort parameter and refuses a level the model lacks, as Anthropic and Copilot do.

Cursor serves every model on your Cursor plan, including variants such as claude-opus-5-5-high-fast or gpt-5.6-sol-low-fast, which /v1/models does not list. Name them as cursor/<model>, so byokey claude start --model cursor/claude-opus-5-5-low-fast runs Claude Code on Cursor; copilot/<model> does the same for Copilot. A prefix overrides the routes for that request.

Migrating from the previous configuration

BYOKEY does not migrate configuration files automatically. Legacy and unknown fields fail configuration loading, and a failed hot reload keeps the last valid configuration. Edit the file by hand:

Previous settingCurrent setting
routes (root)anthropic.routes
responses.defaultresponses.routes.default
responses.models.<alias> with upstream, modelresponses.routes.models.<alias> with provider, model
catalog_model or catalog on an aliasproviders.<provider>.model_overrides.<model>.catalog_model or .catalog
responses.upstreams.<name>providers.<name> (requires base_url)
responses.chatgpt_base_urlproviders.chatgpt.base_url
responses.catalog.provider_names, anthropic.catalog.provider_namesproviders.<name>.display_name
responses.catalog.model_names, anthropic.catalog.model_namesproviders.<provider>.model_overrides.<model>.name
providers.claude.backendanthropic.routes.default
providers.copilot.small_modelRemove; set ANTHROPIC_DEFAULT_HAIKU_MODEL in the client

port, host, proxy_url, log, telemetry and claude_code are unchanged.

Logs

BYOKEY logs one line for each request it sends upstream, when that exchange ends:

INFO http{… model=claude-opus-5-5 stream=true}:upstream{provider=copilot model=claude-opus-5.5 account=default initiator="user" upstream_request_id="00000-…"}: byokey_proxy::exchange: upstream finished outcome="completed" first_byte_ms=812 duration_ms=14233 input_tokens=9 output_tokens=412 cache_read_tokens=51200 cache_write_tokens=0 stop_reason="end_turn"

outcome is one of:

  • completed: the upstream finished its answer.
  • rejected: the upstream answered with an error status. The line carries its status, error_type and upstream_message, such as an organisation policy or a context limit.
  • failed: the connection failed, the stream carried an error, or it stopped or went silent before the end.
  • abandoned: the client went away first, for example Esc in Claude Code.

On Copilot, initiator is user for a prompt you typed and agent for a tool-loop step, which is how Copilot counts premium requests. keepalives counts the comments BYOKEY wrote while the upstream was silent. upstream_message is text the upstream wrote, so it stays in the local log and is never sent to Sentry.

Every line of a request starts with its http{…} span, which names the model and streaming mode the client asked for; the upstream{…} span names the model actually sent. request_id is BYOKEY's id for the request, which the client also receives as the x-request-id header. When Claude Code sends them, client_request_id and session are its x-client-request-id and session id: claude --debug prints the former for each API request, so a request in Claude Code's debug log can be found in BYOKEY's. Management API calls, which byokey tui makes every few seconds, are logged only at debug.

log.level in the config file takes RUST_LOG-style directives, such as debug or info,byokey_proxy=debug, and defaults to info,tarpc=warn. The running server applies a change on the next config reload, without a restart. RUST_LOG, when set, overrides it for the life of the process. A value that does not parse, or that sets no default level (a typo such as degub is read as a module name), stops serve from starting.

log:
  level: info,byokey_proxy=debug
  format: json      # one JSON object per line; default `text`
  file: /path/to/byokey.log   # rotated daily, instead of stdout

Colour is used only when stdout is a terminal and NO_COLOR is unset, so a service's redirected log stays plain text.

Contributing

With Nix and devenv installed, run devenv shell to load the Rust toolchain and build dependencies.

See CONTRIBUTING.md for build commands, architecture details, and coding guidelines.

License

Licensed under either of MIT or Apache-2.0 at your option.

关于 About

Turn AI subscriptions into standard API endpoints. OpenAI & Anthropic compatible gateway — for Amp Code, Cursor, Factory CLI, and more.
ai-gatewayampanthropic-apiclaudecopilotcursorgeminillmoauthopenai-apiproxyrust

语言 Languages

Rust99.2%
JavaScript0.5%
Shell0.3%
Makefile0.0%
Nix0.0%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
378
Total Commits
峰值: 83次/周
Less
More

核心贡献者 Contributors