AIRelays: an independent OpenAI-compatible local relay for single-user subscription-backed access.
Project description
AIRelays
AIRelays is a local OpenAI-compatible HTTP server.
- The runtime uses an AIRelays-owned ChatGPT subscription login.
- AIRelays protects the relay with its own bearer token by default.
- Every transit is logged to hourly JSONL files.
Independence And Intended Use
- AIRelays is an independent third-party project. It is not affiliated with, endorsed by, or sponsored by any provider.
- Provider and product names are used only to describe compatibility targets and upstream behavior.
- AIRelays is designed for a single user running a local relay for personal convenience.
- AIRelays is not presented as a shared, pooled, multi-user, or resale service.
See DISCLAIMER.md.
Install
AIRelays ships two ways; both drive the same relay and share the same
config (~/.config/airelays) and data (~/.airelays).
CLI / server install (PyPI)
For headless machines, servers, or terminal-first workflows:
python -m pip install airelays
Or from a source checkout:
python -m pip install .
Desktop app (GUI + system tray)
A cross-platform tray app (macOS, Windows, Linux) lives under
desktop/: a dashboard with relay start/stop, auth and
network modes, OpenAI sign-in/sign-out, per-account usage bars,
a model list with copy-ready ids, live traffic, and diagnostics. The tray
icon shows connection state and blinks on request activity; the app can
start at login, starts the relay when it opens, and restarts a crashed
relay automatically. Installers (DMG, NSIS, AppImage, deb) build from
.github/workflows/desktop.yml; locally:
cd desktop
./scripts/bundle_runtime.sh
npm install && npm run build
An earlier native macOS status-bar app remains available under macos/AIRelaysMenuBar:
swift build --package-path macos/AIRelaysMenuBar
swift run --package-path macos/AIRelaysMenuBar AIRelaysMenuBar
Quick Start
OpenAI runtime:
airelays init
airelays login
airelays doctor
airelays serve --port 8080
Headless / server install (SSH, no browser):
airelays init
airelays login --device
airelays doctor
airelays serve --port 8080
Device-code login prints a short code you approve from a browser on any
other device (laptop, phone). On SSH sessions and displayless Linux,
airelays login selects it automatically. Do not paste the browser-flow
URL into a browser on another computer: its sign-in redirect only works on
the machine running the relay (see
docs/troubleshooting.md for the SSH-tunnel
alternative).
OpenAI runtime in open local relay mode:
airelays init --no-auth
airelays login
airelays serve --no-auth --port 8080
This disables only the AIRelays client-token gate. It does not bypass the upstream ChatGPT login.
Basic Verification
Run setup and upstream probes before starting the server:
airelays doctor
List the model ids the running relay accepts:
airelays models
Use airelays doctor --skip-response to skip the tiny /responses smoke request.
Public health:
curl http://127.0.0.1:8080/healthz
Protected relay status:
curl http://127.0.0.1:8080/v1/relay/status \
-H 'authorization: Bearer YOUR_AIRELAYS_TOKEN'
OpenAI model listing:
curl http://127.0.0.1:8080/v1/models \
-H 'authorization: Bearer YOUR_AIRELAYS_TOKEN'
OpenAI text request:
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"}]
}'
Multiple OpenAI Accounts
One person can enroll several of their own OpenAI subscriptions and let the relay balance across them. Signing in again with a different account adds it (the previous sign-in is kept, never overwritten):
airelays login # first account
airelays login # second account — added alongside the first
airelays accounts # list accounts and the commands to manage them
airelays logout perso@gmail.com # sign one account out
airelays accounts order work@company.com perso@gmail.com # change priority
airelays accounts is the hub: it lists your accounts in balancing order and
prints the exact commands to add, sign out, or reorder them. In the desktop
app, each account row has a sign-out button and the "Add account" button
offers both browser and code (headless) sign-in.
By default AIRelays uses the first account until it reaches its usage
limit, then continues with the next, and returns when the limit resets.
Set [providers.openai] balance = "round_robin" to spread requests evenly
across healthy accounts instead. Failed-over requests are logged with the
serving account, and /v1/subscription/status?all_accounts=true reports
usage per account.
Multiple accounts exist so one user can use their own subscriptions from one relay; it is not a mechanism for sharing or pooling access between people (see DISCLAIMER.md).
Relay Token
Show the current token:
airelays token show
Rotate the current token:
airelays token rotate
Use the relay token as the client credential when you point an OpenAI-compatible SDK at AIRelays.
Provider Routing
- all model ids route to the OpenAI runtime
- AIRelays rejects requests when the runtime is disabled or the route is outside its published subset
What AIRelays Exposes
GET /v1/modelsGET /v1/subscription/statusGET /v1/account/rate_limitsGET /v1/relay/statusPOST /v1/relay/accounts/refreshPOST /v1/responsesPOST /v1/chat/completionsPOST /v1/completionsPOST /v1/filesGET /v1/filesGET /v1/files/{file_id}GET /v1/files/{file_id}/contentDELETE /v1/files/{file_id}POST /v1/conversationsGET /v1/conversations/{conversation_id}POST /v1/conversations/{conversation_id}DELETE /v1/conversations/{conversation_id}/no-tools/v1/models/no-tools/v1/responses/no-tools/v1/chat/completions/no-tools/v1/completions
What The Relay Changes (Compatibility Layer)
The ChatGPT subscription backend is not the public OpenAI platform API, so
AIRelays adapts some requests instead of letting them fail. Every
adaptation is visible: it is logged as a compatibility_adaptation record
in the traffic logs and reported in the x-airelays-ignored-parameters
response header.
Sampling parameters are removed. The upstream rejects temperature,
top_p, presence_penalty, and frequency_penalty outright
("Unsupported parameter: temperature"). AIRelays strips them so standard
SDK calls keep working; generation then runs with the upstream's own
sampling defaults, which cannot be overridden.
Reasoning effort is forwarded, not invented. reasoning_effort (chat
completions) and reasoning: {"effort": ...} (responses) pass through to
the upstream unchanged. When a request does not set one, the upstream runs
reasoning models at effort none — noticeably below what the official
apps use (medium). For quality comparable to the ChatGPT apps, set it
explicitly:
curl http://127.0.0.1:8317/v1/chat/completions \
-H 'authorization: Bearer YOUR_AIRELAYS_TOKEN' \
-H 'content-type: application/json' \
-d '{
"model": "gpt-5.5",
"reasoning_effort": "medium",
"messages": [{"role": "user", "content": "..."}]
}'
Conversations stick to one account. With multiple OpenAI accounts, a conversation keeps using the account that served its first turn (preserving upstream prompt caching); it only fails over to another account at a turn boundary when the pinned account is at its limit.
Compatibility Boundary
- first-class routes:
/v1/responses,/v1/chat/completions,/v1/completions - local files and local conversations are supported
- non-stream responses are reconstructed from streamed upstream events
store=trueis rejected- output-token limit fields are rejected explicitly on the OpenAI-shaped text-generation routes
Security Defaults
- default listener:
127.0.0.1:8080 - protected routes:
/v1/*and/no-tools/v1/* - public routes:
/andGET /healthz - protected diagnostics:
GET /v1/relay/status - default rate limit:
120requests/minute with burst40 - default concurrent request cap:
8per IP - repeated bad tokens trigger a temporary IP block
Configuration
AIRelays reads configuration in this order:
- CLI flags
AIRELAYS_*environment variables- legacy
OPENAI_ENDPOINT_*migration variables where supported ~/.config/airelays/config.toml- built-in defaults
Important toggles:
AIRELAYS_REQUIRE_BEARER_AUTHAIRELAYS_BEARER_TOKENAIRELAYS_BEARER_TOKEN_FILEAIRELAYS_ENABLE_OPENAIAIRELAYS_OPENAI_MODELS_CACHE_TTL_SECONDS
Paths
- config:
~/.config/airelays/config.toml - data dir:
~/.airelays - logs:
~/.airelays/logs - relay token:
~/.airelays/relay-token - earlier singular AIRelay paths remain compatible for local upgrades
More Docs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file airelays-0.3.0.tar.gz.
File metadata
- Download URL: airelays-0.3.0.tar.gz
- Upload date:
- Size: 6.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
071d8b3c279e01d09b64f8988ffe53a55c7897d749c0f58adc50b7c64cf34ce7
|
|
| MD5 |
e54237bb07896467679f855e477d3a3f
|
|
| BLAKE2b-256 |
c4fc61698dcc9264012f140339ce1ec73871a2200235e6effc64de06dde60590
|
Provenance
The following attestation bundles were made for airelays-0.3.0.tar.gz:
Publisher:
release.yml on lpalbou/AIRelays
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
airelays-0.3.0.tar.gz -
Subject digest:
071d8b3c279e01d09b64f8988ffe53a55c7897d749c0f58adc50b7c64cf34ce7 - Sigstore transparency entry: 2109509256
- Sigstore integration time:
-
Permalink:
lpalbou/AIRelays@b0c6dfa2e50bdef66219633ffd42019c035c5fe7 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/lpalbou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b0c6dfa2e50bdef66219633ffd42019c035c5fe7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file airelays-0.3.0-py3-none-any.whl.
File metadata
- Download URL: airelays-0.3.0-py3-none-any.whl
- Upload date:
- Size: 72.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3725a38e90f0d930602c76ffdd920d53b8ae41d1263ae31521ccc7d62b97844
|
|
| MD5 |
c06df654a20a7d8e455220ca421361b3
|
|
| BLAKE2b-256 |
3b536cfacb96f426b2ae411ecdafd01c8d1190c37c909013a87975093d375753
|
Provenance
The following attestation bundles were made for airelays-0.3.0-py3-none-any.whl:
Publisher:
release.yml on lpalbou/AIRelays
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
airelays-0.3.0-py3-none-any.whl -
Subject digest:
e3725a38e90f0d930602c76ffdd920d53b8ae41d1263ae31521ccc7d62b97844 - Sigstore transparency entry: 2109509711
- Sigstore integration time:
-
Permalink:
lpalbou/AIRelays@b0c6dfa2e50bdef66219633ffd42019c035c5fe7 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/lpalbou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b0c6dfa2e50bdef66219633ffd42019c035c5fe7 -
Trigger Event:
push
-
Statement type: