proxy

NameLast commit messageLast commit date
.githubci(homebrew): remove workflow for Homebrew formula bump1 year ago
authsrebuild branch1 year ago
cmdfeat: prefer util.WritablePath() for logs and local storage1 year ago
docsfeat(auth, docs): add SDK guides and local password support for management1 year ago
examplesrefactor(auth): replace `TokenRecord` with `coreauth.Auth` and migrate `TokenStore` to `coreauth.Store`1 year ago
internalMerge pull request #145 from router-for-me/path1 year ago
sdkfeat(iflow): add masked token logs; increase refresh lead to 24h1 year ago
.dockerignorefeat(store): introduce `GitTokenStore` for token persistence via Git backend1 year ago
.env.exampleAdd Object Storage1 year ago
.gitignoreAdd Object Storage1 year ago
.goreleaser.ymlrebuild branch1 year ago
config.example.yamlrefactor(provider): remove Gemini Web cookie-based support1 year ago
docker-build.ps1rebuild branch1 year ago
docker-build.shrebuild branch1 year ago
docker-compose.ymlAdd Object Storage1 year ago
Dockerfilefeat(store): introduce `GitTokenStore` for token persistence via Git backend1 year ago
go.modAdd Object Storage1 year ago
go.sumAdd Object Storage1 year ago
LICENSEUpdate LICENSE to reflect extended copyright ownership1 year ago
MANAGEMENT_API.mdrefactor(provider): remove Gemini Web cookie-based support1 year ago
MANAGEMENT_API_CN.mdrefactor(provider): remove Gemini Web cookie-based support1 year ago
README.mdUPDATE README1 year ago
README_CN.mdUPDATE README1 year ago
README.md

CLI Proxy API

English | 中文

A proxy server that provides OpenAI/Gemini/Claude/Codex compatible API interfaces for CLI.

It now also supports OpenAI Codex (GPT models) and Claude Code via OAuth.

So you can use local or multi-account CLI access with OpenAI(include Responses)/Gemini/Claude-compatible clients and SDKs.

Chinese providers have now been added: Qwen Code, iFlow.

Features

  • OpenAI/Gemini/Claude compatible API endpoints for CLI models
  • OpenAI Codex support (GPT models) via OAuth login
  • Claude Code support via OAuth login
  • Qwen Code support via OAuth login
  • iFlow support via OAuth login
  • Streaming and non-streaming responses
  • Function calling/tools support
  • Multimodal input support (text and images)
  • Multiple accounts with round-robin load balancing (Gemini, OpenAI, Claude, Qwen and iFlow)
  • Simple CLI authentication flows (Gemini, OpenAI, Claude, Qwen and iFlow)
  • Generative Language API Key support
  • Gemini CLI multi-account load balancing
  • Claude Code multi-account load balancing
  • Qwen Code multi-account load balancing
  • iFlow multi-account load balancing
  • OpenAI Codex multi-account load balancing
  • OpenAI-compatible upstream providers via config (e.g., OpenRouter)
  • Reusable Go SDK for embedding the proxy (see docs/sdk-usage.md)

Installation

Prerequisites

  • Go 1.24 or higher
  • A Google account with access to Gemini CLI models (optional)
  • An OpenAI account for Codex/GPT access (optional)
  • An Anthropic account for Claude Code access (optional)
  • A Qwen Chat account for Qwen Code access (optional)
  • An iFlow account for iFlow access (optional)

Building from Source

  1. Clone the repository:

    git clone https://github.com/luispater/CLIProxyAPI.git
    cd CLIProxyAPI
    
  2. Build the application:

    Linux, macOS:

    go build -o cli-proxy-api ./cmd/server
    

    Windows:

    go build -o cli-proxy-api.exe ./cmd/server
    

Installation via Homebrew

brew install cliproxyapi
brew services start cliproxyapi

Usage

GUI Client & Official WebUI

EasyCLI

A cross-platform desktop GUI client for CLIProxyAPI.

Cli-Proxy-API-Management-Center

A web-based management center for CLIProxyAPI.

Set remote-management.disable-control-panel to true if you prefer to host the management UI elsewhere; the server will skip downloading management.html and /management.html will return 404.

