npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dianshuv/copilot-api

v0.20.1

Published

Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!

Downloads

3,310

Readme

Copilot API Proxy (Fork)

[!NOTE] This is a fork of @hsupu/copilot-api, which itself is a fork of ericc-ch/copilot-api, with additional improvements and bug fixes.

[!WARNING] This is a reverse-engineered proxy of GitHub Copilot API. It is not supported by GitHub, and may break unexpectedly. Use at your own risk.

New Features (over @hsupu/copilot-api)

  • Responses API endpoint: /v1/responses passthrough for codex models (e.g., gpt-5.2-codex, gpt-5.3-codex) used by tools like OpenCode. Includes stream ID synchronization for @ai-sdk/openai compatibility.
  • SubagentStart marker support: Detects __SUBAGENT_MARKER__ injected by Claude Code hooks to override X-Initiator header to "agent" for subagent requests, ensuring correct credit tier usage. Includes a ready-to-use Claude plugin (claude-plugin/).
  • Token analytics tab: The /history page includes a Tokens tab with per-model token usage summary table and cumulative ECharts line chart for visualizing API consumption over time.
  • Real-time history updates: The /history UI uses WebSocket for live updates instead of polling, with automatic fallback to polling and exponential backoff reconnection.
  • Graceful shutdown: 4-phase shutdown sequence — stops accepting requests, waits for in-flight requests to complete, sends abort signal, then force-closes. Configurable via --shutdown-graceful-wait and --shutdown-abort-wait.
  • Stream repetition detection: Detects when models get stuck in repetitive output loops using KMP-based pattern matching and logs a warning.
  • Stale request reaping: Automatically force-fails requests that exceed a configurable maximum age (default 600s) to prevent resource leaks.
  • PostHog analytics: Optional PostHog Cloud integration (--posthog-key) sends per-request token usage events for long-term trend analysis. Free tier (1M events/month) is more than sufficient for individual use.
  • GitHub Copilot CLI emulation: All upstream requests to GitHub — device-flow login, /copilot_internal/user bootstrap, and CAPI model/chat calls — carry the official GitHub Copilot CLI's (@github/copilot) identity: its copilot-integration-id (copilot-developer-cli), editor-version/user-agent (copilot/<version>), x-github-api-version, and a persistent x-client-machine-id (stored at ~/.local/share/copilot-api/machine_id). The CAPI Bearer is the GitHub OAuth token itself — the CLI does not perform a separate token exchange. The login flow uses the CLI's own OAuth app, so new logins request the read:user, read:org, repo, and gist scopes; existing tokens keep working without re-authentication.

Quick Start

Install from npm (Recommended)

# Run directly with npx
npx @dianshuv/copilot-api start

# Or install globally
npm install -g @dianshuv/copilot-api
copilot-api start

Development

# Start the server (foreground, production mode)
make up

# Stop the server (graceful shutdown)
make down

Command Reference

| Command | Description | |---------|-------------| | start | Start the API server (handles auth if needed) | | login | Run GitHub authentication flow only | | logout | Remove the local GitHub token file (does not revoke authorization on GitHub) | | debug | Display diagnostic information |

Start Command Options

| Option | Description | Default | |--------|-------------|---------| | --port, -p | Port to listen on | 4141 | | --host, -H | Host/interface to bind to (0.0.0.0 = all interfaces) | 127.0.0.1 | | --verbose, -v | Enable verbose logging | false | | --account-type, -a | Account type (individual, business, enterprise) | individual | | --no-rate-limit | Disable adaptive rate limiting | false | | --github-token, -g | Provide GitHub token directly (or GH_TOKEN env) | none | | --posthog-key | PostHog API key for token usage analytics (opt-in) | none | | --api-key | Proxy API key for inbound authentication (see Authentication). Empty = disabled | none | | --allow-token-endpoint | Opt-in to expose GET /token (echoes the raw GitHub OAuth token; requires --api-key too). COPILOT_ALLOW_TOKEN_ENDPOINT=1 env twin. | false |

Hidden Models

By default the proxy hides 30 stale / duplicate / unused upstream model ids from its listing surfaces (/v1/models and the startup banner).

