Skip to content

Repository files navigation

Hoopilot

npm version CI

Hoopilot is a local OpenAI- and Anthropic-compatible proxy for GitHub Copilot accounts. It runs on Bun and exposes OpenAI-style /v1/chat/completions, /v1/responses, /v1/completions, and /v1/models routes, plus Claude Code-compatible /v1/messages and /v1/messages/count_tokens routes.

This project uses GitHub Copilot service endpoints and is not an official GitHub product. Upstream behavior can change without notice. Use Hoopilot only with accounts and usage patterns you are allowed to use.

Contents

Highlights

  • GitHub Copilot OAuth login via GitHub's device flow — prints a one-time code and opens your browser when possible — with a local credential store.
  • OpenAI-compatible Chat Completions, Responses, legacy Completions, and model-list routes.
  • Anthropic Messages compatibility for Claude Code and other Anthropic-style clients.
  • Bundled codexx launcher that runs Codex against a local Hoopilot server with the right Responses API provider settings.
  • Local API-key gate, loopback-safe defaults, structured logs, Prometheus metrics, and Copilot quota reporting.
  • Self-contained live dashboard at /dashboard showing usage and status metrics in real time.
  • npm package, standalone binaries, Docker image, and self-update support for release binaries.

Requirements

  • A GitHub account with an active GitHub Copilot subscription.
  • Bun 1.3 or newer to run from npm or source — the CLI runs on the Bun runtime, so bun must be on your PATH (this applies to npx @openhoo/hoopilot too).
  • Nothing extra for the standalone binary or Docker image: both bundle the runtime, so neither needs Bun or Node.js installed.

Quick start

Sign in once, then start the proxy on localhost:

npx @openhoo/hoopilot login
npx @openhoo/hoopilot

By default the server listens on 127.0.0.1:4141 and accepts local requests without authentication, so any placeholder works as the client key:

export OPENAI_BASE_URL=http://127.0.0.1:4141/v1
export OPENAI_API_KEY=hoopilot

PowerShell:

$env:OPENAI_BASE_URL = "http://127.0.0.1:4141/v1"
$env:OPENAI_API_KEY = "hoopilot"

To require clients to authenticate — recommended whenever you expose the proxy beyond localhost — set HOOPILOT_API_KEY to a strong, unique secret of at least 24 characters and send that value as the client key:

export HOOPILOT_API_KEY=$(openssl rand -hex 24)
npx @openhoo/hoopilot

Run Codex through Hoopilot after the server is running:

npx --package @openhoo/hoopilot codexx

Install

Choose the method that fits your environment: npm if you already have Bun, a standalone binary for a dependency-free install, or Docker to run Hoopilot as a long-lived service.

npm

Run without installing:

npx @openhoo/hoopilot

Or install the package globally with either npm or Bun:

npm install -g @openhoo/hoopilot
# or
bun add -g @openhoo/hoopilot

The package is published ESM-only: the CLIs (hoopilot, codexx) and the library entry (import { startHoopilotServer } from "@openhoo/hoopilot") both require an ESM loader. There is no CommonJS (require()) entry — it was dropped because Hoopilot is a Bun/ESM-native tool, not because any dependency forced it.

Standalone binary

When npm is unavailable but GitHub releases are reachable, install a prebuilt self-contained binary. Node.js and Bun are not required to run the binary.

Linux/macOS:

curl -fsSL https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.sh | sh

Windows PowerShell:

irm https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.ps1 | iex

The installer detects your OS, CPU architecture, and libc, downloads the matching binary, verifies its SHA-256 checksum, and installs it to ~/.local/bin on Linux/macOS or %LOCALAPPDATA%\Programs\hoopilot on Windows. Override the install directory with HOOPILOT_INSTALL_DIR, or pin a version:

curl -fsSL https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.sh | sh -s -- --version <version> --dir ~/bin
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.ps1))) -Version <version>

The standalone installer also installs a codexx wrapper next to hoopilot. Re-run the installer if hoopilot works but your shell does not recognize codexx; the installer stops the installed hoopilot.exe if needed and replaces the existing files in place.

Docker

Run Hoopilot as a long-lived service from the published multi-arch image on the GitHub Container Registry (linux/amd64 and linux/arm64). The commands below are the same on Windows (PowerShell or cmd), macOS, and Linux — only the shell prompt differs.

Keyless local quick start

Published on loopback (127.0.0.1) only, the proxy is unreachable from other hosts, so no client API key is needed. Three commands — nothing to export, no keys to generate or keep in sync:

# 1. Sign in once; the OAuth credential persists in the named volume.
docker run --rm -it -v hoopilot-data:/data ghcr.io/openhoo/hoopilot login

# 2. Start the proxy: loopback-only, no key.
docker run -d --name hoopilot --restart unless-stopped -p 127.0.0.1:4141:4141 -e HOOPILOT_ALLOW_UNAUTHENTICATED=1 -v hoopilot-data:/data ghcr.io/openhoo/hoopilot

# 3. Run Codex through it from any directory — no key, no setup.
npx --package @openhoo/hoopilot codexx --yolo

Every line is a single command that pastes as-is into PowerShell, cmd, bash, or zsh. Step 3 needs the codex CLI on your PATH; codexx defaults to gpt-5.5 and sends a throwaway key that the keyless proxy accepts (Bun users can swap npx --package @openhoo/hoopilot for bunx).

Tags follow the release version, for example ghcr.io/openhoo/hoopilot:1.3, :1.3.0, and :latest. The image listens on 0.0.0.0:4141 (required so Docker port publishing can reach it), runs as a non-root user, and stores its OAuth credential at /data/auth.json by default. Override that path with HOOPILOT_AUTH_FILE.

Docker Compose hosting

From a clone of this repo, the bundled docker-compose.yml builds the local image, stores the Copilot OAuth credential in the hoopilot-data Docker volume, and publishes only 127.0.0.1:4141 by default:

git clone https://github.com/openhoo/hoopilot.git
cd hoopilot
cp .env.example .env

# Sign in once. Follow the GitHub device-code URL printed by the container.
docker compose run --rm hoopilot login

# Start the service in the background.
docker compose up -d --build

# Check it.
docker compose ps
curl http://127.0.0.1:4141/healthz

The one-time docker compose run --rm hoopilot login command writes /data/auth.json inside the same named volume used by the long-running service, so restarts and container recreates keep the login. Re-run the login command only if the Copilot credential expires, you switch GitHub accounts, or a model that should be available still does not appear after updating.

For the default loopback-only compose setup, .env.example leaves HOOPILOT_API_KEY empty and sets HOOPILOT_ALLOW_UNAUTHENTICATED=1, so local clients can use any placeholder key:

export OPENAI_BASE_URL=http://127.0.0.1:4141/v1
export OPENAI_API_KEY=hoopilot
npx --package @openhoo/hoopilot codexx

If you publish the port on a non-loopback interface or put Hoopilot behind a reverse proxy, set a strong API key in .env and send the same value from clients:

HOOPILOT_API_KEY=$(openssl rand -hex 24)
printf 'HOOPILOT_API_KEY=%s\nHOOPILOT_ALLOW_UNAUTHENTICATED=0\n' "$HOOPILOT_API_KEY" > .env
docker compose up -d --build

export OPENAI_BASE_URL=http://127.0.0.1:4141/v1
export OPENAI_API_KEY=$HOOPILOT_API_KEY

To run from the published GHCR image instead of building from a checkout, create a compose file like this and use the same login and start commands:

services:
  hoopilot:
    image: ghcr.io/openhoo/hoopilot:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:4141:4141"
    environment:
      HOOPILOT_ALLOW_UNAUTHENTICATED: "1"
      HOOPILOT_API_KEY: ${HOOPILOT_API_KEY:-}
    volumes:
      - hoopilot-data:/data

volumes:
  hoopilot-data:

Use docker compose logs -f hoopilot when you need to watch startup, login, or upstream Copilot errors.

