Skip to main content

Remote and ephemeral machines

anyray-connect sets up the machine it runs on, but your coding agent often runs somewhere else. Each remote is one headless command away from your gateway.

Every path takes --yes, so nothing prompts. None needs a browser on the remote: the CLI prints a URL, you open it anywhere, and the remote finishes on its own.

Devcontainers and Codespaces

1
Store the enrollment link as a secret

Add your org's SSO link, or a shared enrollment link, as a Codespaces or devcontainer secret named ANYRAY_SSO_LINK. Secrets arrive as environment variables, so the link never sits in a committed file.

2
Bootstrap in postCreateCommand
.devcontainer/devcontainer.json
{
"postCreateCommand": "curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- --sso \"$ANYRAY_SSO_LINK\" --yes"
}

The installer puts anyray-connect on PATH, enrolls, and applies.

The container is routed

Run anyray-connect status inside it. The apply also pulls your org's skills and connectors, so they are there from postCreateCommand on.

What a container skips, and why that is correct

A container has no launchd or systemd --user, so connect skips the OS refresh schedule on purpose. The session renews the key instead, through Claude Code's apiKeyHelper or a throttled tick. Connect also skips self-update, because a container updates when you rebuild the image. Neither skip is a failure, and status names the backend it found.

Mount a directory, not a single config file

Mounting a single file to keep tool state across rebuilds (say ~/.claude.json) pins that path as a mount point, and Linux will not let anything replace one in a single step. Connect writes such files in place instead, which doctor reports. Mount the parent directory or a volume:

.devcontainer/devcontainer.json
{
// Prefer a directory or volume mount: atomic config writes keep working.
"mounts": ["source=claude-state,target=/home/vscode/.claude-state,type=volume"]
// Avoid: "type=bind,source=${localEnv:HOME}/.claude.json,target=/home/vscode/.claude.json"
}
Connect lists the environments you work in

An interactive run shows its plan first. Under Other environments you work in it lists the SSH remotes, containers, WSL distros, Codespaces, and tunnels found in your editors' recent history. A run only configures the machine it runs on, so read that list as a checklist.

Machines that stay

Run the normal installer on the host. It prints a sign-in URL and a code, which you open in the browser on your laptop.

curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- --sso https://app.anyray.ai/sso/tnt_example --yes
MachineWhat to do
SSH hostRun the command above. It is a real machine, so the systemd --user refresh schedule installs normally.
Persistent Windows desktop (Azure Virtual Desktop, Windows 365, Citrix with a roaming profile)Run the installer once. A Scheduled Task keeps the key, skills, and connectors fresh.
Non-persistent Windows poolThe profile resets at logoff, so nothing survives. Enroll on login with the managed installer and policy file.

Commit the routing with the repo

Configure the repo once instead of every machine. Then every checkout routes, including checkouts on machines you never touch.

1
Run it in the repo
anyray-connect --project --yes
2
Commit the two files it writes
FileWhat it carries
.claude/settings.jsonANTHROPIC_BASE_URL pointing at the gateway, plus an apiKeyHelper (anyray-connect print-key) that fetches each developer's own key when it is needed.
.codex/config.tomlAn Anyray model_providers block using the same helper. No key is written out.

Neither file holds a credential, an identity, or an absolute path. Each machine still needs anyray-connect installed and enrolled once.

Every checkout routes

To undo it, run anyray-connect --project --revert in the repo and commit that. It removes exactly what was written and leaves your other settings alone.

A committed config bills through the org API lane

A subscription seat is per developer and per machine, so it cannot ride a committed file. Every machine that opens the repo bills through the org API, which is why the command asks first.

CI jobs

1
Enroll the job as an agent

Give the job its own service key and put it in the runner's secret store.

2
Run the bootstrap
export ANYRAY_CLIENT_KEY=ark_svc_… # from the runner's secret store
curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- --gateway <origin> --yes

Add --tools shell-env if the job only needs the SDK environment.

The job is routed

A service key never refreshes, so the container needs no schedule and no helper. What else changes on that lane: Service keys.

Hosted cloud agents

Codex cloud tasks, Cursor cloud agents, Devin, Claude Code on the web, and the Copilot cloud agent run on the vendor's own machines, so no machine config can route them. Checked against each vendor's docs in July 2026.

Hosted agentCan you inject secrets?Can you redirect its inference?
OpenAI Codex cloudYes: per-repo environments, setup scriptsNo
Cursor cloud agentsYes: dashboard secrets, environment.jsonNo, curated models via Cursor's backend
DevinYes: org secrets, YAML blueprintsNo, "does not currently support third-party LLM API keys"
Claude Code on the webYes: cloud environments (no secrets store)No, inference rides an Anthropic-bound channel
Copilot cloud agentYes: Agents secrets, copilot-setup-steps.ymlNo, endpoint pinned to api.*.githubcopilot.com

Every vendor lets the sandbox reach your gateway through an egress allowlist, but the agent's own model client stays outside it. The vendor bills that spend.

Hosted-agent coverage

The one partial opening today is the Copilot cloud agent on self-hosted runners, where inference crosses your own network. If hosted-agent visibility matters to your org, tell us.