Important: this is a display filter only. The remaining POST endpoints (/v1/chat/completions, /v1/messages, /v1/responses) do not reject hidden ids — an explicit POST with a hidden id is still forwarded to upstream verbatim. (The embedding and Gemini ids in the list have no callable endpoint in this proxy at all; they're hidden purely to denoise the /v1/models listing — the upstream /models catalogue still returns them.)

To see the full catalogue or change the blacklist, edit src/lib/hidden-models.ts and re-publish (this fork uses /publish).

Currently hidden (grouped):

  • Legacy GPTgpt-3.5-turbo, gpt-3.5-turbo-0613, gpt-4, gpt-4-0613, gpt-4-0125-preview
  • GPT-4o familygpt-4o, gpt-4o-mini, gpt-4-o-preview, gpt-4o-2024-05-13, gpt-4o-2024-08-06, gpt-4o-2024-11-20, gpt-4o-mini-2024-07-18
  • GPT-4.1 familygpt-4.1, gpt-4.1-2025-04-14, gpt-41-copilot
  • Older / smaller GPT-5gpt-5-mini, gpt-5.3-codex
  • All embeddingstext-embedding-ada-002, text-embedding-3-small, text-embedding-3-small-inference
  • Older Geminigemini-2.5-pro, gemini-3-flash-preview
  • Older / variant Claudeclaude-opus-4.5, claude-opus-4.6, claude-opus-4.7-high, claude-opus-4.7-xhigh, claude-sonnet-4.5
  • Special-purposemai-code-1-flash-internal, trajectory-compaction

API Endpoints

OpenAI Compatible

| Endpoint | Method | Description | |----------|--------|-------------| | /v1/chat/completions | POST | Chat completions | | /v1/models | GET | List available models | | /v1/responses | POST | Responses API (for codex models) |

Anthropic Compatible

| Endpoint | Method | Description | |----------|--------|-------------| | /v1/messages | POST | Messages API | | /v1/messages/count_tokens | POST | Token counting | | /v1/event_logging/batch | POST | Event logging (no-op) |

Utility

| Endpoint | Method | Description | |----------|--------|-------------| | / | GET | Server status | | /usage | GET | Copilot usage stats | | /token | GET | Current CAPI Bearer (= raw GitHub OAuth token). Disabled by default; requires --allow-token-endpoint and --api-key, otherwise 403. | | /health | GET | Health check | | /history | GET | Request history Web UI with token analytics (enabled by default) | | /history/api/* | GET/DELETE | History API endpoints |

Auto-Truncate

When enabled (default), auto-truncate automatically compacts conversation history when it exceeds the model's token limit. This prevents request failures due to context overflow.

  • Token-based truncation: Uses the model's max_context_window_tokens from the Copilot API to determine when truncation is needed. A 2% safety margin is applied.
  • No preset byte limit: There is no hardcoded request body size limit. If the Copilot API returns a 413 (Request Entity Too Large), the proxy dynamically learns the byte limit and applies it to subsequent requests.
  • Orphan filtering: After truncation, orphaned tool results (without matching tool calls) are automatically removed.

Authentication

By default the proxy is unauthenticated: every endpoint is open and any request passes through unchanged. You can optionally protect the proxy's inbound surface with a Proxy API key (this is your own secret for this proxy — it is unrelated to the GitHub OAuth / Copilot token the proxy uses upstream). When a key is configured, all endpoints except / and /health require it (fail-closed: any route not on that exemption list — including future ones — is protected). Genuine CORS preflight OPTIONS requests are also let through (they carry no payload), so browser clients aren't tripped by an opaque preflight failure.

Enabling it

Provide the key via either source:

  • --api-key <key> flag
  • COPILOT_API_KEY environment variable

Rules:

  • Precedence: when both are set to a non-empty value, the flag wins and the env value is ignored.
  • Trim + empty disables: each source is trimmed first; a value that is empty or whitespace-only (--api-key "", COPILOT_API_KEY=) counts as not provided. If neither source yields a non-empty value, auth stays disabled (the default).

The startup banner prints whether auth is on/off and, when on, the source (flag / env) — but never the key value itself.

[!CAUTION] Ambient COPILOT_API_KEY footgun. Because the env var is read on every start, a COPILOT_API_KEY exported anywhere the process can see it (your shell profile, a .env sourced into the environment, a systemd unit, a container env) silently enables authentication for that instance — even when you did not pass --api-key. If a previously-open instance suddenly returns 401, check for an inherited COPILOT_API_KEY. The startup banner's source: env line makes this visible.

Network binding

The proxy binds loopback (127.0.0.1) by default, so an unconfigured instance is reachable only from the local machine. To expose it on your network — behind auth, a tunnel, or inside a container — opt into an all-interfaces bind explicitly:

copilot-api start --host 0.0.0.0

The bind host resolves with --host flag > HOST env > 127.0.0.1. Note that a HOST env var — inherited from your shell or a container — also widens the bind: HOST=0.0.0.0 opens all interfaces just like the flag. A blank HOST (HOST=, or HOST=$UNSET) is ignored and falls back to the loopback default, so an accidentally-empty env var can't silently expose the proxy. The startup banner always reports the real bind address (127.0.0.1 for the loopback default, 0.0.0.0 for an all-interfaces bind, or the narrowed host you passed), so a wide-open bind is never hidden.

Choosing a key

Use a high-entropy secret (e.g. openssl rand -hex 32), not a guessable word. The comparison is constant-time, but a weak key can still be guessed offline or brute-forced over the network.

Migrating clients

Once a key is configured, clients that previously sent a placeholder must send the real key. Two header shapes are accepted and either is sufficient:

  • OpenAI-compatible clientsAuthorization: Bearer <key> (the scheme is matched case-insensitively; a bare value with no Bearer prefix is also tolerated).
  • Anthropic-native clientsx-api-key: <key>.

If both headers are present, a match on either one is accepted.

Per client:

  • opencode (opencode.json): set provider.<name>.options.apiKey from "dummy" to your real key (the @ai-sdk/openai-compatible provider sends it as Authorization: Bearer).
  • Claude Code (.claude/settings.json, see below): change ANTHROPIC_AUTH_TOKEN from "dummy" to your real key. Claude Code talks to the proxy's /v1/messages (Anthropic) surface; the auth gate accepts the token from either header.
  • Raw OpenAI SDKAuthorization: Bearer <key>; raw Anthropic SDKx-api-key: <key>.

[!TIP] Keep the key out of shell history. Don't paste the literal key onto a command line (e.g. curl -H "Authorization: Bearer sk-real-key" …), or it lands in ~/.zsh_history. Read it from an env var or a file instead:

# Put the key in an env var read from a non-echoed prompt or a 0600 file,
# then reference the var — the literal secret never appears in argv/history.
read -rs COPILOT_API_KEY            # typed key is not echoed or saved
export COPILOT_API_KEY
curl -H "Authorization: Bearer $COPILOT_API_KEY" http://127.0.0.1:4141/v1/models

A failed auth returns 401 with a client-appropriate body: requests to the Anthropic surface (/v1/messages, /v1/messages/count_tokens) get {"type":"error","error":{"type":"authentication_error", …}}; every other endpoint gets the OpenAI-style {"error":{"code":"invalid_api_key", …}}. Missing and wrong keys return the identical body (no oracle), always with a WWW-Authenticate: Bearer header.

Browser tools when auth is on

The request logger does not record the Authorization / x-api-key headers, so your key never lands in logs. But the browser-based tools can't send a custom header, so when auth is on they stop working:

  • History UI (/history) and its live-update WebSocket (/history/ws) — the page load and socket upgrade are gated like any other protected route.
  • External Usage Viewer (the ericc-ch.github.io link in the banner) — it fetches /usage, which is now protected, so it can't load your data.

Workarounds:

  • Run a separate local, unauthenticated instance (no --api-key; the default 127.0.0.1 bind keeps it local) for the browser UI, or
  • Hit the history JSON API directly with a key, e.g. curl -H "Authorization: Bearer $COPILOT_API_KEY" http://127.0.0.1:4141/history/api/entries.

Using with Claude Code

Create .claude/settings.json in your project:

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:4141",
    "ANTHROPIC_AUTH_TOKEN": "dummy",
    "ANTHROPIC_MODEL": "claude-opus-4.8",
    "ANTHROPIC_SMALL_FAST_MODEL": "claude-haiku-4.5",
    "DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
  },
  "permissions": {
    "deny": ["WebSearch"]
  }
}