Stop paying twice. Turn your premium subscriptions into a unified, compatible API.
Luna is a local API gateway that transforms the CLI tools for your existing premium subscriptions (like Claude, Grok or ChatGPT) into a single, unified interface. It tricks your code into thinking it is talking to a standard API, letting you build personal projects using the subscriptions you already pay for.
You are already paying for a premium subscription, so why should you pay again for API credits just to build a personal project?
Most tools (editors, agents, scripts) expect the OpenAI API format. But not every backend speaks that language. Some are CLIs, some have proprietary APIs, some need custom auth flows.
Luna bridges that gap:
graph LR
A[Your App] ==> B(Luna Gateway)
B ==> C[Grok API]
B ==> D[Codex CLI]
B ==> E[Any backend you add]
One endpoint. Many backends. Zero rewrites.
- OpenAI compatible · Drop in replacement for
POST /v1/chat/completionsandGET /v1/models - Multi backend routing · Requests are routed to the right engine based on model name
- Pluggable engines · Add a new backend by creating a single Python file with two functions
- Built in chat client · Terminal chat UI with model selection and a 🌑🌒🌓🌔 moon phase thinking animation
- Auto managed gateway · The chat client starts, monitors, and cleans up the gateway automatically
- Smart auth · Grok engine handles OAuth2 token refresh with file locking and caching
- Claude Desktop Auth · Dynamically decrypts the Windows Claude Desktop App SQLite cookies using DPAPI to power the Claude engine
graph TD
Client[Any compatible client] ==>|HTTP OpenAI format| Gateway(gateway.py FastAPI router)
TestClient[chat.py optional test client] ==>|HTTP OpenAI format| Gateway
Gateway ==> Grok[Grok API]
Gateway ==> Codex[Codex CLI]
Gateway ==> Claude[Claude App]
| File | Role |
|---|---|
gateway.py |
FastAPI server · request routing, engine loading, OpenAI format endpoints |
chat.py |
Optional terminal chat client for testing · gateway lifecycle, model selection |
grok_api.py |
Grok engine · OAuth2 auth, token refresh, x.ai API calls |
codex_api.py |
Codex engine · CLI subprocess management, output parsing |
claude_api.py |
Claude engine · Claude Desktop App Windows DPAPI integration, SSE parsing |
- Python 3.11+
- Grok CLI logged in (
grok login) · for the Grok engine - Codex CLI installed · for the Codex engine
- Claude Desktop App (Windows) installed and logged in · for the Claude engine
pip install fastapi uvicorn requests filelock pycryptodome pypiwin32python chat.pyThat is it. The gateway starts automatically in the background, discovers available models, and drops you into an interactive chat.
python gateway.py --port 8000Then point any OpenAI compatible client at http://127.0.0.1:8000/v1.
$ python chat.py
Connecting to Master API Gateway...
Gateway started successfully!
Available Models
1. gpt_5.6_sol
2. grok_4.5
3. tera_luna
Type the number of the model you want to use, or press Enter for default (gpt_5.6_sol):
> 1
Model selected: gpt_5.6_sol
Welcome to Gateway Chat! Type 'exit' or 'quit' to stop.
You: What is Luna?
🌔 gpt_5.6_sol is thinking...
gpt_5.6_sol:
Luna is a local API gateway that turns apps into compatible APIs.
Since Luna exposes standard OpenAI-compatible endpoints, you can use existing tools and libraries directly.
1. Using the OpenAI Python SDK
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8000/v1", # Point this to your Gateway's port
api_key="dummy-key" # API key is ignored locally
)
response = client.chat.completions.create(
model="claude-sonnet-5", # Use any supported model
messages=[{"role": "user", "content": "Hello, how are you?"}]
)
print(response.choices[0].message.content)2. Using standard cURL
# List models
curl http://127.0.0.1:8000/v1/models
# Chat completion
curl -X POST http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "Hello!"}]
}'3. Using Python requests
import requests
response = requests.post(
"http://127.0.0.1:8000/v1/chat/completions",
json={
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "Hello!"}]
}
)
print(response.json()["choices"][0]["message"]["content"])Create a Python file (e.g., my_engine_api.py) with two functions:
def get_models() -> list:
"""Return a list of model dicts with at least an 'id' field."""
return [{"id": "my_model_v1", "object": "model", "created": 0, "owned_by": "my_engine"}]
def generate_completion(model: str, messages: list, **kwargs) -> dict:
"""Return an OpenAI format chat completion response."""
answer = call_your_backend(model, messages) # your logic here
return {
"id": "chatcmpl_...",
"object": "chat.completion",
"choices": [{"index": 0, "message": {"role": "assistant", "content": answer}, "finish_reason": "stop"}],
}Then register it in gateway.py:
ENGINES = {
# existing engines
"my_engine": {
"module": "my_engine_api",
"route_matcher": lambda model_name: model_name.startswith("my_"),
"is_fallback": False,
},
}Restart the gateway. Done.
- Works with:
- Codex
- Grok CLI
- Claude App (Windows Desktop)
- Streaming support (
stream: true) - Kimchi (next)
- Antigravity
- Request/response logging and analytics
MIT
🌑🌒🌓🌔🌕🌖🌗🌘
Built with Luna

