PeaProxy

Local multi-provider AI gateway โœฆ CLI + localhost UI

โ† Back to Home

Point coding tools at one local OpenAI-shaped, Claude-shaped, and Responses endpoint. Use keys and local runtimes first; optionally attach subscription OAuth at your own risk; fail over on 429/401.

Status: CLI + localhost UI at 127.0.0.1:8317. Tagged v3.1.1 is the current release. Schema stays 1. v3 routes for cost (pea/auto, pea/economy, pea/free, pea/local) and does not substitute a model you named. It includes a live catalog, failover policies, image generations + embeddings (API-key OpenAI-compat when the catalog tags them), and the v2 request engine (attempt budget, stream prelude, cooldowns, client connect helpers). Subscription OAuth (Claude Pro/Max/Team/Enterprise, Codex, Gemini/Antigravity, xAI, Kimi, Meta Muse, Copilot) is ToS/ban risk, so prefer official API keys. Also: API keys + free/local providers (llama.cpp, vLLM, Jan, GPT4All, NIM, Workers AI, SambaNova, Ollama Cloud), OpenCode Go API key, POST /v1/responses (native Codex OAuth passes tools through), honest quota remaining on Health. Requires Go 1.26+ for go install.

PathWhenRisk
API keyOfficial provider console / AI Studio (anthropic, openai, google/gemini, xai, Groq, โ€ฆ)Supported. Prefer this.
Local / no keyOllama, LM Studio, llama.cpp, vLLM, Jan, GPT4All, software you already runSupported.
Subscription OAuthpeaproxy auth login --provider โ€ฆ for Claude Pro/Max/Team/Enterprise, ChatGPT/Codex, Gemini/Antigravity, xAI, Kimi, Meta Muse, or GitHub CopilotToS/ban risk. At your own risk. Authors not liable.
OpenCode GoSubscribe at opencode.ai/authOfficial API key (adapter: opencode_go). Distinct from Zen. Not OAuth.
Qwen consumer OAuthn/aNot yet (no CPA flow). Use a Qwen API key with openai_compat.
Factory / Droid upstreamn/aNot yet (no public consumer chat OAuth). Use Droid as a client of PeaProxy.

Homebrew (macOS / Linux)

brew tap ks1686/tap brew install --cask peaproxy

Arch (AUR)

paru -Sy peaproxy-bin

Scoop (Windows)

scoop bucket add ks1686 https://github.com/ks1686/scoop-bucket scoop install peaproxy

Go install (tagged v3.1.1)

go install github.com/ks1686/peaproxy/cmd/peaproxy@v3.1.1

@latest installs the highest release tag (currently v3.1.1). Installs to ~/go/bin/peaproxy; put that directory on PATH. peaproxy -v reports that tag for go install of a release and for release builds. Needs Go 1.26+.

Linux binary (amd64)

curl -Lo peaproxy.tar.gz https://github.com/ks1686/peaproxy/releases/download/v3.1.1/peaproxy_3.1.1_linux_amd64.tar.gz tar -xzf peaproxy.tar.gz && sudo mv peaproxy /usr/local/bin/

Also on the release: linux/darwin/windows amd64 + arm64 (zip on Windows). macOS release and Homebrew cask binaries are Developer ID signed and notarized.

First serve writes ~/.config/peaproxy/config.yaml if missing. Tokens and inline keys go to the OS keychain (encrypted file fallback), not plaintext YAML.

Run

peaproxy --version
peaproxy serve
peaproxy auth login --provider anthropic
# UI + OpenAI/Claude wires at http://127.0.0.1:8317/  (auth is ToS/ban risk)

Captured from live peaproxy serve plus a local OpenAI-compat mock. No API keys or OAuth tokens appear in the images.