Exposing the proxy beyond loopback

The image binds 0.0.0.0 and cannot tell whether the published port is loopback-only, so it fails closed: drop the -e HOOPILOT_ALLOW_UNAUTHENTICATED=1 opt-in (or map the port to a non-loopback interface) and it refuses to start without a strong, unique HOOPILOT_API_KEY of at least 24 characters. Short, repeated, and well-known demo keys are rejected. Clients then send that key as Authorization: Bearer <key> or x-api-key: <key>:

export HOOPILOT_API_KEY=$(openssl rand -hex 24)
docker run -d --name hoopilot --restart unless-stopped -p 4141:4141 -e HOOPILOT_API_KEY -v hoopilot-data:/data ghcr.io/openhoo/hoopilot

With compose, a set HOOPILOT_API_KEY takes precedence over the keyless default: export HOOPILOT_API_KEY=$(openssl rand -hex 24) then docker compose up -d. To run unauthenticated on a non-loopback bind anyway — for example behind your own authenticating proxy — keep HOOPILOT_ALLOW_UNAUTHENTICATED=1. Point codexx at a keyed server by exporting the same HOOPILOT_API_KEY (or CODEXX_API_KEY) in its environment.

Update

Standalone binaries update themselves in place from the latest GitHub release:

hoopilot update

npm installs report when a newer version is available and print the right command. Hoopilot checks GitHub at most once a day in the background. Disable the check with --no-update-check, HOOPILOT_NO_UPDATE_CHECK, or NO_UPDATE_NOTIFIER.

Docker Compose deployments update by replacing the container image, not by running hoopilot update inside the container.

For the bundled repo compose file, pull the latest source and rebuild:

git pull --ff-only
docker compose up -d --build
docker compose ps

For a compose file that uses image: ghcr.io/openhoo/hoopilot:latest, pull the new image and recreate the service:

docker compose pull
docker compose up -d
docker compose ps

The hoopilot-data volume is preserved in both cases, so the Copilot login normally survives updates.

Running the proxy

Login uses GitHub's browser/device flow, verifies that the returned OAuth token can reach the Copilot API, and stores it locally:

hoopilot login

Default credential paths:

  • Linux/macOS: $HOME/.config/hoopilot/auth.json
  • Windows: %APPDATA%\hoopilot\auth.json

Override the path with HOOPILOT_AUTH_FILE or --auth-file.

Start the server:

hoopilot --port 4141

By default Hoopilot listens on 127.0.0.1:4141. If HOOPILOT_API_KEY is unset, local requests are accepted without client authentication. Binding to a non-loopback host requires either a strong, unique HOOPILOT_API_KEY of at least 24 characters or the explicit --allow-unauthenticated / HOOPILOT_ALLOW_UNAUTHENTICATED=1 opt-in. Short, repeated, and well-known demo keys are always rejected on a non-loopback host, even with the unauthenticated opt-in.

When an API key is configured, clients may send it as either Authorization: Bearer <key> or x-api-key: <key>.

Cross-origin browser requests are always blocked, even when an API key is set, so a malicious web page cannot drive the local proxy. Requests from loopback origins are allowed; to permit specific web origins, list them in HOOPILOT_ALLOWED_ORIGINS (comma-separated).

Client setup

OpenAI-compatible clients

export OPENAI_BASE_URL=http://127.0.0.1:4141/v1
export OPENAI_API_KEY=hoopilot

The client key is arbitrary unless you set HOOPILOT_API_KEY (see Running the proxy). Available models depend on your Copilot plan; list the ones your account can use with:

hoopilot models

Claude Code and Anthropic-style clients

export ANTHROPIC_BASE_URL=http://127.0.0.1:4141
export ANTHROPIC_AUTH_TOKEN=hoopilot
claude

Hoopilot accepts the local key as x-api-key too, so ANTHROPIC_API_KEY also works for clients that send Anthropic's standard API-key header.

Codex

Use the bundled codexx command after Hoopilot is running:

codexx

Without a global install:

