Skip to content

Getting Started

This guide covers the CLI/server install. If you prefer a GUI, the desktop app (macOS, Windows, Linux) wraps the same relay with a system tray, dashboard, and one-click sign-in — see the README's install section for its one-line installers and desktop/README.md.

Install

One line on macOS or Linux, without sudo:

curl -fsSL https://raw.githubusercontent.com/lpalbou/AIRelays/main/scripts/install-headless.sh | bash

The script installs the newest PyPI release into an isolated environment (uv tool or a Python 3.11+ virtualenv) and links ~/.local/bin/airelays. Set AIRELAYS_VERSION=X.Y.Z to pin a release; run it again to upgrade.

From PyPI directly:

python -m pip install airelays

From a source checkout:

python -m pip install .

Initialize AIRelays

airelays init

This prepares:

  • config: ~/.config/airelays/config.toml
  • data dir: ~/.airelays
  • logs dir: ~/.airelays/logs
  • relay token: ~/.airelays/relay-token

Show the current relay token at any time:

airelays token show

Custom Configuration

The CLI and desktop use the same saved accounts and relay configuration by default. To use another configuration, pass --config consistently when signing in, inspecting accounts, and starting the relay:

airelays --config ./relay.toml init
airelays --config ./relay.toml claude login
airelays --config ./relay.toml claude accounts --json
airelays --config ./relay.toml serve --host 127.0.0.1 --port 8080

Shared options such as --config and --data-dir work before or after subcommands. A later explicit value takes precedence. See Configuration for paths and environment overrides.

OpenAI Runtime

Log in:

airelays login

On a server or over SSH (no local browser), use device-code login — you approve the sign-in from a browser on any other device:

airelays login --device

airelays login selects the device flow automatically on SSH sessions and displayless Linux. The browser flow's URL only works in a browser on the same machine as the relay (its redirect targets localhost:1455 there).

You can enroll several of your own OpenAI accounts: running airelays login again with a different account adds it alongside the first, and the relay balances across them (see the README's "Multiple OpenAI Accounts" section). Sign an account out with airelays logout <email>; manage order and capacity holds with airelays accounts.

Start the server:

airelays doctor
airelays serve --host 127.0.0.1 --port 8080

Verify:

curl http://127.0.0.1:8080/v1/models \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN'

curl http://127.0.0.1:8080/v1/chat/completions \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.5",
    "messages": [{"role": "user", "content": "Reply with exactly: OPENAI AIRelays OK"}]
  }'

OpenAI Open Local Relay Mode

airelays init --no-auth
airelays login
airelays serve --no-auth --host 127.0.0.1 --port 8080