You can set the MANAGEMENT_STATIC_PATH environment variable to choose the directory where management.html is stored.

Authentication

You can authenticate for Gemini, OpenAI, Claude, Qwen, and/or iFlow. All can coexist in the same auth-dir and will be load balanced.

  • Gemini (Google):

    ./cli-proxy-api --login
    

    If you are an existing Gemini Code user, you may need to specify a project ID:

    ./cli-proxy-api --login --project_id <your_project_id>
    

    The local OAuth callback uses port 8085.

    Options: add --no-browser to print the login URL instead of opening a browser. The local OAuth callback uses port 8085.

  • OpenAI (Codex/GPT via OAuth):

    ./cli-proxy-api --codex-login
    

    Options: add --no-browser to print the login URL instead of opening a browser. The local OAuth callback uses port 1455.

  • Claude (Anthropic via OAuth):

    ./cli-proxy-api --claude-login
    

    Options: add --no-browser to print the login URL instead of opening a browser. The local OAuth callback uses port 54545.

  • Qwen (Qwen Chat via OAuth):

    ./cli-proxy-api --qwen-login
    

    Options: add --no-browser to print the login URL instead of opening a browser. Use the Qwen Chat's OAuth device flow.

  • iFlow (iFlow via OAuth):

    ./cli-proxy-api --iflow-login
    

    Options: add --no-browser to print the login URL instead of opening a browser. The local OAuth callback uses port 11451.

Starting the Server

Once authenticated, start the server:

./cli-proxy-api

By default, the server runs on port 8317.

API Endpoints

List Models

GET http://localhost:8317/v1/models

Chat Completions

POST http://localhost:8317/v1/chat/completions

Request body example:

{
  "model": "gemini-2.5-pro",
  "messages": [
    {
      "role": "user",
      "content": "Hello, how are you?"
    }
  ],
  "stream": true
}

Notes:

  • Use a gemini-* model for Gemini (e.g., "gemini-2.5-pro"), a gpt-* model for OpenAI (e.g., "gpt-5"), a claude-* model for Claude (e.g., "claude-3-5-sonnet-20241022"), a qwen-* model for Qwen (e.g., "qwen3-coder-plus"), or an iFlow-supported model (e.g., "tstars2.0", "deepseek-v3.1", "kimi-k2", etc.). The proxy will route to the correct provider automatically.

Claude Messages (SSE-compatible)

POST http://localhost:8317/v1/messages

Using with OpenAI Libraries

You can use this proxy with any OpenAI-compatible library by setting the base URL to your local server:

Python (with OpenAI library)

from openai import OpenAI

client = OpenAI(
    api_key="dummy",  # Not used but required
    base_url="http://localhost:8317/v1"
)

# Gemini example
gemini = client.chat.completions.create(
    model="gemini-2.5-pro",
    messages=[{"role": "user", "content": "Hello, how are you?"}]
)

# Codex/GPT example
gpt = client.chat.completions.create(
    model="gpt-5",
    messages=[{"role": "user", "content": "Summarize this project in one sentence."}]
)

# Claude example (using messages endpoint)
import requests
claude_response = requests.post(
    "http://localhost:8317/v1/messages",
    json={
        "model": "claude-3-5-sonnet-20241022",
        "messages": [{"role": "user", "content": "Summarize this project in one sentence."}],
        "max_tokens": 1000
    }
)

print(gemini.choices[0].message.content)
print(gpt.choices[0].message.content)
print(claude_response.json())

JavaScript/TypeScript

import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: 'dummy', // Not used but required
  baseURL: 'http://localhost:8317/v1',
});

// Gemini
const gemini = await openai.chat.completions.create({
  model: 'gemini-2.5-pro',
  messages: [{ role: 'user', content: 'Hello, how are you?' }],
});

// Codex/GPT
const gpt = await openai.chat.completions.create({
  model: 'gpt-5',
  messages: [{ role: 'user', content: 'Summarize this project in one sentence.' }],
});

// Claude example (using messages endpoint)
const claudeResponse = await fetch('http://localhost:8317/v1/messages', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    model: 'claude-3-5-sonnet-20241022',
    messages: [{ role: 'user', content: 'Summarize this project in one sentence.' }],
    max_tokens: 1000
  })
});

