copilot-proxy

copilot-proxy is a local GitHub Copilot API proxy. It exposes OpenAI-style and Anthropic-style local endpoints, then forwards requests to https://api.githubcopilot.com with auth and header adaptation.

Features

Default listen address: 127.0.0.1:4000.

Runtime boundary

Install

One-command install (latest release)

curl -fsSL https://rexxiang.github.io/copilot-proxy/install.sh | sh

Default install path is ~/.local/bin/copilot-proxy (no sudo required).

Set a custom install directory with INSTALL_DIR:

curl -fsSL https://rexxiang.github.io/copilot-proxy/install.sh | INSTALL_DIR="$HOME/.local/bin" sh

If ~/.local/bin is not in your PATH, add:

export PATH="$HOME/.local/bin:$PATH"

Build from source

The c-shared build emits ./bin/copilot-proxy-c.so (or the platform-appropriate shared library) plus the generated header ./bin/copilot-proxy-c.h.

Usage

1) Authenticate a GitHub account

copilot-proxy auth login

This uses GitHub device flow and stores credentials in ~/.config/copilot-proxy/auth.json.

2) Start the proxy

With TUI monitor (default when TTY is available):

copilot-proxy

3) Configure Claude Code

Point Claude Code to the local proxy by setting:

export ANTHROPIC_BASE_URL='http://127.0.0.1:4000'

4) Configure messages agent detection and rate limiting (optional)

messages_agent_detection_request_mode defaults to true for /v1/messages.

~/.config/copilot-proxy/settings.json:

{
  "messages_agent_detection_request_mode": true,
  "rate_limit_seconds": 0,
  "claude_haiku_fallback_models": [
    "gpt-5-mini",
    "grok-code-fast-1"
  ],
  "reasoning_policies": {
    "gpt-5-mini@responses": "low",
    "grok-code-fast-1@chat": "none"
  }
}

rate_limit_seconds uses whole seconds and enforces a global cooldown between one proxied request finishing and the next starting. 0 disables rate limiting.

claude_haiku_fallback_models is an ordered list of explicit replacement models to try for claude-haiku-* requests. If none are available, the proxy automatically falls back to the highest available claude-haiku-* model.

reasoning_policies values must be none|low|medium|high.
For /v1/messages requests, reasoning effort is only sent upstream when the selected model reports supported levels via /models capability metadata. Map-style settings (for example required_headers and reasoning_policies) are storage fields; TUI edits should be done through dedicated array-object shadow fields.

Account Management

C ABI

cmd/copilot-proxy-c now exposes a stateless C ABI. The library does not keep runtime handles, queues, account state, login sessions, settings state, model-selection state, or observability aggregates. Callers provide token/model resolution callbacks and own all state. The exported execution path uses the same stateless runtime/api engine flow as the server runtime, including model rewrite, endpoint selection, and /v1/messages protocol translation. Building the shared workflow produces ./bin/copilot-proxy, ./bin/copilot-proxy-c.so, and the generated header ./bin/copilot-proxy-c.h. Use mise x -- build for the combined CLI + shared library or mise x -- build:c-shared for the library alone.

Entry points

int CopilotProxy_Execute(
  const char *request_json,
  CopilotProxyResolveTokenFn resolve_token,
  CopilotProxyResolveModelFn resolve_model,
  CopilotProxyResultCallback on_result,
  CopilotProxyTelemetryCallback on_telemetry,
  void *user_data,
  char **final_error_out
);

int CopilotProxyAuth_RequestCode(char **challenge_out, char **error_out);
int CopilotProxyAuth_PollToken(const char *device_payload, char **token_out, char **error_out);
int CopilotProxyUser_FetchInfo(const char *token, char **info_out, char **error_out);
int CopilotProxyModels_Fetch(const char *token, char **models_out, char **error_out);
void CopilotProxy_FreeCString(char *ptr);

Callback contracts:

typedef int (*CopilotProxyResolveTokenFn)(const char *account_ref, char **token_out, char **error_out, void *user_data);
typedef int (*CopilotProxyResolveModelFn)(const char *model_id, char **model_json_out, char **error_out, void *user_data);
typedef void (*CopilotProxyResultCallback)(int status_code, const char *headers_json, const uint8_t *body, size_t body_len, const char *error_message, void *user_data);
typedef void (*CopilotProxyTelemetryCallback)(const char *event_json, void *user_data);

request_json is the JSON encoding of types.RequestInvocation (Method, Path, optional Header, and Body as base64).

Execution semantics

Testing