In this mode AIRelays does not require Authorization on /v1/*. Open local relay mode applies to all enabled providers, including the Claude runtime.

Claude Runtime

AIRelays uses only Claude accounts it owns. Add one with a browser sign-in:

airelays claude login
airelays claude login       # optional: add another of your own accounts
airelays claude accounts

Each sign-in creates a separate Claude Code profile under ~/.airelays/claude/accounts/<id>/. Claude Code owns its credentials and refreshes them. The desktop offers Sign in / Add account → "In a browser" in the Anthropic card. Usage bars need a Claude Code version that supports get_usage (verified with 2.1.292+); requests work without it.

Headless Claude login — claude setup-token needs a browser, so run it on any machine that has one, then carry the token to the server:

# on a machine with a browser:
claude setup-token

# on the server:
airelays init
airelays claude set-token   # paste the token; stored 0600, survives restarts

The token is stored in ~/.airelays/claude-token and appears as the account default (desktop: "With a token"). It is inference-only: Claude reports no usage or email for setup tokens, so it has no usage bar and cannot be deduplicated against browser accounts.

Your personal Claude Code sign-in (~/.claude), an inherited CLAUDE_CONFIG_DIR, and an exported CLAUDE_CODE_OAUTH_TOKEN are never used; airelays doctor reports an ignored CLAUDE_CODE_OAUTH_TOKEN. Until an account is connected, claude:* requests return 503 provider_auth_error.

Manage one account using its email or id from airelays claude accounts:

airelays claude login --replace ACCOUNT
airelays claude logout ACCOUNT

Renewal requires the same account and pauses that profile until sign-in succeeds. To renew the setup token, run airelays claude set-token again. Duplicate browser subscriptions receive only one share of traffic.

Signing out runs claude auth logout inside that AIRelays profile only; airelays claude logout default only deletes the stored setup token. Neither touches your personal Claude Code sign-in. Use --all only to sign out all AIRelays accounts. The running relay discovers account changes automatically and balances requests across eligible accounts with capacity.

Start AIRelays with the Claude runtime enabled:

airelays serve --host 127.0.0.1 --port 8080

Verify:

curl http://127.0.0.1:8080/v1/chat/completions \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN' \
  -H 'content-type: application/json' \
  -d '{
    "model": "claude:sonnet",
    "messages": [{"role": "user", "content": "Reply with exactly: CLAUDE AIRelays OK"}]
  }'

Current Claude limits:

  • runs through the claude CLI on the relay's machine
  • served on the relay's listener, local or network
  • follows the relay's protected or open local authentication mode
  • no audio, no image generation (GPT models only), no server-side tools (web search), no forced tool calls

Status

Inspect relay and provider readiness:

airelays status

Usage windows of the running relay, including the image-generation quota:

airelays usage

Image Generation

GPT models also generate and edit images through OpenAI's Images routes:

curl http://127.0.0.1:8080/v1/images/generations \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN' \
  -H 'content-type: application/json' \
  -d '{"prompt": "a watercolor fox", "quality": "low"}'

The image comes back as PNG b64_json; /v1/images/edits takes the image to change as a multipart file. See API Notes.

Run local setup checks plus live upstream probes:

airelays doctor

airelays doctor checks config, relay-token state, OpenAI login readiness, upstream /models, a tiny /responses smoke request, and Claude readiness when the Claude runtime is enabled. Use airelays doctor --skip-response to skip the response smoke request.

List every model id the running relay accepts, grouped by provider, with each model's reasoning modes and, when the provider publishes one, its API list price per 1M tokens (a relative cost indicator; subscription requests are not billed per token):

airelays models

Machine-readable output:

airelays status --json
airelays doctor --json
airelays models --json

airelays status shows:

  • the installed AIRelays version (title line)
  • relay config and token state
  • Who can connect: the enforced network scope
  • OpenAI runtime readiness
  • Claude runtime readiness when enabled
  • next recommended commands

Provider Routing

  • models starting with claude: use the Claude runtime when it is enabled
  • other model ids use the OpenAI runtime when it is enabled
  • AIRelays rejects requests when the selected runtime is disabled or the route is outside that runtime's published subset

Client Configuration

Base URL:

http://127.0.0.1:8080/v1

Standard OpenAI SDKs can use the AIRelays relay token through their normal api_key field when the base_url points at AIRelays.

Example shell setup:

export OPENAI_BASE_URL='http://127.0.0.1:8080/v1'
export AIRELAYS_TOKEN="$(tr -d '\n' < ~/.airelays/relay-token)"

Use The Relay From Other Devices

airelays serve listens on 127.0.0.1 by default, so only this machine can connect. To serve your phone, another computer, or a Tailscale network, listen on all interfaces:

airelays serve --host 0.0.0.0 --port 8080

The default network_scope = "private" then admits this machine and private networks (home and office LANs, 100.64.0.0/10 VPNs such as Tailscale) and answers every other address with 403 client_not_on_private_network. Clients use http://<this machine's LAN address>:8080/v1 with the same relay token.

For access from anywhere, choose any (bearer auth stays required):

airelays init --host 0.0.0.0 --network-scope any   # add --force to rewrite an existing config
airelays serve

airelays init prints Who can connect and the matching airelays serve command. Forward the port on your router and put the relay behind a TLS reverse proxy or a VPN; Who Can Connect lists the steps, and Troubleshooting covers refused connections.

Subscription Status

OpenAI subscription usage:

curl http://127.0.0.1:8080/v1/subscription/status \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN'

Claude subscription usage (same normalized shape):

curl 'http://127.0.0.1:8080/v1/subscription/status?provider=claude' \
  -H 'authorization: Bearer YOUR_AIRELAYS_TOKEN'

See Subscription Status for multi-account parameters and the payload shape.

If a step fails, see Troubleshooting. Next, read API Notes for routes and limits, or Architecture for how requests flow. Back to the README.