anyray-connect
v0.9.7
Published
Anyray connect — points local coding tools (Claude Code, Cursor, Windsurf, SDKs) at the Anyray gateway by writing their base URL + a placeholder key. The gateway stays the brain; this is just the on-ramp.
Maintainers
Readme
anyray-connect
The on-ramp. A small, dependency-free Node CLI that points a developer's local coding tools at the Anyray gateway by writing each tool's base URL and a placeholder API key. The gateway stays the brain (routing, spend store, content encryption, optimizer) — this only does capture/onboarding.
The Anyray gateway you target may itself front an existing gateway (LiteLLM, OpenRouter, Portkey, homegrown) via the
anyray-upstreamprovider — that's configured server-side on the gateway, with no client-side difference toconnect.
npx anyray-connect --gateway https://gw.yourorg.internal --user [email protected]Personal gateway keys (invites)
When the gateway is exposed publicly, each dev authenticates with a personal
gateway key (ark_...) instead of the shared placeholder:
An org admin creates an invite on the gateway (admin-token-gated):
POST <gateway>/admin/inviteswith{ "user": "<email>", "team": "..." }→ anari_...invite token. (POST /admin/client-keysmints a key directly, skipping the invite step.)The dev redeems it while connecting:
npx anyray-connect --gateway https://gw.yourorg.example --invite ari_xxxxxxxx
Redemption (POST <gateway>/connect/redeem) is single-use: it returns the
personal key plus the user/team the invite was issued for, which become the
attribution defaults (explicit --user/--team win). The key is written
straight into the tool configs and never printed (the CLI shows only a masked
ark_…xxxx). Because redemption is single-use, --dry-run skips it — the
invite is not consumed on a dry run.
Already have a key? Set ANYRAY_CLIENT_KEY in the environment and run without
--invite; it's picked up the same way.
How the key is sent depends on the auth mode:
- Placeholder mode (default): the key replaces the shared placeholder as
the
Authorizationbearer. --subscription: the tool's seat OAuth token keeps theAuthorizationheader, and the personal key rides thex-anyray-api-keyheader instead so the gateway can still identify the dev.
What it changes
| Tool | How |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude Code | Automatic — writes the env block in ~/.claude/settings.json (ANTHROPIC_BASE_URL, placeholder ANTHROPIC_AUTH_TOKEN, and ANTHROPIC_CUSTOM_HEADERS carrying x-anyray-metadata). With --subscription, no auth token is written: Claude Code keeps its seat (Pro/Max/Team/Enterprise) sign-in and the gateway passes the OAuth token through (x-anyray-auth-mode: passthrough), so spend stays on the subscription. |
| Codex CLI | Automatic — writes ~/.codex/anyray.config.toml as a layered profile, leaving the base config.toml untouched so existing MCP servers keep loading; opt in per run with codex --profile anyray. With --subscription, the provider sets requires_openai_auth = true and no static key: Codex attaches its ChatGPT sign-in itself, and the gateway passes the OAuth token through to the ChatGPT Codex backend (x-anyray-custom-host), so spend stays on the seat. |
| Shell env | Automatic — a managed, idempotent block in your shell profile with OPENAI_BASE_URL / ANTHROPIC_BASE_URL + placeholder keys (covers SDK jobs and scripts). |
| Cursor / Windsurf | Detect + print exact UI steps (their config is app state we don't script). |
The real provider key is never written here — it stays server-side in the
gateway (ANYRAY_PROVIDER_KEY_*), which swaps it in per request. Only metadata
(user/team) is attached for spend attribution; prompt/response content is never
touched.
Common flags
--gateway <url> Gateway origin (default: $ANYRAY_GATEWAY_URL or http://localhost:8787)
--user <id> Attribute spend to this user (default: git email, else OS user)
--team <id> Attribute spend to this team
--tools <ids> Subset: claude-code, codex, cursor, windsurf, shell-env
--invite <token> Redeem an org invite (single-use) for a personal gateway key
and use it as your auth; defaults --user/--team from the
invite. Skipped under --dry-run (the invite isn't consumed).
Already have a key? Set $ANYRAY_CLIENT_KEY instead.
--subscription Seat-billed (subscription) auth: pass the tool's own OAuth
token through the gateway instead of the org API key.
Honored by Claude Code (Anthropic seats) and Codex (ChatGPT
seats); other tools configure as usual. With a personal
gateway key (--invite / $ANYRAY_CLIENT_KEY), the key rides
x-anyray-api-key while the seat token stays the bearer.
--dry-run Show what would change without writing
--yes, -y Skip confirmation (scripted/fleet rollout)
--revert Undo a previous runWithout a TTY (CI, piped stdin) the CLI exits 1 instead of prompting — pass
--yes for any scripted run, including --revert (piping y no longer works).
Adding a tool
Adapters live in src/tools/ and are registered in src/tools/index.ts
(REGISTRY) — same open/closed seam as the optimizer's strategy registry. Write
an adapter implementing ToolAdapter (detect / apply / revert) and add one
line to the registry. Nothing in the CLI orchestrator changes.
Develop
npm install
npm run dev -- --dry-run # run from source
npm test # node --test
npm run build # tsc → dist/