console.log(gemini.choices[0].message.content);
console.log(gpt.choices[0].message.content);
console.log(await claudeResponse.json());

Supported Models

  • gemini-2.5-pro
  • gemini-2.5-flash
  • gemini-2.5-flash-lite
  • gemini-2.5-flash-image
  • gemini-2.5-flash-image-preview
  • gpt-5
  • gpt-5-codex
  • claude-opus-4-1-20250805
  • claude-opus-4-20250514
  • claude-sonnet-4-20250514
  • claude-sonnet-4-5-20250929
  • claude-3-7-sonnet-20250219
  • claude-3-5-haiku-20241022
  • qwen3-coder-plus
  • qwen3-coder-flash
  • qwen3-max
  • qwen3-vl-plus
  • deepseek-v3.2
  • deepseek-v3.1
  • deepseek-r1
  • deepseek-v3
  • kimi-k2
  • glm-4.5
  • glm-4.6
  • tstars2.0
  • And other iFlow-supported models
  • Gemini models auto-switch to preview variants when needed

Configuration

The server uses a YAML configuration file (config.yaml) located in the project root directory by default. You can specify a different configuration file path using the --config flag:

./cli-proxy-api --config /path/to/your/config.yaml

Configuration Options

Parameter Type Default Description
port integer 8317 The port number on which the server will listen.
auth-dir string "~/.cli-proxy-api" Directory where authentication tokens are stored. Supports using ~ for the home directory. If you use Windows, please set the directory like this: C:/cli-proxy-api/
proxy-url string "" Proxy URL. Supports socks5/http/https protocols. Example: socks5://user:pass@192.168.1.1:1080/
request-retry integer 0 Number of times to retry a request. Retries will occur if the HTTP response code is 403, 408, 500, 502, 503, or 504.
remote-management.allow-remote boolean false Whether to allow remote (non-localhost) access to the management API. If false, only localhost can access. A management key is still required for localhost.
remote-management.secret-key string "" Management key. If a plaintext value is provided, it will be hashed on startup using bcrypt and persisted back to the config file. If empty, the entire management API is disabled (404).
remote-management.disable-control-panel boolean false When true, skip downloading management.html and return 404 for /management.html, effectively disabling the bundled management UI.
quota-exceeded object {} Configuration for handling quota exceeded.
quota-exceeded.switch-project boolean true Whether to automatically switch to another project when a quota is exceeded.
quota-exceeded.switch-preview-model boolean true Whether to automatically switch to a preview model when a quota is exceeded.
debug boolean false Enable debug mode for verbose logging.
logging-to-file boolean true Write application logs to rotating files instead of stdout. Set to false to log to stdout/stderr.
usage-statistics-enabled boolean true Enable in-memory usage aggregation for management APIs. Disable to drop all collected usage metrics.
api-keys string[] [] Legacy shorthand for inline API keys. Values are mirrored into the config-api-key provider for backwards compatibility.
generative-language-api-key string[] [] List of Generative Language API keys.
codex-api-key object {} List of Codex API keys.
codex-api-key.api-key string "" Codex API key.
codex-api-key.base-url string "" Custom Codex API endpoint, if you use a third-party API endpoint.
codex-api-key.proxy-url string "" Proxy URL for this specific API key. Overrides the global proxy-url setting. Supports socks5/http/https protocols.
claude-api-key object {} List of Claude API keys.
claude-api-key.api-key string "" Claude API key.
claude-api-key.base-url string "" Custom Claude API endpoint, if you use a third-party API endpoint.
claude-api-key.proxy-url string "" Proxy URL for this specific API key. Overrides the global proxy-url setting. Supports socks5/http/https protocols.
openai-compatibility object[] [] Upstream OpenAI-compatible providers configuration (name, base-url, api-keys, models).
openai-compatibility.*.name string "" The name of the provider. It will be used in the user agent and other places.
openai-compatibility.*.base-url string "" The base URL of the provider.
openai-compatibility.*.api-keys string[] [] (Deprecated) The API keys for the provider. Use api-key-entries instead for per-key proxy support.
openai-compatibility.*.api-key-entries object[] [] API key entries with optional per-key proxy configuration. Preferred over api-keys.
openai-compatibility.*.api-key-entries.*.api-key string "" The API key for this entry.
openai-compatibility.*.api-key-entries.*.proxy-url string "" Proxy URL for this specific API key. Overrides the global proxy-url setting. Supports socks5/http/https protocols.
openai-compatibility.*.models object[] [] The actual model name.
openai-compatibility.*.models.*.name string "" The models supported by the provider.
openai-compatibility.*.models.*.alias string "" The alias used in the API.

