Skip to main content

Janus

The two-faced gateway for AI coding tools. Janus sits at the threshold of every AI call — facing the developer on one side and every provider on the other.

Janus is a local-first, single-user AI routing gateway. It exposes OpenAI/Anthropic/Gemini-compatible HTTP endpoints that your coding tools (Claude Code, Codex, Cursor, Cline, ...) talk to, then translates and routes each request to any of 29 built-in AI providers — or any OpenAI-compatible endpoint — without either side needing to know the other exists.

First-time setup

Janus needs Python 3.11+. Everything lives under ~/.janus/ — a seed config.yaml and a SQLite database (janus.db) that becomes the source of truth after the first startup.

1. Install

From PyPI (recommended):

pip install janus-ai

From source (development):

git clone https://github.com/amanverasia/Janus.git
cd Janus
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

2. Create config

janus config-init

This writes ~/.janus/config.yaml. Open it and add at least one provider with your API keys. Environment variables in ${VAR} form are resolved at startup:

export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...

Example provider block:

providers:
  - id: openai
    prefix: openai
    api_type: openai_compat
    base_url: https://api.openai.com/v1
    api_key: ${OPENAI_API_KEY}
    models: [gpt-4o, gpt-4o-mini]

You can also add providers later from the dashboard — no restart required.

3. Start the server

janus serve --port 20128

For access from other machines on your LAN or Tailscale:

janus serve --host 0.0.0.0 --port 20128

Janus serves plain HTTP only. Use http://, not https://, unless you put a reverse proxy with TLS in front.

4. Verify

curl http://localhost:20128/v1/health
# {"status":"ok"}

Open the dashboard at http://localhost:20128/dashboard. The root URL / redirects there.

5. Configure via dashboard

On first startup, Janus imports providers, combos, token_savers, and pricing from YAML into SQLite. After that, the database is authoritative — editing YAML and restarting will not re-apply changes. Use the dashboard instead.

Step Where What
Add providers Providers Pick from the catalog or add custom; fetch models, test connection
Create a client key API Keys sk-janus-... shown once — save it
Enable auth Settings Toggle Require API key (recommended for remote access)
Set reporting timezone Settings Choose an IANA timezone for Today's Spend and daily-budget boundaries
Set dashboard login Settings → Dashboard Login Username + password for remote browser sign-in
Connect your tools Tool Setup Copy-paste env vars for Claude Code, Codex, Cursor, Cline

Dashboard access rules:

  • localhost — no sign-in required
  • Remote (LAN, Tailscale, Docker on 0.0.0.0) — sign in at /dashboard/login with your dashboard username/password or a Janus API key

Create a key from the CLI instead:

janus keys create --name "my-laptop"

6. Send a test request

curl http://localhost:20128/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Hello!"}],
    "max_tokens": 50
  }'

List registered models:

curl http://localhost:20128/v1/models

7. Point your coding tool at Janus

Claude Code / Anthropic tools:

export ANTHROPIC_BASE_URL=http://localhost:20128/v1
export ANTHROPIC_API_KEY=sk-janus-yourkey   # if require_api_key is on

Cursor / OpenAI Chat Completions tools:

export OPENAI_BASE_URL=http://localhost:20128/v1
export OPENAI_API_KEY=sk-janus-yourkey      # if require_api_key is on

Codex CLI uses POST /v1/responses — configure a provider in ~/.codex/config.toml with wire_api = "responses" (see Client Setup).

Use prefix/model in requests (e.g. openai/gpt-4o, anthropic/claude-sonnet-4-20250514) or a combo name like best-effort.

📚 Documentation · Contributing · Changelog

Docker

mkdir -p janus-data
janus config-init --path janus-data/config.yaml
# Edit janus-data/config.yaml — add providers and ${ENV_VAR} keys

# Optional: pass API keys via .env in the repo root
echo 'OPENAI_API_KEY=sk-...' >> .env

docker compose up -d

The image binds to 0.0.0.0:20128. SQLite and config persist in ./janus-data/. After first startup, manage providers and settings from the dashboard — not by editing YAML alone.

Remote dashboard: enable Require API key in Settings, create a Janus API key, and set a dashboard username/password under Dashboard Login.

curl http://localhost:20128/v1/health
open http://localhost:20128/dashboard    # macOS; or visit in your browser

