Run a local OpenAI-compatible proxy for every major cloud AI service. Store API keys once and let any client app — desktop, mobile, or web — talk to http://localhost instead of registering keys in every tool.
Getting Started
1. Launch the App
Open AIProxyServer. On first launch the proxy starts automatically and listens on port 8421 of your local machine. The main window shows three sections:
- Proxy Server — current status, base URL, and a button to start or stop the listener
- Bearer Token — optional authentication toggle and token display
- Providers — every supported cloud AI provider, with a Set API Key button per row
2. Add Your First API Key
- Pick any provider from the Providers list (for example OpenAI (ChatGPT))
- Click Get API key to open the provider's console in your browser, then create or copy a key
- Click Set API Key on the same row and paste the value into the dialog
- Click Save. The status label flips to Configured in green
3. Connect a Client App
Point any OpenAI-compatible client at the proxy. The Base URL is http://localhost:8421/<provider>/v1. The provider segment chooses which cloud receives the request.
# Example: OpenAI Python SDK pointed at the proxy
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8421/openai/v1",
api_key="not-used-but-required-by-sdk",
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)
The client never sees the real key. AIProxyServer attaches the upstream credentials when it forwards the request.
Interface Overview
Proxy Server Panel
| Field | Description |
|---|---|
| Status | Running when the listener is active, Stopped otherwise. |
| Base URL | The address client apps should use, including hostname and port. Click Copy to copy it to the clipboard. |
| Start / Stop button | Toggle the HTTP listener without quitting the app. |
Bearer Token Panel
- Require Bearer Token authentication — checkbox that turns auth on or off. Off by default for hassle-free local use.
- Token field — read-only display of the current token. Shown as dots; use Copy to grab it.
- Regenerate — issue a fresh random token. Existing clients must be updated with the new value.
Providers Panel
One row per supported cloud provider. Each row shows:
- The display name (for example Claude (Anthropic))
- Configuration status — green Configured when an API key is saved, gray Not configured otherwise
- The URL path your clients use, e.g.
/anthropic/v1/chat/completions - Set API Key — opens a dialog to enter credentials
- Get API key — opens the provider's console in your browser
Supported Providers
Eleven cloud AI services are bundled. Most use the OpenAI Chat Completions format natively and are proxied as-is. Three (Anthropic, Gemini, ERNIE) speak their own protocols; AIProxyServer translates requests and responses on the fly so your client only ever sees OpenAI shapes.
| Provider | Route prefix | What you need |
|---|---|---|
| OpenAI (ChatGPT) | /openai/v1 | API key from platform.openai.com |
| Claude (Anthropic) | /anthropic/v1 | API key from Anthropic Console |
| Gemini (Google) | /gemini/v1 | API key from Google AI Studio |
| Grok (xAI) | /grok/v1 | API key from xAI Console |
| Azure OpenAI (Copilot) | /copilot/v1 | API key plus your deployment endpoint URL |
| Perplexity | /perplexity/v1 | API key from Perplexity settings |
| Groq | /groq/v1 | API key from Groq Cloud |
| DeepSeek | /deepseek/v1 | API key from DeepSeek Platform |
| Kimi (Moonshot) | /kimi/v1 | API key from Moonshot Console |
| Qwen (DashScope) | /qwen/v1 | API key from Alibaba DashScope |
| ERNIE (Baidu) | /ernie/v1 | Both API Key and Secret Key from Baidu Qianfan |
Provider-specific notes
- Azure OpenAI — paste the full deployment endpoint into the Endpoint Base URL field, for example
https://my-resource.openai.azure.com/openai/deployments/gpt-4o. The proxy appends/chat/completions?api-version=2024-02-01automatically. - ERNIE — Baidu Qianfan uses OAuth, so both API Key and Secret Key are required. AIProxyServer requests and caches access tokens behind the scenes.
- Gemini — authentication is by URL query parameter; the proxy adds it for you. Free-tier per-minute quotas still apply.
API Reference
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /health | Liveness check. Returns service status and provider list. No auth required. |
| GET | /v1/providers | Configured providers and metadata. |
| GET | /<provider>/v1/models | Model list for the given provider, in OpenAI format. |
| POST | /<provider>/v1/chat/completions | OpenAI Chat Completions request. Pass stream:true for SSE. |
Streaming
When the client sends "stream": true, the proxy responds with Server-Sent Events in OpenAI's format:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant"},...}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":"Hello"},...}]}
data: [DONE]
Anthropic and Gemini native streams are translated to this shape so all clients can use a single parser.
Authentication header
When Require Bearer Token authentication is on, send the token from the main window with every request:
Authorization: Bearer <token-shown-in-app>
Settings
Open the Settings window from the gear icon in the bottom toolbar.
| Setting | Default | Description |
|---|---|---|
| Proxy Port | 8421 | TCP port the listener binds to. Change requires restarting the proxy. |
| Auto Start Server | On | Start the proxy when the app launches. |
| Allow LAN Access | Off | When off, the proxy only binds to 127.0.0.1. When on, other devices on your Wi-Fi can reach the proxy. |
| Require Bearer Token | Off | When on, every request must include the token displayed in the main window. Strongly recommended whenever Allow LAN Access is on. |
Client Examples
cURL
# OpenAI (passthrough)
curl http://localhost:8421/openai/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello"}]
}'
# Claude via the same OpenAI shape
curl http://localhost:8421/anthropic/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 1024
}'
OpenAI Python SDK
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8421/gemini/v1",
api_key="placeholder", # ignored when Bearer Token is off
)
stream = client.chat.completions.create(
model="gemini-2.0-flash",
messages=[{"role": "user", "content": "Tell me a joke"}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)
Flutter / Dart
// Using any OpenAI-compatible Dart client
final client = OpenAIClient(
baseUrl: 'http://localhost:8421/anthropic/v1',
apiKey: '', // unused when Bearer Token is off
);
localhost with your Mac's LAN IP (shown in the Base URL field when Allow LAN Access is on).Tips
- Leave the Bearer Token off while you are developing locally; turn it on the moment you enable LAN access.
- Use distinct Base URLs per provider in your client code so you can switch providers by changing one constant.
- The proxy auto-starts but you can stop it temporarily from the main window if a port conflict occurs.
- If a provider's free tier rate-limits you, the upstream error message is forwarded verbatim. No retry logic is hidden from the client.
- The
/v1/providersendpoint is useful to discover which providers are configured at runtime.
Troubleshooting
The proxy will not start
- Another process may already use port 8421. Change the port in Settings and restart the proxy.
- Check the system log for the error message displayed at start time.
A request returns 401 Unauthorized
- The Bearer Token requirement is on but the client did not send a matching
Authorization: Bearer ...header. - The provider's own API key may be invalid — the upstream error is forwarded so check the message body.
A request returns "API key is not configured"
- Open the Providers list and click Set API Key for the provider in question.
- For ERNIE, both API Key and Secret Key must be filled. For Azure OpenAI, the Endpoint Base URL is also required.
Mobile device cannot reach the proxy
- Turn on Allow LAN Access in Settings.
- Use the LAN IP shown in the Base URL field, not
localhost. - Ensure both devices are on the same Wi-Fi network and that your firewall allows incoming connections on the proxy port.
Streaming responses arrive all at once
- Make sure your client sends
"stream": truein the JSON body. - Some HTTP libraries buffer SSE by default — disable response buffering on the client side.
Privacy
- API keys are stored encrypted with Fernet in
~/Library/Application Support/AIProxyServer/credentials.enc. The encryption key inmaster.keyhas 0600 permissions. - The Bearer Token, when enabled, is also stored only in the encrypted vault and never written to the regular settings file.
- The proxy only forwards requests to providers you have explicitly configured. It makes no other outbound calls.
- No telemetry, no analytics, no crash reporting.
- Default network binding is
127.0.0.1only. LAN exposure is opt-in. - Conversation contents are not stored. AIProxyServer forwards bytes and immediately forgets them.