Example Configuration File

# Server port
port: 8317

# Management API settings
remote-management:
  # Whether to allow remote (non-localhost) management access.
  # When false, only localhost can access management endpoints (a key is still required).
  allow-remote: false

  # Management key. If a plaintext value is provided here, it will be hashed on startup.
  # All management requests (even from localhost) require this key.
  # Leave empty to disable the Management API entirely (404 for all /v0/management routes).
  secret-key: ""

  # Disable the bundled management control panel asset download and HTTP route when true.
  disable-control-panel: false

# Authentication directory (supports ~ for home directory). If you use Windows, please set the directory like this: `C:/cli-proxy-api/`
auth-dir: "~/.cli-proxy-api"

# API keys for authentication
api-keys:
  - "your-api-key-1"
  - "your-api-key-2"

# Enable debug logging
debug: false

# When true, write application logs to rotating files instead of stdout
logging-to-file: true

# When false, disable in-memory usage statistics aggregation
usage-statistics-enabled: true

# Proxy URL. Supports socks5/http/https protocols. Example: socks5://user:pass@192.168.1.1:1080/
proxy-url: ""

# Number of times to retry a request. Retries will occur if the HTTP response code is 403, 408, 500, 502, 503, or 504.
request-retry: 3

# Quota exceeded behavior
quota-exceeded:
   switch-project: true # Whether to automatically switch to another project when a quota is exceeded
   switch-preview-model: true # Whether to automatically switch to a preview model when a quota is exceeded

# API keys for official Generative Language API
generative-language-api-key:
  - "AIzaSy...01"
  - "AIzaSy...02"
  - "AIzaSy...03"
  - "AIzaSy...04"

# Codex API keys
codex-api-key:
  - api-key: "sk-atSM..."
    base-url: "https://www.example.com" # use the custom codex API endpoint
    proxy-url: "socks5://proxy.example.com:1080" # optional: per-key proxy override

# Claude API keys
claude-api-key:
  - api-key: "sk-atSM..." # use the official claude API key, no need to set the base url
  - api-key: "sk-atSM..."
    base-url: "https://www.example.com" # use the custom claude API endpoint
    proxy-url: "socks5://proxy.example.com:1080" # optional: per-key proxy override

# OpenAI compatibility providers
openai-compatibility:
  - name: "openrouter" # The name of the provider; it will be used in the user agent and other places.
    base-url: "https://openrouter.ai/api/v1" # The base URL of the provider.
    # New format with per-key proxy support (recommended):
    api-key-entries:
      - api-key: "sk-or-v1-...b780"
        proxy-url: "socks5://proxy.example.com:1080" # optional: per-key proxy override
      - api-key: "sk-or-v1-...b781" # without proxy-url
    # Legacy format (still supported, but cannot specify proxy per key):
    # api-keys:
    #   - "sk-or-v1-...b780"
    #   - "sk-or-v1-...b781"
    models: # The models supported by the provider.
      - name: "moonshotai/kimi-k2:free" # The actual model name.
        alias: "kimi-k2" # The alias used in the API.

Git-backed Configuration and Token Store

The application can be configured to use a Git repository as a backend for storing both the config.yaml file and the authentication tokens from the auth-dir. This allows for centralized management and versioning of your configuration.

To enable this feature, set the GITSTORE_GIT_URL environment variable to the URL of your Git repository.

Environment Variables

Variable Required Default Description
MANAGEMENT_PASSWORD Yes The password for management webui.
GITSTORE_GIT_URL Yes The HTTPS URL of the Git repository to use.
GITSTORE_LOCAL_PATH No Current working directory The local path where the Git repository will be cloned. Inside Docker, this defaults to /CLIProxyAPI.
GITSTORE_GIT_USERNAME No The username for Git authentication.
GITSTORE_GIT_TOKEN No The personal access token (or password) for Git authentication.