Configuration

Janus reads YAML from ~/.janus/config.yaml (or --config) with ${ENV_VAR} token resolution. Generate a template with janus config-init.

On first startup only, YAML seeds the SQLite database. Subsequent changes should be made via the dashboard or Export Config / Reset to Defaults on the Settings page.

server:
  port: 20128
  host: 127.0.0.1
  require_api_key: false

providers:
  - id: openai
    prefix: openai
    api_type: openai_compat
    base_url: https://api.openai.com/v1
    api_key: ${OPENAI_API_KEY}
    models: [gpt-4o, gpt-4o-mini, o3, o4-mini]

  - id: anthropic
    prefix: anthropic
    api_type: anthropic
    base_url: https://api.anthropic.com
    api_key: ${ANTHROPIC_API_KEY}
    models: [claude-sonnet-4-20250514, claude-opus-4-20250514]

combos:
  - name: best-effort
    models: [anthropic/claude-sonnet-4-20250514, openai/gpt-4o]

Supported Provider Types

api_type Use For
openai_compat Any OpenAI-compatible API (OpenAI, Groq, Together, DeepSeek, OpenRouter, Mistral, Fireworks, Perplexity, xAI, ...)
anthropic Direct Anthropic API
gemini Direct Google Gemini API
github_copilot GitHub Copilot (device-code OAuth from the dashboard)
opencode_free OpenCode Zen free tier

Known Provider Base URLs

Provider base_url
OpenAI https://api.openai.com/v1
Groq https://api.groq.com/openai/v1
Together AI https://api.together.xyz/v1
DeepSeek https://api.deepseek.com/v1
OpenRouter https://openrouter.ai/api/v1
Mistral https://api.mistral.ai/v1
Fireworks https://api.fireworks.ai/inference/v1
Perplexity https://api.perplexity.ai
xAI (Grok) https://api.x.ai/v1
Qwen/DashScope https://dashscope.aliyuncs.com/compatible-mode/v1

Client Setup

See step 7 in First-time setup for the basics. Full guides: Client Setup. The dashboard Tool Setup page (/dashboard/tools) generates copy-paste env vars for your exact server URL and auth settings.

Claude Code / Anthropic tools:

export ANTHROPIC_BASE_URL=http://localhost:20128/v1

Cursor / OpenAI Chat Completions tools:

export OPENAI_BASE_URL=http://localhost:20128/v1
export OPENAI_API_KEY=sk-janus-yourkey  # if require_api_key is on

Codex CLI speaks the Responses API (POST /v1/responses). Prefer a ~/.codex/config.toml provider with wire_api = "responses" and base_url = "http://localhost:20128/v1" — see the docs link above.

Ollama-only tools use OLLAMA_HOST=http://localhost:20128 (/api/chat, /api/generate, /api/show, /api/tags). Gemini-native tools use GOOGLE_GEMINI_BASE_URL=http://localhost:20128.

Features

  • Multi-format inbound — OpenAI Chat Completions, OpenAI Responses (/v1/responses for Codex CLI), Anthropic Messages, Gemini GenerateContent, and Ollama (/api/chat, /api/generate, /api/show, /api/tags)
  • Fallback routing — multi-account rotation with cooldowns (429→60s, 5xx→30s, auth→300s, network→15s)
  • Rate-limit-aware rotation — accounts at their per-minute or per-day request quota are tried last
  • Subscription quotas — per-provider 5h / daily / weekly / monthly windows; near-limit banners and soft deprioritization in routing
  • Combos — named ordered model sequences (e.g., "model": "best-effort")
  • Token savers — RTK compression (default ON), Caveman, Ponytail, and optional Headroom compression proxy
  • GitHub Copilot OAuth — device-code connect from the dashboard; session tokens refreshed automatically
  • API key scopes — API-only keys (can_login), model allowlists (prefix/*), optional daily budgets
  • Budgets — daily spending limits per API key or global, with warn/block thresholds
  • Request logging — opt-in debug capture of request/response bodies (Settings → Request Logs)
  • Analytics — cost tracking, spend trends, success rates, per-model/provider/key breakdowns
  • Pricing — builtin model prices, YAML/DB overrides, cache token rates
  • Dashboard — HTMX UI at /dashboard with charts, budgets, usage, routing overview, remote login, and self-hosted frontend assets (no runtime CDN dependency)
  • Upstream key inventory — validate, monitor, and route through a multi-key pool for 29 providers (/dashboard/inventory)

Upstream Key Inventory

Built-in dashboard for upstream provider API keys: health checks, credit tracking, and automatic routing through the best available key.

Dashboard: http://127.0.0.1:20128/dashboard/inventory

  • Overview stats, paginated/sortable keys table, key detail modal, best-keys widget
  • Add keys, bulk submit, import from Dashboard export JSON, re-identify misclassified keys
  • Encryption at rest; routable keys wired into gateway fallback rotation
  • Credentials masked by default; authenticated Reveal/Copy actions clear the value after 30 seconds
  • History shows real status transitions and credit snapshots without no-op transition noise
  • Detected rate limits (RPM/RPD) deprioritize near-quota keys during routing
  • Background recheck scheduler (twice daily by default)
Variable Purpose
INVENTORY_ENCRYPTION_KEY Fernet key for encrypting upstream keys at rest
INVENTORY_PUSH_TOKEN Auth token for POST /dashboard/api/inventory/push
INVENTORY_SCHEDULER_ENABLED Set to false to disable background rechecks (default: true)
janus inventory generate-encryption-key          # create Fernet key
janus inventory migrate export.json --verify     # import Dashboard export + summary
janus inventory verify                           # cutover verification summary
janus inventory encrypt-keys                       # encrypt plaintext keys in DB

CLI Reference

Command Description
janus serve Start the gateway server
janus config-init Generate default config YAML
janus config-path Print config file path
janus keys create/list/update/revoke Manage API keys (scopes: --no-login, --models, --daily-budget)
janus usage stats/cost/by-key Usage and cost reports
janus budgets list/set/delete Manage spending budgets
janus pricing list/show View model pricing
janus inventory migrate/verify/encrypt-keys/generate-encryption-key Upstream key inventory and cutover

Development

git clone https://github.com/amanverasia/Janus.git
cd Janus
python -m venv .venv
pip install -e ".[dev]"

# Run tests
.venv/bin/python -m pytest

# Lint + typecheck
.venv/bin/ruff check src/janus/ tests/
.venv/bin/mypy src/janus/

# Start dev server
.venv/bin/janus serve --port 20128 --reload

Tech Stack

Python 3.11+ / FastAPI / httpx / Pydantic v2 / aiosqlite / Jinja2 / HTMX / Chart.js

License

GPL-3.0 © 2026 Aman Verasia

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

janus_ai-2.2.0.tar.gz (871.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

janus_ai-2.2.0-py3-none-any.whl (561.3 kB view details)

Uploaded Python 3

File details

Details for the file janus_ai-2.2.0.tar.gz.

File metadata

  • Download URL: janus_ai-2.2.0.tar.gz
  • Upload date:
  • Size: 871.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for janus_ai-2.2.0.tar.gz
Algorithm Hash digest
SHA256 927072cc2ad5bcdd447be3a0a439db9d310261caf592ccba27f22f15717ce4b8
MD5 52e8faadf916800db010d85e550eeda9
BLAKE2b-256 6e136d0803ed22106a744ab37e931c8c248bd40ced420bad81b31cf0e9bb6b2e

See more details on using hashes here.

Provenance

The following attestation bundles were made for janus_ai-2.2.0.tar.gz:

Publisher: publish.yml on amanverasia/Janus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file janus_ai-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: janus_ai-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 561.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for janus_ai-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 edba002113687cb4deb62a4120652ef9f948e21ea52d5d0e03286963fefa2100
MD5 10e54d33661d32551b49329de2a7e7c5
BLAKE2b-256 d8ca805aa12b3c8d82c4aa7ffec19236a845ee9e2aee57cfa402ce53fc8cf20c

See more details on using hashes here.

Provenance

The following attestation bundles were made for janus_ai-2.2.0-py3-none-any.whl:

Publisher: publish.yml on amanverasia/Janus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

3.1.0

2 files

2.2.2

2 files

This release

2.2.0 This release

2 files

2.1.5

2 files

2.1.4

2 files

2.1.3

2 files

2.1.2

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.8.0

2 files

1.7.0

2 files

1.6.0

2 files

1.5.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page