npx --package @openhoo/hoopilot codexx

With the keyless Docker quick start, no key is involved: codexx --yolo works from any directory because codexx sends a throwaway key that the loopback-only proxy accepts. If the server does require an API key, set HOOPILOT_API_KEY (or CODEXX_API_KEY) in the codexx environment to match.

codexx does not start Hoopilot and does not alter your shell environment. It starts codex with a temporary hoopilot model provider pointed at http://127.0.0.1:4141/v1, uses the Responses API wire format, disables Responses WebSockets for that provider, maps HOOPILOT_API_KEY (or a random throwaway key when none is set) to OPENAI_API_KEY for the child process, disables Codex's managed network proxy (-c permissions.workspace.network.enabled=false), and removes standard proxy variables from the spawned Codex process.

codexx also sets Codex's temporary provider stream idle timeout to 120 seconds by default, so a silent Responses stream fails and Codex's normal stream retry path can run instead of leaving the turn apparently stuck. Override with CODEXX_STREAM_IDLE_TIMEOUT_MS, or set it to 0 to use Codex's own default.

Why the network proxy is disabled. Codex ships a managed network proxy that routes the agent's traffic through a local proxy (port 3128) and enforces a domain allowlist. Because the local Hoopilot server isn't on that allowlist, leaving the proxy on makes Codex's request to Hoopilot fail with an instant 403 Squid error. The proxy has two independent gates — the network_proxy feature flag and the permissions.workspace.network.enabled config — and disabling only the feature is not always enough, so codexx turns off both (--disable network_proxy and -c permissions.workspace.network.enabled=false) and requests reach Hoopilot directly.

codexx defaults to gpt-5.5 with model_reasoning_effort="xhigh". Before starting Codex, it checks /v1/models and reports if the logged-in Copilot account does not advertise the requested model. Set CODEXX_MODEL to one of the listed models, or log in with a Copilot account that has access to the default model.

Codex compaction posts to /v1/responses/compact for OpenAI- and Azure-named providers. Hoopilot handles that route with a unary Copilot Responses request and returns the { "output": [...] } summary Codex expects, so compaction works through either codexx or a direct OpenAI-compatible base URL override.

Authentication

Hoopilot supports one upstream credential flow: GitHub Copilot OAuth browser login.

hoopilot login
hoopilot

Direct bearer tokens, GitHub CLI token fallback, classic GitHub PATs, and fine-grained GitHub PATs are not supported.

Re-run hoopilot login after upgrading Hoopilot if Copilot reports a supported model as unavailable. Older stored tokens can have a reduced model set.

To print the verified OAuth token for another local tool, use --print-key (the alias --print-token also works). Login status goes to stderr, so stdout contains only the token.

hoopilot login --print-key | sed 's/^/COPILOT_OAUTH_TOKEN=/' >> .env

PowerShell:

hoopilot login --print-key |
  ForEach-Object { "COPILOT_OAUTH_TOKEN=$_" } |
  Add-Content -Encoding utf8 .env

Docker:

docker run --rm -v hoopilot-data:/data ghcr.io/openhoo/hoopilot login --print-key \
  | sed 's/^/COPILOT_OAUTH_TOKEN=/' >> .env

Logging

Hoopilot uses Pino for structured logs. Server startup, request errors, upstream Copilot failures, model-list fallback, auth failures, and update-check diagnostics are logged with stable event names and request IDs. Successful request completion logs are disabled by default; pass --access-log or set HOOPILOT_ACCESS_LOG=1 to enable them.

Logs never include request bodies, prompt text, completions, stream chunks, OAuth tokens, API keys, authorization headers, cookies, or auth-file contents.

Console logs default to pretty output at info level:

hoopilot --log-level info --log-format pretty

When access logs are enabled, pretty logs keep common request and diagnostic fields inline for terminal use:

INFO [16:40:14]: request completed component=server event=http.request.completed method=POST path=/v1/chat/completions status=200 duration=42.37ms stream=true requestId=req-test

For newline-delimited JSON:

