Skip to main content

Anyray Connect

anyray-connect points a developer's coding tools at your gateway in one command.

Connect finds the AI tools on a machine and edits each tool's own config so its requests go through the gateway. The org's provider keys stay on the gateway, and each developer gets a personal ark_… client key. --revert restores every config it wrote.

Run it

1
Get an enrollment link

An admin creates a passwordless link in Console → Users, or shares the org's SSO command.

2
Run Connect
Enrollment link
curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- \
--enroll https://app.anyray.ai/enroll/enl_…

Enrollment mints your personal gateway key and sets your name and team for spend attribution. Connect then detects your tools, shows what it will change, and writes each config. --dry-run previews without writing, and anyray-connect with no setup flags chooses interactively.

3
Restart open tools

An editor that was already open holds the environment it captured at launch, so it keeps its old routing until it restarts. An interactive run asks once, then closes and reopens exactly those apps. An app already pointed at the gateway is never touched.

FlagEffect
--quit-appsSkip the question and do it. The only way a scripted run closes anything
--no-quit-appsNever close anything, whatever else is passed

Without either flag, only an interactive run asks. --yes, a non-interactive shell, --dry-run, and the managed and MDM payloads close nothing.

4
Check the result
curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- status

status lists which tools point at the gateway, plus your gateway, name, and team. If something looks wrong, run doctor the same way. It diagnoses gateway reachability and each tool's config.

What Connect changes, per tool

Tools that are not installed are skipped. --tools takes a comma-separated list of ids to configure a subset.

ToolWhat Connect changesID
Claude (API)the env block in ~/.claude/settings.json, plus an apiKeyHelper that renews the ark_ key on demandclaude-code
Claude (Subscription)same env block; your own Claude sign-in stays. No apiKeyHelper here, because its output would hijack the seat's OAuth sign-in, so a SessionStart hook re-mints the key insteadclaude-code
Claude Desktopits third-party gateway mode, plus queued migration of eligible local sessions, MCP entries, plugins, and skillsclaude-desktop
Codex (app, CLI, IDE)~/.codex/config.toml ($CODEX_HOME overrides the directory), where anyray becomes the default providercodex
Cursornative Team mode: local Shell/Read/MCP optimization hooks plus a team steering rule (the BYOK OpenAI endpoint only under --org)cursor
VS Code Copilot Chatan Anyray chat provider (VS Code 1.121+)copilot
GitHub Copilot CLICOPILOT_PROVIDER_* env in your shell profile; seat-billed through the gateway's Copilot carrier route when a Copilot sign-in is readable, org-billed BYOK under --org or with no seatcopilot-cli
OpenCodeits direct API providers and its Copilot provideropencode
OpenClawits anthropic and openai providers in ~/.openclaw/openclaw.json, plus the prompt-cache setting its custom-host mode skipsopenclaw
pi / ompthe built-in anthropic and openai providers in ~/.pi/agent/models.json / ~/.omp/agent/models.yml, plus omp's retrieval MCP entrypi, omp
JetBrains AI AssistantAnyray Claude and Codex agents in its agent registryjetbrains
Devin DesktopAnyray Claude and Codex agents in its agent registrywindsurf
Shell & SDKsbase-URL env vars in the shell profileshell-env

The full on-disk footprint, every hook and MCP seam, background services, and the fleet command surface: Connect reference.

Bring the machine under policy

Add --endpoint to a --sign-in, --sso, --enroll, or --claim command to install the signed endpoint agent, so the device reports compliance. It takes one sudo prompt on macOS and Linux, or an elevated shell on Windows.

In the console, tick Also bring the machine under policy and the copied command carries the flag. Nothing adds it for you, and --no-endpoint never installs it.

Drive enrollment from a program

Add --json to --sign-in, --sso, --enroll, or --claim. Stdout becomes a stream of NDJSON events (sso_grant, enrolled, applied, error), human output moves to stderr, --yes is required, and no browser is opened.

Claude Code source hooks

Managed Claude hosts get a source hook with either credential lane. The console and Connect diagnostics report hook installation separately from retrieval. Two experimental trims: passing-command summaries and unchanged re-read stubs. Both stay off until paired session benchmarks establish savings. Switches, recovery path, and diagnostics: Claude Code source trims.

Uninstall

anyray-connect --revert restores every tool config Connect wrote and clears the stored enrollment. Restart any editor that was running. Reconnecting later needs a fresh enrollment link or the SSO command.

If the CLI is not on your PATH, pass the flag to the CLI, not to curl:

npx anyray-connect@latest --revert

Mixing both lanes in one organization

--subscription and --org are chosen per enrollment command, not once per deployment, so one gateway serves both at the same time. Publish one command per group, both carrying the same enrollment link.

