AIClient-2-API: The Lightweight, OpenAI-Compatible Gateway for Google Gemini, OpenAI, Claude, and Beyond
A step-by-step guide for junior developers, power users, and small teams who want one universal endpoint for every major large-language-model provider.
Table of Contents
-
Why You Need a Unified API Gateway -
What AIClient-2-API Actually Does -
Architecture at a Glance (No Jargon) -
Installation & First Run in 10 Minutes -
Everyday Usage Examples -
Advanced Tricks for Teams and Power Users -
Troubleshooting & Common Pitfalls -
Extending the Gateway for New Providers -
Legal Notes & Credits
1. Why You Need a Unified API Gateway
If you have ever built a chatbot, a VS Code extension, or a simple web app that calls a large-language-model (LLM), you know the pain:
-
Different keys, different URLs, different rate limits. -
Some services block entire regions. -
Switching from OpenAI to Claude means rewriting request code.
AIClient-2-API removes all of that friction. You run one small Node.js server on your laptop, in Docker, or on a VPS. Every client—LobeChat, NextChat, a Python script, or even curl—points to the same local address. Behind the scenes the gateway silently translates each request to the right upstream provider and returns the response in perfect OpenAI format.
Benefits you will notice immediately:
2. What AIClient-2-API Actually Does
In one sentence: It is a tiny reverse proxy that speaks OpenAI on the outside and Gemini, OpenAI, Claude, or Kiro on the inside.
You pick the upstream provider at startup:
-
gemini-cli-oauth
– Uses the Google Gemini CLI behind the scenes; automatic OAuth token refresh -
openai-custom
– Your own OpenAI key or any OpenAI-compatible endpoint -
claude-custom
– Your own Anthropic key -
claude-kiro-oauth
– Free Claude access via the Kiro ecosystem
3. Architecture at a Glance (No Jargon)
You do not need to understand the code to use the gateway, but a high-level picture helps when you debug or extend it.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Your App │───────▶│ Gateway │───────▶│ Real Service │
│ (OpenAI fmt) │◀───────│ (Translator) │◀───────│(Gemini,etc.) │
└──────────────┘ └──────────────┘ └──────────────┘
Key files you may open one day:
The project uses classic design patterns—Adapter, Strategy, Factory—so adding a new provider is roughly:
-
Create a new folder under src/
. -
Implement two tiny JavaScript classes (adapter + strategy). -
Register the classes in adapter.js
.
That is it. No core logic changes required.
4. Installation & First Run in 10 Minutes
4.1 Prerequisites
-
Node.js 20 or newer (check with node -v
) -
Git (or download the ZIP from GitHub)
4.2 Clone and Install
git clone https://github.com/your-org/AIClient-2-API.git
cd AIClient-2-API
npm install # installs ~10 lightweight dependencies
4.3 Create Your First Config
Copy-paste the snippet below into a new file named config.json
. Replace the placeholder strings with your real keys or leave them empty for the OAuth modes.
{
"REQUIRED_API_KEY": "my-secret-123",
"HOST": "0.0.0.0",
"SERVER_PORT": 3000,
"MODEL_PROVIDER": "gemini-cli-oauth",
"OPENAI_API_KEY": "",
"OPENAI_BASE_URL": "https://api.openai.com/v1",
"CLAUDE_API_KEY": "",
"CLAUDE_BASE_URL": "https://api.anthropic.com",
"PROJECT_ID": "gcp-project-123",
"PROMPT_LOG_MODE": "console"
}
Quick field guide:
4.4 First Run
node src/api-server.js
You should see:
AIClient-2-API listening on http://0.0.0.0:3000
Provider set to: gemini-cli-oauth
Prompt logs → console
If you chose Gemini CLI mode, a browser window will pop up asking for your Google account. Grant the permission once; the gateway will refresh tokens automatically.
5. Everyday Usage Examples
5.1 Health Check
curl http://localhost:3000/health
Response:
{"status":"ok","provider":"gemini-cli-oauth","uptime":"12s"}
5.2 List Models
curl http://localhost:3000/v1/models \
-H "Authorization: Bearer my-secret-123"
You will get a JSON array that looks exactly like OpenAI’s /v1/models
answer, regardless of the upstream provider.
5.3 Simple Chat (No Streaming)
curl http://localhost:3000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-123" \
-d '{
"model": "gemini-2.5-flash",
"messages": [
{"role": "user", "content": "Explain quantum tunneling like I am 12."}
]
}'
5.4 Chat with Streaming
Add "stream": true
and use -N
so curl displays each token as it arrives:
curl -N http://localhost:3000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-123" \
-d '{
"model": "claude-3-opus-20240229",
"messages": [{"role": "user", "content": "Write a haiku about debugging."}],
"stream": true
}'
5.5 Vision (Image + Text)
Images must be base64-encoded data URLs. The gateway forwards them transparently.
curl http://localhost:3000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-123" \
-d '{
"model": "gemini-2.5-flash",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "What is this logo?"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."}}
]
}]
}'
5.6 Switching Providers on the Fly
You have two ways:
-
Restart with a new provider:
node src/api-server.js --model-provider claude-custom --claude-api-key sk-ant-xxx
-
Use path-based routing (no restart):
# Gemini curl http://localhost:3000/gemini-cli-oauth/v1/chat/completions ... # Claude curl http://localhost:3000/claude-custom/v1/chat/completions ...
6. Advanced Tricks for Teams and Power Users
6.1 Persistent Logging for Audits
Set in config.json
:
"PROMPT_LOG_MODE": "file",
"PROMPT_LOG_BASE_NAME": "audit"
Every request and response will be written to audit-YYYY-MM-DD.log
with millisecond timestamps. The file is plain text—easy to grep, zip, or feed into a data pipeline.
6.2 Dynamic System Prompts
Create input_system_prompt.txt
:
You are a helpful assistant. Always cite your sources.
Then add to config.json
:
"SYSTEM_PROMPT_FILE_PATH": "input_system_prompt.txt",
"SYSTEM_PROMPT_MODE": "append"
Result: the gateway silently appends your rule to every chat, even if the client did not send a system message.
6.3 Docker One-Liner
A ready-made Dockerfile
is included. Build and run:
docker build -t ai-gateway .
docker run -p 3000:3000 \
-v $(pwd)/config.json:/app/config.json \
ai-gateway
Mount your OAuth credential files the same way if you use Gemini CLI or Kiro modes.
6.4 Running Multiple Instances
Because the gateway is stateless, you can start several copies on different ports:
# Terminal 1
node src/api-server.js --port 3001 --model-provider openai-custom
# Terminal 2
node src/api-server.js --port 3002 --model-provider claude-custom
Then load-balance with nginx or Caddy for zero-downtime fail-over.
7. Troubleshooting & Common Pitfalls
8. Extending the Gateway for New Providers
Suppose you want to add Mistral AI:
-
Create
src/mistral/
. -
Copy
src/openai/openai-adapter.js
tosrc/mistral/mistral-adapter.js
and change the base URL. -
Copy
src/openai/openai-strategy.js
tosrc/mistral/mistral-strategy.js
and tweak the request/response shape if Mistral differs. -
Register the adapter in
src/adapter.js
with one line:case 'mistral-custom': return new MistralAdapter(config);
-
Re-start the server with
--model-provider mistral-custom
.
That is literally all. The test suite will automatically pick up the new provider if you follow the same folder conventions.
9. Legal Notes & Credits
-
License: GNU General Public License v3 (GPLv3). You may use, modify, and redistribute the code freely, but any derivative work must also be open-source under the same license. -
Upstream Terms: Your use of Google Gemini, OpenAI, Claude, or Kiro remains governed by their respective terms of service. The gateway does not store or retransmit data beyond your own logs. -
Credits: The project is inspired by the official Google Gemini CLI and borrows small portions of early Cline code. We thank Google and the Cline authors for their excellent groundwork.
Happy building—and may your tokens always stream smoothly.