hoopilot --log-level info --log-format json

Incoming x-request-id headers are preserved on responses. If a request has no ID, Hoopilot generates one and returns it as x-request-id.

Metrics and usage

Hoopilot tracks token usage, request counts, and latency in memory while the server runs. It can also report your GitHub Copilot account quota and premium-request usage, plus your GitHub REST API rate-limit budget.

  • GET /metrics returns Prometheus text (text/plain; version=0.0.4; charset=utf-8). It exposes request counters, upstream call counters, token counters by model and type, a request-duration histogram, an in-flight gauge, process start-time and uptime gauges (hoopilot_process_start_time_seconds, hoopilot_uptime_seconds), Copilot quota gauges, and GitHub REST API rate-limit gauges (hoopilot_github_ratelimit_limit, _remaining, _used, _reset_timestamp_seconds, _retry_after_seconds, labelled by resource) — the quota and rate-limit series appear after /v1/usage has been fetched at least once. Counters reset to zero on restart, which Prometheus handles natively.
  • GET /v1/usage returns JSON combining the proxy metrics snapshot with live Copilot quota fetched from GitHub and cached for 60 seconds. If quota cannot be read, copilot is null and copilot_error explains why. The snapshot's proxy.githubRateLimit field reports the most recent GitHub REST rate-limit budget per resource (limit, remaining, used, resetAt, retryAfterSeconds, observedAt).
  • hoopilot usage prints your Copilot plan and quota — and, when GitHub returns them, your GitHub API rate-limit budget — from the command line.

Token usage is read from the upstream usage object when Hoopilot is already parsing a compatibility response, or when full token accounting is enabled. For streaming chat completions, usage is only available when the client sends stream_options: {"include_usage": true}; Hoopilot does not inject that flag.

The default HOOPILOT_USAGE_ACCOUNTING=basic mode skips token extraction from pass-through response bodies and SSE streams while still recording usage from compatibility responses Hoopilot already has to parse. Set HOOPILOT_USAGE_ACCOUNTING=full when exact pass-through stream/body token accounting matters more than CPU use. Set HOOPILOT_USAGE_ACCOUNTING=off to skip token accounting entirely. Request counts, upstream counts, latency, in-flight metrics, /metrics, and /v1/usage still work in every mode. The hoopilot_token_extraction_total{outcome="extracted"|"missing"} counter (mirrored in /v1/usage as proxy.tokens.extraction) tracks how often a completion reported usage versus not.

GitHub API usage is read from the x-ratelimit-* response headers that api.github.com returns on the copilot_internal/user quota call Hoopilot already makes, so it costs no extra request. (The Copilot completion host api.githubcopilot.com does not currently emit these headers, so per-completion rate-limit data is not yet available there.)

/metrics and /v1/usage are subject to the same HOOPILOT_API_KEY gate as the other routes.

Dashboard

GET /dashboard serves a self-contained live dashboard — open http://127.0.0.1:4141/dashboard in a browser. It renders the proxy's status and usage in real time: request rate, tokens/sec, in-flight requests, uptime, a per-route request table, status-code and latency breakdowns, token usage by model, your Copilot quota, upstream-call health, and a throughput chart. It polls /v1/usage every few seconds (interval and pause are adjustable in the header) and computes rates client-side, with dark and light themes.

The page is a single HTML document with no external resources — no CDN, fonts, or images — so it works offline, in the Docker image, and in the standalone binary. The HTML shell is served without the API-key gate (it contains no secrets) so a browser navigation can load it; the data it polls from /v1/usage stays behind the gate, and when HOOPILOT_API_KEY is set the page prompts for the key (stored in the browser and sent as x-api-key). Cross-origin browser access is blocked as for every route, so open the dashboard by navigating to it directly rather than linking from another site.

Troubleshooting

Codex auth errors

Hoopilot does not return raw 403 responses to Codex for authentication or Copilot-entitlement failures. Local Hoopilot API-key problems return 401 invalid_api_key; OAuth credential and upstream Copilot auth failures return 401 copilot_auth_error.