Own Claude or ChatGPT plan
curl -fsSL https://app.anyray.ai/i/tnt_… | sh -s -- --subscription
LaneWhat the tool sendsWho pays
--subscriptionThe tool's own seat token, forwarded to Anthropic or OpenAI unchangedThe developer's plan
--orgThe personal gateway key. The gateway swaps in the server-held provider credentialThe org's provider account
neither flagWhichever of the two fits each tool on that machineDepends on what is signed in

Everyone still enrols normally and gets a personal gateway key, so per-user attribution works the same in both groups. The lanes stay separate inside the gateway: seat traffic keeps the developer's own token and deliberately skips the org's routing config, because routing every request to Bedrock cannot capture a seat request. Org-lane traffic pins no provider of its own, which is what lets routing steer it.

Always pass a lane flag to the group you are splitting

With no flag, Connect looks for a Claude or ChatGPT sign-in and uses the seat when it finds one. A developer meant to bill to the org account, who happens to be signed into Claude Code, silently bills their personal plan instead. --org makes that group deterministic, and the choice is remembered, so later key refreshes rebuild the same lane.

Assign the lane centrally instead

Two published commands leave the split to whichever one each person copied. Console → Tools → Billing lane decides it centrally, per team and per user.

1
Assign a team

Add the team id and pick Organization account or Own subscription. It covers everyone on that team: the seat's current SCIM-mapped team when SCIM manages the roster, otherwise the team set at enrollment. A SCIM group move re-lanes the seat on its next policy pull, with no re-enrollment.

2
Override individuals

Add a user id, usually their email, for anyone who differs. A user assignment wins over their team's. Setting a user to Automatic exempts them from their team's assignment rather than inheriting it.

3
Let the fleet apply it

Each machine picks the assignment up on its next policy pull and re-points every managed tool. anyray-connect sync applies it immediately.

An assignment overrides the flag the developer passes, and Connect says so when it does. Anyone with no assignment keeps the default behavior above, and --upstream BYO passthrough is neither lane and is left alone. An older gateway, an unreachable one, or a not-yet-enrolled developer all resolve to "unassigned", and enrollment proceeds on the developer's own choice. Governance that cannot be read degrades to ungoverned, never to broken.

Staying current

Every install method converges on one managed standalone binary at ~/.anyray/bin/anyray-connect, which connect.sh installs directly. Connect keeps every hook and MCP registration on that stable launcher, so the path never changes when the engine behind it does. The updater checks the published release about every 30 minutes, however the first run started.

Which engine runs a command depends on what is installed:

What is installedWhat runs your command
A verified desktop appIts bundled engine, preserving arguments, input, output, and exit code
No desktop appThe managed CLI. An absent app never blocks CLI recovery
A remote sessionIts own existing CLI installation
A source checkoutIts own launcher path

Credential helpers and protocol commands always run locally, with no engine discovery. npm and npx setup stay supported.

On CLI-only machines, maintenance keeps eligible refresh schedules installed and repoints them. The desktop app owns maintenance while it runs, with no separate refresh schedule. An old runtime copy is deleted after two safe passes, and only when the integrations verify as current: queued, unknown, or unreadable ones keep their older copy. Two standalone releases stay available for rollback, and doctor --json reports the recorded owner, its version when readable, the schedule, and recent cleanup events. Diagnostics still work from another installed version. For version conflicts, see installation repair.

Testing desktop startup needs a dedicated OS account: changing HOME does not isolate native login registration. CLI-only comparisons can use isolated homes for settings and enrollment.

The desktop app updates itself the same way: it downloads the new version, checks the published checksum and the Apple or Microsoft signature, then swaps it in and restarts. On Windows you confirm the install from the tray menu. The engine inside the app never updates on its own.

CommandWhat it does
anyray-connect --versionPrint the selected engine version and check for updates. Use --version --local to identify the invoked copy
anyray-connect updateCheck and install a standalone engine now. Inside the desktop app, report that the app owns updates and exit successfully
anyray-connect update --checkReport which version is published, and change nothing
anyray-connect update --auto offStop updating this machine automatically
anyray-connect update --auto onResume automatic updates, and update now

Fleet posture lives in Console → Tools → Connect updates:

ModeWhat happens
Automatic, the defaultMachines update themselves
Administrator-directedNothing downloads unattended. Versions land when an admin sends an update
OffNo Anyray process fetches a binary. You ship each version with your own tooling

The restricted modes suit fleets running behavioral endpoint security, which scores the download-and-run shape whatever the code signature (Fleet update policy). npm installs and platforms without a standalone binary: update path variants.

doctor and status --json also report source-trim evidence: whether the source lane has actually trimmed for this key, separately from hook installation.