How it Works

  1. Cloning: On startup, the application clones the remote Git repository to the GITSTORE_LOCAL_PATH.
  2. Configuration: It then looks for a config.yaml inside a config directory within the cloned repository.
  3. Bootstrapping: If config/config.yaml does not exist in the repository, the application will copy the local config.example.yaml to that location, commit, and push it to the remote repository as an initial configuration. You must have config.example.yaml available.
  4. Token Sync: The auth-dir is also managed within this repository. Any changes to authentication tokens (e.g., through a new login) are automatically committed and pushed to the remote Git repository.

PostgreSQL-backed Configuration and Token Store

You can also persist configuration and authentication data in PostgreSQL when running CLIProxyAPI in hosted environments that favor managed databases over local files.

Environment Variables

Variable Required Default Description
MANAGEMENT_PASSWORD Yes Password for the management web UI (required when remote management is enabled).
PGSTORE_DSN Yes PostgreSQL connection string (e.g. postgresql://user:pass@host:5432/db).
PGSTORE_SCHEMA No public Schema where the tables will be created. Leave empty to use the default schema.
PGSTORE_LOCAL_PATH No Current working directory Root directory for the local mirror; the server writes to <value>/pgstore. If unset and CWD is unavailable, /tmp/pgstore is used.

How it Works

  1. Initialization: On startup the server connects via PGSTORE_DSN, ensures the schema exists, and creates the config_store / auth_store tables when missing.
  2. Local Mirror: A writable cache at <PGSTORE_LOCAL_PATH or CWD>/pgstore mirrors config/config.yaml and auths/ so the rest of the application can reuse the existing file-based logic.
  3. Bootstrapping: If no configuration row exists, config.example.yaml seeds the database using the fixed identifier config.
  4. Token Sync: Changes flow both ways—file updates are written to PostgreSQL and database records are mirrored back to disk so watchers and management APIs continue to operate.

Object Storage-backed Configuration and Token Store

An S3-compatible object storage service can host configuration and authentication records.

Environment Variables

Variable Required Default Description
MANAGEMENT_PASSWORD Yes Password for the management web UI (required when remote management is enabled).
OBJECTSTORE_ENDPOINT Yes Object storage endpoint. Include http:// or https:// to force the protocol (omitted scheme → HTTPS).
OBJECTSTORE_BUCKET Yes Bucket that stores config/config.yaml and auths/*.json.
OBJECTSTORE_ACCESS_KEY Yes Access key ID for the object storage account.
OBJECTSTORE_SECRET_KEY Yes Secret key for the object storage account.
OBJECTSTORE_LOCAL_PATH No Current working directory Root directory for the local mirror; the server writes to <value>/objectstore. If unset, defaults to current CWD.

How it Works

  1. Startup: The endpoint is parsed (respecting any scheme prefix), a MinIO-compatible client is created in path-style mode, and the bucket is created when missing.
  2. Local Mirror: A writable cache at <OBJECTSTORE_LOCAL_PATH or CWD>/objectstore mirrors config/config.yaml and auths/.
  3. Bootstrapping: When config/config.yaml is absent in the bucket, the server copies config.example.yaml, uploads it, and uses it as the initial configuration.
  4. Sync: Changes to configuration or auth files are uploaded to the bucket, and remote updates are mirrored back to disk, keeping watchers and management APIs in sync.

OpenAI Compatibility Providers

Configure upstream OpenAI-compatible providers (e.g., OpenRouter) via openai-compatibility.

  • name: provider identifier used internally
  • base-url: provider base URL
  • api-key-entries: list of API key entries with optional per-key proxy configuration (recommended)
  • api-keys: (deprecated) simple list of API keys without proxy support
  • models: list of mappings from upstream model name to local alias

Example with per-key proxy support:

openai-compatibility:
  - name: "openrouter"
    base-url: "https://openrouter.ai/api/v1"
    api-key-entries:
      - api-key: "sk-or-v1-...b780"

Document preview limited. Open the file to continue