SandboxClaude Code subscription

Claude Code on your Claude subscription

Run Claude Code in a cloud sandbox on your Claude Pro or Max plan. Model usage counts against your Claude plan; Tangle bills only the sandbox’s compute.

1. Create a token

On your machine, with Claude Code installed:

claude setup-token

It opens a browser to sign in to your Claude account and prints a long-lived OAuth token that starts with sk-ant-oat. Treat it like a password.

2. Store it as a secret

Store the token once as an account secret. Secrets are encrypted at rest, and no API returns their values.

export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-..."
tangle secret create CLAUDE_TOKEN --value-stdin <<< "$CLAUDE_CODE_OAUTH_TOKEN"

Or from TypeScript:

await client.secrets.create("CLAUDE_TOKEN", process.env.CLAUDE_CODE_OAUTH_TOKEN!);

3. Start the agent

import { Sandbox } from "@tangle-network/sandbox";
 
const client = new Sandbox({
  apiKey: process.env.TANGLE_API_KEY!,
  baseUrl: "https://sandbox.tangle.tools",
});
 
const agent = await client.create({
  name: "claude-on-my-plan",
  backend: {
    type: "claude-code",
    model: {
      cliAuth: { account: "me", secretEnv: "CLAUDE_TOKEN", format: "token" },
    },
  },
  secrets: ["CLAUDE_TOKEN"],
  git: { url: "https://github.com/your-org/your-repo" },
  idleTimeoutSeconds: 900,
});
await agent.waitFor("running");
 
const result = await agent.prompt("Summarize this repository in five bullets.", {
  sessionId: "main",
});
if (!result.success) throw new Error(result.error);
console.log(result.response);

From a terminal, the same agent is one command:

tangle sandbox create --name claude-on-my-plan --backend claude-code \
  --cli-auth CLAUDE_TOKEN --git-url https://github.com/your-org/your-repo
tangle agent prompt <sandbox-id> "Summarize this repository in five bullets." \
  --session main --stream

Three fields do the work:

FieldMeaning
backend.type: "claude-code"Run the Claude Code harness. Always set it; the default harness is OpenCode, which does not take a Claude token.
backend.cliAuthWhich secret holds the credential. format: "token" means the secret is the raw setup-token value. account is your own label for it.
secrets: ["CLAUDE_TOKEN"]Grants this sandbox that secret. The create request is refused if cliAuth names a secret you did not grant.

Do not inject the token as a plain environment variable such as CLAUDE_CODE_OAUTH_TOKEN. Without cliAuth, the platform configures Claude Code to use a Tangle model key and the harness ignores the variable.

In a workflow

A workflow’s agent.run runs on the same secret when its profile declares the source. Store the token under the name CLAUDE_TOKEN as above, then set model.metadata.credentialSource: subscription on a claude-code profile:

- id: review
  agent.run:
    profile:
      harness: claude-code
      model:
        default: anthropic/claude-sonnet-5-5
        metadata: { credentialSource: subscription }
      prompt: { instructions: ["Review the change."] }
    prompt: "Review the last commit."

The run creates its sandbox with backend.cliAuth and CLAUDE_TOKEN in secrets, and mints no Router key, so the Router bills nothing for it. A run whose account stored no CLAUDE_TOKEN fails with No stored secret named CLAUDE_TOKEN. The profile cannot run in a worker or as topology: inference, which only the Router serves.

Rotate or revoke

A secret name cannot be overwritten. To rotate, delete it and store the new token under the same name; sandboxes created afterwards use the new value.

claude setup-token
tangle secret delete CLAUDE_TOKEN --force
tangle secret create CLAUDE_TOKEN --value-stdin <<< "$CLAUDE_CODE_OAUTH_TOKEN"

To cut access everywhere at once, revoke the token in your Claude account settings.

From HTTP

Any language can start the same agent. On the wire, credential fields sit under backend.model. The body names the secret; the token never appears in it.

curl -X POST https://sandbox.tangle.tools/v1/sandboxes \
  -H "Authorization: Bearer $TANGLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "claude-on-my-plan",
    "backend": {
      "type": "claude-code",
      "model": {
        "cliAuth": { "account": "me", "secretEnv": "CLAUDE_TOKEN", "format": "token" }
      }
    },
    "secrets": ["CLAUDE_TOKEN"]
  }'

Troubleshooting

ResultCauseFix
401 OAuth access token is invalidThe token expired, was revoked, or was pasted with extra characters.Run claude setup-token again and rotate the secret.
400 Native authentication secret CLAUDE_TOKEN must be listed in secretscliAuth.secretEnv is not in secrets.Add the secret name to secrets.
cliAuth cannot be combined with API credentials, baseUrl, or inline authFilescliAuth was set together with apiKey, apiKeyEnv, baseUrl, or authFiles.Use one credential per backend.

A 401 from Anthropic proves the token reached Claude Code inside the sandbox: the remaining problem is the token itself.