PeaProxy Accounts tab with local and API-key onboarding CTAs first
First-run Accounts: local / API-key onboarding CTAs first. Subscription OAuth is last-resort (ToS/ban risk; authors are not liable).
PeaProxy Catalog tab with live ListModels and image_out modality tag
Catalog: live ListModels with pin/rename overlays. image_out is a modality tag on the row.
PeaProxy Showcase generating an image via POST /v1/images/generations
Showcase: image_out one-click generate via POST /v1/images/generations (never faked as chat). The lime square is a throwaway mock upstream, not a photoreal generator.
PeaProxy Request log redacted inspector
Request log: opt-in redacted inspector (requestLog: true or the Settings / Request log toggle).
PeaProxy Settings showing loopback bind and secret backend
Settings: loopback bind, secret backend, request-log toggle, catalog overlay counts. Tokens and API keys are not shown.
PeaProxy Health tab with adapter ListModels status and cooldown overlay
Health: adapter ListModels status, cooldown overlay, and provider-reported remaining when known.

Live catalog

Models come from live ListModels, with no hand-maintained allowlist. Hide is listing-only; optional pin/rename overlays (UI and peaproxy catalog). Routing is unchanged.

Local wires

OpenAI /v1/chat/completions, Claude /v1/messages (true SSE), and Codex /v1/responses. Native Codex OAuth passes tools through (tools, tool_choice, function-call items); only stream_options is dropped. Other adapters round-trip function tools via chat and do not execute them.

Image generations

POST /v1/images/generations for API-key OpenAI-compat when the catalog tags image_out. Showcase one-click generates. Subscription OAuth adapters refuse clearly; there is no fake chat image path.

Embeddings

POST /v1/embeddings for API-key OpenAI-compat when the catalog tags embeddings. Showcase can try. OAuth / Messages-only adapters refuse clearly; there are no fake vectors.

Honest quota remaining

Health / peaproxy health / GET /admin/health show provider-reported remaining when known (rate-limit headers; OpenRouter GET /key). Unknown remaining is omitted, never invented as 0 or unlimited.

CLI + localhost UI

No macOS / Windows tray, by design. Accounts, Catalog, Showcase, Clients, Health, Request log, and Settings in the browser on loopback. First-run onboarding CTAs; Settings shows bind, LAN, and secret-backend status.

Keys, free, and local

Ollama (local or Cloud), LM Studio, llama.cpp, vLLM, Jan, GPT4All, Groq, Cerebras, Google AI Studio, xAI, Hugging Face, NVIDIA NIM, Cloudflare Workers AI, SambaNova, Anthropic/OpenAI/OpenRouter keys, OpenCode Zen, OpenCode Go (API key, distinct from Zen), custom OpenAI-compat. Presets show env var names, never values.

Subscription OAuth

v3.1.1 includes Claude (Pro/Max/Team/Enterprise), Codex, Gemini/Antigravity, xAI, Kimi, Meta Muse, and GitHub Copilot login. Ban/ToS risk; prefer API keys. See Security.

Failover

429/401/503/529 and retryable rate-limit / overloaded / auth-expired bodies move to the next account; policies round-robin (default), fill-first, and sticky. Cooled accounts are not re-hit (503 + Retry-After). Usage is persisted next to the config as usage.json.

v3 cost routing

On by default. pea/auto, pea/economy, pea/free, and pea/local choose a live model for cost. A model you name is never substituted. Spend ceiling fails closed when spend cannot be measured. Details: docs/V3.md.

Spend ceiling + free-only

optimization.spendCeilingUSD caps spend in a rolling window and fails closed when spend cannot be measured. optimization.freeOnly refuses any deployment that cannot prove a call stays free, including a model you named. Inspect with GET /admin/policy or peaproxy optimization status|explain.

Grouped accounts + 8 paid presets

Accounts UI is grouped. New API-key presets: DeepSeek, Mistral, Z.AI, MiniMax, Together, Fireworks, Alibaba Coding Plan, Cohere. Only Cohere is live-verified; the rest show (not verified) and mean it.

Cursor subscription upstream

cursor_agent runs your Cursor subscription through Cursor's own cursor-agent CLI (ask mode, read-only, no tool calling). POSIX-only. ToS/ban risk.

Carried context + local assistant

pea_search retrieves earlier context, bounded at 4 rounds, for tool-using non-streaming requests only; every round is billed by the provider. The local assistant is off by default and loopback only.

v2 request engine

One attempt budget, stream prelude check, cooldowns, and client connect helpers. Schema stays 1.

Harness presets

