# AIRelays

AIRelays is a local OpenAI-compatible HTTP server with provider-scoped runtimes. The default runtime uses an AIRelays-owned ChatGPT subscription login and balances requests across multiple of your own OpenAI accounts by default. The Claude runtime balances your own subscriptions through AIRelays-owned local `claude` CLI profiles (never your personal Claude Code sign-in) for explicit `claude:*` text models. AIRelays protects `/v1/*` and `/no-tools/v1/*` with its own relay bearer token by default and can run all enabled providers in open local relay mode. A cross-platform desktop app (macOS, Windows, Linux) wraps the same relay with a system tray and dashboard.

## Key Docs

- [README.md](README.md): overview, install (CLI and desktop), quick start, compatibility layer
- [docs/getting-started.md](docs/getting-started.md): setup, custom CLI configuration, multi-account sign-in, verification
- [docs/configuration.md](docs/configuration.md): config file shape, environment overrides, and traffic-log retention
- [docs/security.md](docs/security.md): relay auth, open local relay mode, Claude guardrails
- [docs/api.md](docs/api.md): routes, compatibility adaptations, provider limits
- [docs/architecture.md](docs/architecture.md): request flow and module boundaries
- [docs/subscription-status.md](docs/subscription-status.md): usage reporting for OpenAI and Claude, desktop account details via **?**
- [docs/faq.md](docs/faq.md): common questions and limits
- [docs/troubleshooting.md](docs/troubleshooting.md): symptoms, causes, fixes
- [docs/adr/README.md](docs/adr/README.md): durable design decisions
- [desktop/README.md](desktop/README.md): combined connection/access card, hide-on-blur dashboard, tray controls, build, supervision
- [DISCLAIMER.md](DISCLAIMER.md): independence and intended use

## Install

- Headless relay and CLI (macOS, Linux): `curl -fsSL https://raw.githubusercontent.com/lpalbou/AIRelays/main/scripts/install-headless.sh | bash`
- Desktop app (macOS Apple Silicon, Linux x86_64): `curl -fsSL https://raw.githubusercontent.com/lpalbou/AIRelays/main/scripts/install-desktop.sh | bash`
- Desktop app (Windows x64, PowerShell): `irm https://raw.githubusercontent.com/lpalbou/AIRelays/main/scripts/install-desktop.ps1 | iex`
- PyPI: `python -m pip install airelays`; `AIRELAYS_VERSION=X.Y.Z` pins a release for any installer

## Main Commands

- `airelays init` / `airelays init --no-auth`
- `airelays login` (additive; repeat to enroll more accounts) / `airelays login --device` (headless)
- `airelays logout <email>` / `airelays accounts` (list, order, refresh)
- `airelays serve` / `airelays serve --no-auth`
- `airelays status` / `airelays doctor` / `airelays models` / `airelays logs`
- `airelays token show` / `airelays token rotate`
- `airelays claude set-token` (optional headless setup token; account `default`, inference-only)
- `airelays claude login` (additive) / `airelays claude accounts`
- `airelays claude login --replace ACCOUNT` / `airelays claude logout ACCOUNT` (or `--all`)
- `claude setup-token` (on any machine with a browser, before `airelays claude set-token`)

## Important Notes

- Shared CLI options (`--config`, `--data-dir`, `--logs-dir`, `--auth-storage`, `--bearer-token-file`) work before or after subcommands; a later explicit value wins. `--auth-storage` is accepted for compatibility only.
- Sign-ins (OpenAI, relay token, Claude setup token) are owner-only files in the data directory on every OS; AIRelays does not use the OS keychain. OpenAI sign-ins that 0.16.0 or earlier kept in the keychain need a new sign-in (`airelays doctor` lists them under `openai_keyring_sign_ins`).

- Traffic logs default to 7 days, 1024 MiB total, and hourly/50 MiB rotation. `airelays logs`, GET/PUT `/v1/relay/logging`, and tray Settings inspect or change the saved policy; see `docs/configuration.md` for limits and permanent-deletion behavior.