Verify browser login and the local proxy before retrying Codex:

hoopilot login
hoopilot --port 4141

Then, in another shell:

curl http://127.0.0.1:4141/v1/models
codexx

If you started the server with HOOPILOT_API_KEY, add -H "Authorization: Bearer $HOOPILOT_API_KEY" to the curl command and set the same HOOPILOT_API_KEY for codexx.

If /v1/models returns 401 copilot_auth_error, rerun hoopilot login and confirm that the GitHub account has active Copilot access.

Configuration

Settings written as ENV / --flag accept either the environment variable or the command-line flag.

Server and local-client settings:

Setting Description
HOST / --host Host to listen on. Default: 127.0.0.1 for local runs; Docker sets 0.0.0.0.
PORT / --port Port to listen on. Default: 4141.
HOOPILOT_API_KEY / --api-key Require clients to send Authorization: Bearer <key> or x-api-key: <key>. Must be a strong, unique secret of at least 24 characters on non-loopback binds; short, repeated, and well-known demo keys are rejected.
--api-key-file Read the local API key from a file instead of argv.
HOOPILOT_ALLOWED_ORIGINS Comma-separated browser origins allowed to make cross-origin requests. Loopback origins are always allowed; every other origin is blocked.
HOOPILOT_ALLOW_UNAUTHENTICATED / --allow-unauthenticated Allow non-loopback binds without a local API key.
HOOPILOT_STREAM_MODE / --stream-mode auto, live, or buffer. auto buffers streams for Windows standalone binaries. HOOPILOT_STREAMING_PROXY_MODE is accepted as an alias.
HOOPILOT_USAGE_ACCOUNTING / --usage-accounting basic, full, or off. Default: basic. basic avoids token extraction from pass-through bodies/streams; full tracks all reported usage; off skips token accounting.

Copilot and GitHub settings:

Setting Description
HOOPILOT_AUTH_FILE / --auth-file OAuth credential store path.
HOOPILOT_GITHUB_CLIENT_ID GitHub OAuth app client ID override. COPILOT_GITHUB_CLIENT_ID is accepted as an alias.
HOOPILOT_GITHUB_DOMAIN GitHub domain override. Default: github.com.
COPILOT_API_BASE_URL / --copilot-api-base-url Upstream Copilot API base URL. Default: https://api.githubcopilot.com.
HOOPILOT_GITHUB_API_BASE_URL GitHub REST API base URL used for quota lookup. Default: https://api.github.com.
HOOPILOT_ALLOW_UNSAFE_UPSTREAM=1 Allow sending the stored OAuth token to nonstandard HTTPS Copilot/GitHub API hosts. Use only for trusted test or enterprise endpoints.

Logging and update settings:

Setting Description
HOOPILOT_LOG_LEVEL / --log-level trace, debug, info, warn, error, fatal, or silent. Default: info.
HOOPILOT_LOG_FORMAT / --log-format pretty or json. Default: pretty.
HOOPILOT_ACCESS_LOG / --access-log / --no-access-log Successful request logs are disabled by default. Set 1/true or pass --access-log to enable them. Client and server errors are still logged.
HOOPILOT_UPSTREAM_TIMEOUT_MS Time to wait for Copilot response headers before returning 504 copilot_timeout. Default: 120000; set 0 to disable.
HOOPILOT_UPSTREAM_STREAM_IDLE_TIMEOUT_MS Time to wait for bytes on a Copilot response body before failing the stream so clients can retry. Default: 120000; set 0 to disable.
HOOPILOT_NO_UPDATE_CHECK / --no-update-check Disable background update checks. NO_UPDATE_NOTIFIER is also honored.

The default service profile is low-resource:

hoopilot

For the quietest local service, also use HOOPILOT_LOG_LEVEL=warn HOOPILOT_NO_UPDATE_CHECK=1.

If you prefer fewer stream timers and can tolerate clients handling stalled upstream streams themselves, also set HOOPILOT_UPSTREAM_STREAM_IDLE_TIMEOUT_MS=0.

