Problem Statement
Currently Claude Code users who subscribe to the Pro or Max plans are unable to use OpenShell with their Anthropic paid plans because OpenShell's Claude Code runner only supports API key auth. A workaround that greatly jeopardizes security is possible that is also tedious: Authenticating using the OAuth flow inside the sandbox's Claude instance.
As an enterprise or individual subscriber to a Claude Pro or Max plan, I should be able to securely, natively use my plan with OpenShell for Oauth2 grants.
Proposed Design
I propose creating a native new provider type anthropic-oauth that enables the behavior I'm seeking - running Claude Code on a subscription instead of metered API key. I'd create a new inference protocol that sets the proper headers, use the same Oauth token pattern as Vertex where the token is acquired, stored, and refreshed in the trust boundary OUTSIDE the sandbox, and then injected at the egress proxy boundary.
The Openshell CLI, prior to spawning a sandbox, would read the local filesystem of the running machine for Claude Code subscription creds. I'd support both macOS and Linux by retrieving the key from the keychain store and falling back to .credentials.json (old Claude Code on macOS, Linux uses this primitive).
Since the headers need to be updated to support the way Anthropic subscription plans implement Oauth, we'd rebuild the supervisor image to make some small header changes.
Alternatives Considered
Considered building a more custom, less OOTB implementation letting Openshell run arbitrary pre-run workflows (shell scripts, a la how Atlantis/Dockerfiles can be configured). I ultimately deemed this not necessary as having secure persistent Claude Oauth credentials available to the runtime is my only objective at this time. I also noticed native primitives already existed for this model (good example is the Vertex ADC pattern), so decided to use this route instead.
Agent Investigation
- New provider type anthropic-oauth (alias claude-plan): lets a sandbox run Claude Code on an Anthropic
- Pro/Max subscription instead of a metered API key, reusing the Vertex --from-gcloud-adc pattern.
- Core invariant: the OAuth token is acquired, stored, and refreshed entirely outside the sandbox and
injected only at the egress proxy boundary — never in the sandbox env, filesystem, or logs.
- New inference profile (openshell-core/inference.rs): AuthHeader::Bearer + mandatory default headers
anthropic-version: 2023-06-01 and anthropic-beta: oauth-2025-04-20 (subscription tokens require the beta
flag; API keys don't). Auth/headers derive purely from provider_type, so a new behavior needs a new type.
- Non-injectable credential: ANTHROPIC_OAUTH_TOKEN is marked proxy-only
(is_non_injectable_provider_credential), so it rides the route bundle into the supervisor but is never
exported into sandbox env — same mechanism as Vertex's GOOGLE_SERVICE_ACCOUNT_KEY.
- Host-side harvest (--from-claude-login): CLI reads the local Claude Code login (macOS Keychain Claude
Code-credentials, falling back to ~/.claude/.credentials.json), extracts accessToken/refreshToken/expiresAt,
and stores the access token as the proxy-only credential.
- Gateway-side refresh reused: configures the existing Oauth2RefreshToken strategy with Anthropic's public
client_id (no client secret) and token_url: https://console.anthropic.com/v1/oauth/token; the background
worker refreshes ahead of expiry and persists the rotated refresh token.
- Live propagation, no restart: refreshed tokens reach running sandboxes via the revisioned on-demand
GetSandboxProviderEnvironment fetch — the route bundle updates in place.
- Router beta-merge (openshell-router/backend.rs): merges the mandatory anthropic-beta flag with any
client-sent anthropic-beta into one header (case-insensitive dedupe), so a sandbox client can't drop the
OAuth flag and we never emit a duplicate.
- Supervisor applies the boundary headers (not the gateway), so the supervisor ghcr image must be rebuilt —
a stale supervisor silently drops the headers and Anthropic returns 400.
- Validated end-to-end on macOS: token absent from sandbox env/fs, Bearer injected at the boundary, live
200/pong completion (model must be claude-sonnet-4-6, since CLI 2.1.156 sends an effort param that 4-5
rejects). Linux uses the same OS-agnostic file reader — expected to work, flagged as not-yet-tested.
Checklist
Problem Statement
Currently Claude Code users who subscribe to the Pro or Max plans are unable to use OpenShell with their Anthropic paid plans because OpenShell's Claude Code runner only supports API key auth. A workaround that greatly jeopardizes security is possible that is also tedious: Authenticating using the OAuth flow inside the sandbox's Claude instance.
As an enterprise or individual subscriber to a Claude Pro or Max plan, I should be able to securely, natively use my plan with OpenShell for Oauth2 grants.
Proposed Design
I propose creating a native new provider type
anthropic-oauththat enables the behavior I'm seeking - running Claude Code on a subscription instead of metered API key. I'd create a new inference protocol that sets the proper headers, use the same Oauth token pattern as Vertex where the token is acquired, stored, and refreshed in the trust boundary OUTSIDE the sandbox, and then injected at the egress proxy boundary.The Openshell CLI, prior to spawning a sandbox, would read the local filesystem of the running machine for Claude Code subscription creds. I'd support both macOS and Linux by retrieving the key from the keychain store and falling back to .credentials.json (old Claude Code on macOS, Linux uses this primitive).
Since the headers need to be updated to support the way Anthropic subscription plans implement Oauth, we'd rebuild the supervisor image to make some small header changes.
Alternatives Considered
Considered building a more custom, less OOTB implementation letting Openshell run arbitrary pre-run workflows (shell scripts, a la how Atlantis/Dockerfiles can be configured). I ultimately deemed this not necessary as having secure persistent Claude Oauth credentials available to the runtime is my only objective at this time. I also noticed native primitives already existed for this model (good example is the Vertex ADC pattern), so decided to use this route instead.
Agent Investigation
injected only at the egress proxy boundary — never in the sandbox env, filesystem, or logs.
anthropic-version: 2023-06-01 and anthropic-beta: oauth-2025-04-20 (subscription tokens require the beta
flag; API keys don't). Auth/headers derive purely from provider_type, so a new behavior needs a new type.
(is_non_injectable_provider_credential), so it rides the route bundle into the supervisor but is never
exported into sandbox env — same mechanism as Vertex's GOOGLE_SERVICE_ACCOUNT_KEY.
Code-credentials, falling back to ~/.claude/.credentials.json), extracts accessToken/refreshToken/expiresAt,
and stores the access token as the proxy-only credential.
client_id (no client secret) and token_url: https://console.anthropic.com/v1/oauth/token; the background
worker refreshes ahead of expiry and persists the rotated refresh token.
GetSandboxProviderEnvironment fetch — the route bundle updates in place.
client-sent anthropic-beta into one header (case-insensitive dedupe), so a sandbox client can't drop the
OAuth flag and we never emit a duplicate.
a stale supervisor silently drops the headers and Anthropic returns 400.
200/pong completion (model must be claude-sonnet-4-6, since CLI 2.1.156 sends an effort param that 4-5
rejects). Linux uses the same OS-agnostic file reader — expected to work, flagged as not-yet-tested.
Checklist