- OpenAI runtime: first-class `responses`, `chat.completions`, and `completions`
- Claude runtime: text `chat.completions` and text `completions` only
- Claude uses only AIRelays-owned accounts: browser profiles with their own `CLAUDE_CONFIG_DIR` under `~/.airelays/claude/accounts/<id>/`, plus an optional setup token (`default`, inference-only, no usage). The personal Claude Code sign-in (`~/.claude`), an inherited `CLAUDE_CONFIG_DIR`, and `CLAUDE_CODE_OAUTH_TOKEN` are ignored; with no account, `claude:*` requests return 503 `provider_auth_error`. Signing out never touches Claude Code. Selection honors fresh usage and model eligibility, with failover only before response bytes reach the client.
- One launcher starts every `claude` process: it finds `claude` on PATH and in the usual install locations (path used as found), or uses `[providers.claude].command` / `AIRELAYS_CLAUDE_COMMAND` (JSON array) as a full argv; Windows requires a real `claude.exe` and refuses npm `.cmd` shims; system prompts go through a private file when supported; over-long arguments return 413; `doctor`/`status` show the CLI path
- models starting with `claude:` or discovered concrete `claude-*` ids route to the Claude runtime when it is enabled
- model discovery follows the installed Codex client version and Claude CLI catalog; `GET /v1/models?refresh=true` bypasses provider caches, and Claude alias resolutions appear in `airelays.resolved_model`
- OpenAI catalogs form a union; balancing, affinity, and failover stay inside the requested model's supporting account subset; `airelays.account_availability` exposes coverage counts and `catalog_visibility` preserves upstream-hidden status
- other model ids route to the OpenAI runtime when it is enabled
- Claude runtime follows the relay's protected or open local auth mode and requires loopback binding
- `GET /v1/subscription/status` reports OpenAI usage by default and Claude usage with `?provider=claude`, both in one normalized shape; `?all_accounts=true` always returns the per-account list, with a per-account `error` when a probe fails
- Claude usage includes explicitly named scoped caps (including Fable), credit/spend metadata with declared currency scales, and fetch timestamps; scoped exhaustion does not imply all-model exhaustion, and quota percentages are not token counts
- Claude usage comes from each profile's Claude Code via the SDK `get_usage` control request (no inference; verified with 2.1.292+), refreshed every five minutes; the relay never reads Claude credentials. Readings without live data keep the last good values marked stale with `stale_reason` (`usage_unavailable`, `nonessential_traffic_disabled`, `cli_unsupported`, `cli_failed`) and never unblock or rank an account
- the upstream rejects `temperature`/`top_p`/penalty parameters and does not honor output-token limits (`max_tokens`, `max_completion_tokens`, `max_output_tokens`); the relay strips them on both runtimes and discloses it via the `x-airelays-ignored-parameters` header
- `reasoning_effort` works on both runtimes; each model's supported modes and default are published in `/v1/models` under `airelays.reasoning`, using provider catalog metadata when available
- `response_format` structured outputs work on chat completions for both runtimes (Claude: `json_schema` and `json_object`, enforced natively by the CLI's `--json-schema`; OpenAI: `json_schema`); supported types per model are published under `airelays.structured_output`
- failed upstream OpenAI calls retry automatically with exponential backoff (default 3 retries, 5s/20s/60s; configurable, `0` disables) before returning an OpenAI-shaped error with the real HTTP status
- `airelays doctor` runs local setup checks plus live OpenAI `/models` and optional `/responses` probes

## Optional

- [CHANGELOG.md](CHANGELOG.md): release history
- [ACKNOWLEDGEMENTS.md](ACKNOWLEDGEMENTS.md): credits
- [CONTRIBUTING.md](CONTRIBUTING.md): contributor workflow
- [SECURITY.md](SECURITY.md): vulnerability reporting