codexx settings:

Setting Description
CODEXX_BASE_URL OpenAI-compatible Hoopilot base URL. Default: http://127.0.0.1:4141/v1.
CODEXX_API_KEY API key sent to Hoopilot. Falls back to HOOPILOT_API_KEY, then a random per-run key for an unauthenticated local server.
CODEXX_CODEX_BIN Codex executable to run. Default: codex.
CODEXX_MODEL Codex model to use. Default: gpt-5.5.
CODEXX_MODEL_REASONING_EFFORT Codex reasoning effort. Default: xhigh.
CODEXX_STREAM_IDLE_TIMEOUT_MS Codex Responses stream idle timeout for the temporary Hoopilot provider. Default: 120000; set 0 to use Codex's own default.
CODEXX_SKIP_MODEL_PREFLIGHT=1 Skip the /v1/models availability check before starting Codex.

CLI reference

hoopilot [serve] [options]
hoopilot codexx [codex options] [prompt]
hoopilot login [options]
hoopilot models [options]
hoopilot usage [options]
hoopilot update

Commands:

serve                             Start the proxy server (default)
codexx                            Run Codex through the local Hoopilot server
login                             Sign in through GitHub OAuth in a browser and verify Copilot access
models                            List available GitHub Copilot model IDs
usage                             Show GitHub Copilot quota and premium-request usage
update, upgrade                   Update hoopilot to the latest release

Options:

-p, --port <port>                 Port to listen on. Default: 4141
    --host <host>                 Host to listen on. Default: 127.0.0.1
    --api-key <key>               Require clients to send Authorization: Bearer <key> or x-api-key: <key>
    --api-key-file <path>         Read the local API key from a file instead of argv
    --auth-file <path>            OAuth credential store path
    --copilot-api-base-url <url>  Copilot API base URL override
    --print-key                   Login: print the received OAuth token to stdout
    --log-level <level>           trace, debug, info, warn, error, fatal, or silent
    --log-format <format>         json or pretty. Default: pretty
    --stream-mode <mode>          auto, live, or buffer. Auto buffers Windows standalone streams.
    --no-update-check             Do not check GitHub for a newer release
    --allow-unauthenticated       Allow non-loopback bind without --api-key
-h, --help                        Show help
-v, --version                     Show version

Endpoints

  • GET / and GET /healthz
  • GET /dashboard
  • GET /metrics
  • GET /v1/models
  • GET /v1/usage
  • POST /v1/chat/completions
  • POST /v1/responses
  • POST /v1/responses/compact
  • POST /v1/completions
  • POST /v1/messages
  • POST /v1/messages/count_tokens

/v1/chat/completions and /v1/responses are proxied to the matching Copilot endpoints as directly as possible. /v1/messages translates Anthropic Messages requests and responses to Copilot's Responses endpoint. /v1/messages/count_tokens returns a local token estimate for Claude Code preflights because Copilot does not expose Anthropic's count-tokens route. /v1/completions translates legacy completion requests and responses to the closest chat-completions equivalent. GET /v1/responses returns an explicit unsupported-WebSocket response; codexx configures Codex to use HTTP Responses instead.

Development

bun install
bun run check

Useful scripts:

bun run test
bun run test:coverage
bun run typecheck
bun run build
bun run biome:fix

Release

Commits merged to main are evaluated by hooversion after CI passes. When a release is produced, the release workflow creates the release commit, tag, and GitHub release automatically, publishes the package through npm trusted publishing, then cross-compiles standalone binaries for every supported platform with scripts/build-binaries.sh and attaches them plus a SHA256SUMS manifest to the GitHub release. Build all binaries locally with:

bun run build:binaries

Configure npm trusted publishing for @openhoo/hoopilot on npmjs.com before relying on automatic publication. The workflow uses GitHub Actions OIDC with npm publish --access public --provenance.

License

MIT. See LICENSE.

About

OpenAI-compatible local proxy for GitHub Copilot accounts.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages