
English | 简体中文
Multi-provider AI proxy with a built-in admin UI, routing, and usage tracking.
Maxx supports three deployment methods:
| Method | Description | Best For |
|---|---|---|
| Docker | Containerized deployment | Server/production |
| Desktop App | Native application with GUI | Personal use |
| Local Build | Build from source | Development |
docker compose up -d
The service will run at http://localhost:9880.
📄 Full docker-compose.yml example
services:
maxx:
image: ghcr.io/awsl-project/maxx:latest
container_name: maxx
restart: unless-stopped
ports:
- "9880:9880"
volumes:
- maxx-data:/data
environment:
- MAXX_ADMIN_PASSWORD=your-password # Optional: Enable admin authentication
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9880/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
maxx-data:
driver: local
Download from GitHub Releases:
| Platform | File | Notes |
|---|---|---|
| Windows | maxx.exe |
Run directly |
| macOS (ARM) | maxx-macOS-arm64.dmg |
Apple Silicon (M1/M2/M3/M4) |
| macOS (Intel) | maxx-macOS-amd64.dmg |
Intel chips |
| Linux | maxx |
Native binary |
🍺 macOS Homebrew Installation
# Install
brew install --cask awsl-project/awsl/maxx
# Upgrade
brew upgrade --cask awsl-project/awsl/maxx
Gatekeeper note: maxx is not notarized. On first launch, macOS Gatekeeper may block it. To allow it, run:
xattr -d com.apple.quarantine /Applications/maxx.appOr go to System Settings > Privacy & Security and click Open Anyway.
If macOS says the app is damaged: 1. Remove quarantine attributes:
sudo xattr -rd com.apple.quarantine /Applications/maxx.app2. Right-clickmaxx.appin Finder and choose Open once. 3. If it still fails, reinstall and retry:brew uninstall --cask awsl-project/awsl/maxx && brew install --cask awsl-project/awsl/maxx
# Server mode
go run cmd/maxx/main.go
# With admin authentication
MAXX_ADMIN_PASSWORD=your-password go run cmd/maxx/main.go
# Desktop mode (Wails)
go install github.com/wailsapp/wails/v2/cmd/wails@latest
wails dev
Frontend requirements: Node.js 22.12.0+ within the 22.x line (see .node-version / .nvmrc) and pnpm 10.7.0 (locked via web/package.json).
maxx-cli)maxx-cli is a separate binary that talks to a running maxx server's admin
HTTP API. It covers everything the web UI does — providers, API tokens,
routes (with weights), routing strategies (with sticky session affinity),
users, invite codes, and settings — and is designed for scripts, CI, and
AI agents.
Supported install paths:
# From source (latest tagged release):
go install github.com/awsl-project/maxx/cmd/maxx-cli@latest
# From source (local checkout):
task install:cli # uses Taskfile; installs to $GOBIN
# Inside the official Docker image: maxx-cli is on PATH at /usr/local/bin/maxx-cli
docker exec <container> maxx-cli --help
Standalone binary release assets and Homebrew/Scoop manifests for
maxx-cli are not yet published; track #585
for the follow-up.
First-time usage:
maxx-cli login --server http://localhost:9880 --username admin
maxx-cli help reference # full command tree, auto-generated
maxx-cli -o json provider list
For the full agent-friendly briefing run maxx-cli help reference,
maxx-cli help formatting, and maxx-cli help auth-config.
Create a project in the maxx admin interface and generate an API key.
settings.json (Recommended)
Location: ~/.claude/settings.json or .claude/settings.json
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "your-api-key-here",
"ANTHROPIC_BASE_URL": "http://localhost:9880"
}
}
🔧 Shell Function (Alternative)
Add to your shell profile (~/.bashrc, ~/.zshrc, etc.):
claude_maxx() {
export ANTHROPIC_BASE_URL="http://localhost:9880"
export ANTHROPIC_AUTH_TOKEN="your-api-key-here"
claude "$@"
}
Then use claude_maxx instead of claude.
🔐 Token Authentication
When Token Authentication is Enabled:
- Set ANTHROPIC_AUTH_TOKEN to a token created in the 'API Tokens' page (format: maxx_xxx)
- Claude Code will automatically add the x-api-key header to requests
- maxx will validate the token before processing requests
When Token Authentication is Disabled:
- You can set ANTHROPIC_AUTH_TOKEN to any value (e.g., "dummy") or leave it empty
- maxx will not validate the token
- Suitable for internal networks or testing scenarios
- ⚠️ Warning: Disabling token authentication reduces security
config.toml
Add to ~/.codex/config.toml:
# Optional: Set as default provider
model_provider = "maxx"
[model_providers.maxx]
name = "maxx"
base_url = "http://localhost:9880"
wire_api = "responses"
request_max_retries = 4
stream_max_retries = 10
stream_idle_timeout_ms = 300000
auth.json
Create or edit ~/.codex/auth.json:
{
"OPENAI_API_KEY": "maxx_your_token_here"
}
Usage:
# Use --provider flag to specify
codex --provider maxx
# Or use directly if set as default provider
codex
🔐 Token Authentication
When Token Authentication is Enabled:
- Configure OPENAI_API_KEY in auth.json with a token created in the 'API Tokens' page (format: maxx_xxx)
- Codex CLI will automatically add the Authorization: Bearer <token> header to requests
- maxx will validate the token before processing requests
When Token Authentication is Disabled:
- You can set OPENAI_API_KEY in auth.json to any value (e.g., "dummy")
- maxx will not validate the token
- Suitable for internal networks or testing scenarios
- ⚠️ Warning: Disabling token authentication reduces security
| Type | Endpoint |
|---|---|
| Claude | POST /v1/messages |
| OpenAI | POST /v1/chat/completions |
| Codex | POST /v1/responses |
| Gemini | POST /v1beta/models/{model}:generateContent |
| Project Proxy | /project/{project-slug}/v1/messages (etc.) |
| Admin API | /api/admin/* |
| WebSocket | ws://localhost:9880/ws |
| Health Check | GET /health |
| Web UI | http://localhost:9880/ |
| Variable | Description |
|---|---|
MAXX_ADMIN_PASSWORD |
Enable admin authentication with JWT. Default username: admin, password: the value of this variable |
MAXX_DSN |
Database connection string |
MAXX_DATA_DIR |
Custom data directory path |
MAXX_DISABLE_UI |
Headless mode: when truthy (1/true/yes/on), do not serve the web UI — only the API and proxy endpoints are exposed. Equivalent to the -no-ui flag (the flag takes precedence when set). Project proxy routes (/project/{slug}/...) remain available. |
MAXX_CORS_ALLOW_ORIGINS |
Comma-separated list of allowed origins (or *) for cross-origin requests. Enables a separately-hosted frontend to point at this backend; unset disables CORS (same-origin only). |
MAXX_ROUTING_SEED_SALT |
Optional shared secret for the weighted_random routing strategy. If unset, each process generates its own random salt — anti-grinding still holds and Redis sticky bindings still converge after the first successful request, but the pre-sticky first-pick order for the same (token, session) can differ across instances. Set the same value on every instance when you need consistent first-pick behavior in multi-instance deployments. |
Run maxx as a pure API gateway without serving the admin Web UI — useful for server/production deployments where you configure everything through the Admin API and want a smaller attack surface.
Enable it with either the -no-ui flag or the MAXX_DISABLE_UI
environment variable (the flag wins if both are set):
# Flag (local build)
maxx -no-ui
# Env var (Docker / compose)
docker run -e MAXX_DISABLE_UI=true -p 9880:9880 ghcr.io/awsl-project/maxx
In headless mode:
/ and all web UI routes return 404 (no static files are served)./api/admin/*), proxy endpoints (/v1/messages, /v1/chat/completions, …), project proxy (/project/{slug}/...), /health, and /ws all keep working.MAXX_ADMIN_PASSWORD to protect it.You can host the Web UI on one origin (e.g. a CDN, a dev server, or a headless maxx's sibling) and have it talk to a backend on a different origin.
1. Allow the frontend's origin on the backend via CORS (otherwise the browser blocks cross-origin requests):
# Single origin
MAXX_CORS_ALLOW_ORIGINS=https://ui.example.com maxx
# Multiple origins (comma-separated), or "*" to allow any
MAXX_CORS_ALLOW_ORIGINS=https://ui.example.com,http://localhost:3000 maxx
⚠️ CORS is not a substitute for authentication.
*lets any website read and call your API from a browser, including the admin API. Only use*for trusted/local setups, and always setMAXX_ADMIN_PASSWORDso the admin API requires a token. Prefer listing explicit origins over*. maxx logs a warning at startup if*is combined with an unauthenticated admin API.
2. Point the UI at the backend. Open the Web UI and either:
https://api.example.com); orThe value is stored in the browser (localStorage), so each user/browser can
target a different backend. Leave it empty to use the same origin that served
the page (the default). Build-time default: set VITE_BACKEND_URL when building
the frontend.
Configurable via Admin UI:
| Setting | Description | Default |
|---|---|---|
proxy_port |
Proxy server port | 9880 |
request_retention_hours |
Request log retention (hours) | 168 (7 days) |
request_detail_retention_seconds |
Request detail retention (seconds, unified — used when split is off) | -1 (forever) |
request_detail_retention_split_enabled |
Configure success/failed retention separately | false |
request_detail_retention_seconds_success |
Success request detail retention (seconds, only when split=true) | falls back to unified |
request_detail_retention_seconds_failed |
Failed request detail retention (seconds, only when split=true) | falls back to unified |
timezone |
Timezone setting | Asia/Shanghai |
quota_refresh_interval |
Antigravity quota refresh (minutes) | 0 (disabled) |
auto_sort_antigravity |
Auto-sort Antigravity routes | false |
codex_reasoning_guard |
Codex non-stream reasoning token guard retry config | disabled by default |
enable_pprof |
Enable pprof profiling | false |
pprof_port |
Pp |