peaproxy clients show for Cursor, Claude Code, OpenCode, Pi, Codex, Amp, Continue, Cline (YAML / /v1 polish), and Droid (Factory client preset only, not an upstream), plus clients verify.

CommandPurpose
serveListen 127.0.0.1:8317 + UI (writes first-run config)
--versionRelease tag on a release build or go install of a tag; dev for a dirty local build
authSubscription OAuth (--provider anthropic|openai|gemini|xai|kimi|kimi-ai|meta|copilot). Prints a ToS/ban-risk warning. --print-url / --device / --no-browser. Prefer API keys. Qwen and Factory are not yet. OpenCode Go is an API key (--provider opencode-go explains).
accountsConfigured provider accounts (list / add <preset>)
modelsLive catalog (--filter all|free|paid|local|subscription_oauth)
catalogListing overlays (pin / rename / hide) matching the Catalog UI
requestsOpt-in inspector (tail when request log is on)
healthAdapter health / quota remaining / provider-reported remaining when known / cooldowns matching GET /admin/health
statusBind / config path / version
configpath / show / validate (--strict-config exits non-zero on keys this version does not read) / init
optimizationv3 policy (status / explain <model>)
completionShell completion script (bash / zsh / fish / powershell)
clientsHarness presets (list / show / verify [--chat])
curl -s http://127.0.0.1:8317/v1/models
curl -s http://127.0.0.1:8317/v1/images/generations \
  -H 'Content-Type: application/json' \
  -d '{"model":"dall-e-3","prompt":"a pea pod icon"}'
curl -s http://127.0.0.1:8317/v1/embeddings \
  -H 'Content-Type: application/json' \
  -d '{"model":"text-embedding-3-small","input":"hello pea"}'
peaproxy clients show cursor
peaproxy clients show opencode      # includes /v1
peaproxy clients show claude-code   # does NOT include /v1
peaproxy clients show pi            # both wires; cloak off
peaproxy clients show codex         # Responses API
peaproxy clients show droid         # Factory Droid BYOK client
peaproxy clients verify cursor --chat
PathStatus
GET /v1/modelsLive list; hide/expose affect listing only
GET /v0/catalogRich catalog (tier, modalities, privacy, hidden/routable)
POST /v1/chat/completionsStream + non-stream; failover on retryable status/bodies; cooled accounts are not re-hit (503 + Retry-After)
POST /v1/messagesNative Anthropic SSE or translated OpenAI stream
POST /v1/responsesCodex / OpenAI Responses (native OAuth passes tools through; else translated via chat)
POST /v1/images/generationsOpenAI Images API for models tagged image_out; refused (no chat fake) otherwise
POST /v1/embeddingsOpenAI Embeddings API for models tagged embeddings; refused (no chat fake) otherwise
GET /UI: Accounts, Catalog, Showcase, Clients, Health, Request log, Settings
GET /healthzLiveness (LAN warning flags; no admin token)
GET /admin/healthBind, adapter health, provider-reported remaining when known, account cooldowns (token required off loopback)
GET /admin/quotaPer-account quota remaining plus the provider honesty matrix (unknown omitted, never invented)
GET /admin/policyResolved v3 optimization switches, spend against the ceiling, whether spend could be measured (unset ceiling is null, never 0)
ToS / ban liability. Subscription OAuth through a local proxy (Claude Pro/Max/Team/Enterprise, ChatGPT/Codex, Gemini/Antigravity, xAI, Kimi, Meta Muse, GitHub Copilot) may violate a providerโ€™s terms and can result in account suspension or ban. You proceed at your own risk. PeaProxy authors are not liable for bans, suspensions, lost subscriptions, lost data, or any other damages. The official, lower-risk path is an API key. Details: docs/OAUTH.md.

Default bind is loopback. Binding 0.0.0.0 requires --allow-lan and a non-empty admin token. Never log secrets; the opt-in request log is redacted. OpenCode Zen free models may train on prompts; see catalog privacy notes. GitHub Models is retired and is not a provider.

Ready to run a local gateway?

PeaProxy is open-source and MIT licensed. v3.1.1 includes subscription OAuth at your own risk. Prefer official API keys.