# claude --cloud: the GitHub token never enters the VM

> Each Claude Code cloud task gets a fresh VM (~4 vCPU, 16 GB, 30 GB). Your GitHub token stays in a proxy outside the box; the session only gets a short-lived credential that can push to its own branch.

URL: https://bartlomiejkrupa.dev/articles/claude-code-cloud-sessions/
Published: 2026-10-14
Updated: 2026-10-14
Tags: claude-code, cloud-sessions, teleport, security, sandboxing, github
Summary: Each Claude Code cloud task gets a fresh VM (~4 vCPU, 16 GB, 30 GB). Your GitHub token stays in a proxy outside the box; the session only gets a short-lived credential that can push to its own branch.

`claude --cloud "<prompt>"` starts a Claude Code session on a fresh Anthropic-managed VM - about **4 vCPUs, 16 GB RAM, and 30 GB disk** - with your repo cloned onto a new branch. The feature that matters for security is not the extra CPU. Your GitHub token never enters that VM. A proxy outside the box holds it; the session only gets a short-lived credential that can push to its own working branch. That is a harder boundary than local `/sandbox`, which still wraps Bash on a machine that already holds your SSH keys and cloud CLIs.

The work is not safe until it is on a remote branch. Idle VMs get reclaimed. If the Claude GitHub App does not cover the repo, `--cloud` may upload a bundle that cannot push back - often with no clear warning until you look for the branch.

## What you get vs what stays local

| | Local Claude Code | Cloud session (`--cloud`) |
| --- | --- | --- |
| Machine | Your laptop | Fresh VM per task |
| Laptop sleep / offline | Session stops | Session keeps going |
| Parallel tasks on one repo | Worktrees, ports, care | One VM and one branch per task |
| Credentials in reach | Whatever your user can use | Session-scoped GitHub credential + connectors you enable |
| Config that travels | Full `~/.claude` | Repo `CLAUDE.md`, rules, skills, agents, commands - not your personal `~/.claude` |
| Ends with | Working-tree edits | A branch (and a PR when you want one) |
| Compute bill | Your machine | No separate VM charge; uses plan limits |

Stay local when the task needs something only your machine has: a real local database, a VPN service, a GPU, a phone simulator, or hardware on your desk. Stay local for tight visual loops, and when your organization uses **Zero Data Retention (ZDR)**, which turns cloud sessions off. Use cloud when isolation, parallelism, or "keep running while the laptop sleeps" is the point.

Local Bash isolation is a different layer. [Claude Code security: when /sandbox is not enough](/articles/claude-code-security-sandboxing-2026) covers `/sandbox`, sandbox-runtime, containers, and VMs. Cloud sessions sit at the top of that ladder for "no local secrets in the agent's reach" - with the caveat that None network still talks to Anthropic and can still push via the proxy.

## The security model in one picture

These four rules are what actually change day-to-day work:

1. **One VM per task.** Sessions cannot see each other's files or ports. Split parallel work along file boundaries and merge branches in a sensible order. One session will sometimes report a bug another session is already fixing - that is expected, not a failure.
2. **GitHub token stays outside.** The proxy issues a short-lived, branch-scoped credential. Untrusted install scripts and contributor PRs run without sitting next to your SSH keys.
3. **Repo config travels; personal config does not.** Put test commands in `CLAUDE.md`. Commit skills under `.claude/`. Project MCP belongs in `.mcp.json`. A **SessionStart hook** is a repo hook that runs when a session begins - gate cloud-only steps with the `CLAUDE_CODE_REMOTE` environment variable (set in cloud, unset locally).
4. **Idle VMs are reclaimed.** Reopening restores the conversation on a fresh machine. If you have not committed, that work is gone with the old VM.

Network levels, from narrow to wide: **None**, **Trusted** (default: registries, GitHub, major cloud SDK hosts), **Custom**, **Full**. Outbound traffic is proxied and hostnames are logged. Even at None, Anthropic API traffic and own-branch pushes still work.

## When cloud pays off

Addy Osmani's field guide ran three parallel cloud sessions on one sample repo. Started within 16 seconds of each other, all three finished **87 seconds** after the first start (61 / 65 / 72 s each). That is the guide author's run on a small sample repository, not your production monorepo - treat it as a shape of parallelism, not a benchmark you will hit.

Patterns that fit:

- **Backlog in parallel** - several small, unrelated fixes, each with its own proof command.
- **Proof that burns laptop time** - run the suite dozens of times, bisect across many commits, start the app and curl every endpoint.
- **Plan locally, build in the cloud** - agree the plan in `--permission-mode plan`, commit it, then `claude --cloud "Execute the plan in …"`.
- **Untrusted code** - a fresh clone, a new dependency's install script, or a contributor PR, with network set to None or Trusted.

Foreground commands time out after **2 minutes** by default (**10** max), then can continue in the background for up to **30** more. Raise defaults with `BASH_DEFAULT_TIMEOUT_MS` and `BASH_MAX_TIMEOUT_MS`. A long test loop inside one command still counts as agent turns against your plan, but it does not burn your laptop CPU.

## GitHub: the usual failure mode

Cloud sessions need two separate GitHub permissions. Signing in with GitHub tells Claude who you are. Installing the **Claude GitHub App** on the owning account or org sets which private repos Claude can see.

| Connected | Public repos | Your private repos | Org private repos |
| --- | --- | --- | --- |
| GitHub sign-in only | Yes | No | No |
| + App on your personal account | Yes | Yes | No |
| + App on the organization (owner approves) | Yes | Only if also on your account | Yes |

Paste-string errors and fixes:

| What you see | Likely cause | Fix |
| --- | --- | --- |
| "You must be an owner of the organization to link it" | Pending App permission request, IP allow list, or SAML | Owner accepts the request, enables IP allow list inheritance for installed Apps, or grants Claude access under SAML |
| Private repo missing from the picker | App not installed on the owning account/org, or repo excluded from App access | Install the App there, or add the repo in GitHub App repository access |
| Org repos missing right after connect | SAML authorize step skipped | Authorize Claude for that org in GitHub, then reconnect |
| Session uploaded a bundle, cannot push | No App coverage / no push path for that remote | Install the App, or use a GitHub remote the connection can push to |

`claude --cloud` clones your GitHub remote at your **current** branch - push local commits first. Two alternate paths exist: `/web-setup` sends your existing `gh` CLI token to Claude (Team/Enterprise owners must enable Quick setup first), and a repo with no GitHub remote (or no App) uploads a **bundle** of the tree instead of cloning - push-back only works if the connection has push access. GitLab and Bitbucket can upload a bundle but cannot push back from cloud sessions.

## Do not strand the work

A GitHub issue report (#100853) describes finished work left unretrievable after an idle reclaim - one task took three launches and roughly 3 h 50 min, with about 2.5 h of work the reporter could not get back. Treat that as a single user report, not a rate. The short version is in the note [push before cloud, commit before idle](/notes/push-before-cloud-commit-before-idle). The durable habits are the same either way:

1. **Push before `--cloud`.** Unpushed commits never reach the VM.
2. **Commit as you go** on long tasks. Idle reclaim is expected.
3. **Finish background shells before you walk away.** A turn that ends with tests still running in the background is a reclaim risk.
4. **Prove done in the prompt.** Name the command (`npm test` N times, curl every endpoint). Read the summary before the diff.
5. **Teleport or PR when finished.** `claude --teleport` or `/tp` pulls the session local - same repo, clean tree (stash offered), branch already pushed. Or open the PR from claude.ai/code.

Queue a follow-up from anywhere you are logged in:

```bash
claude -p "rebase on main and fix conflicts" --cloud <session-id>
```

October 2026 Claude Code releases (2.1.290–2.1.296) fixed `--teleport` cases that deleted files in a folder or opened an empty conversation - upgrade if teleport misbehaves.

## Setup that lets the agent check itself

- Start from the **Default** environment (Trusted network, no setup script) for common JS/Python/Go/Rust repos.
- Use a **setup script** (runs as root, must exit 0, aim for ~5 minutes) so heavy installs land in a cached snapshot. Cache rebuilds when the script or allowed hosts change, and about every **7 days**. Running processes do not survive the cache - start services per session or in a SessionStart hook.
- Put `npm install`-style steps in a repo SessionStart hook; gate cloud-only steps with `CLAUDE_CODE_REMOTE` ([snippet](/notes/claude-code-remote-env-gate)).
- Keep secrets out of shared environment variables. On Pro/Max, API credentials for named hosts can attach outside the VM so keys never sit in a variable the agent can read.

## Bottom line

Reach for `claude --cloud` when you need a disposable machine, parallel branches, or a secret boundary harder than local `/sandbox`. Keep the Claude GitHub App installed where the repo lives. Push before you launch. Commit before the session goes idle. An unpushed cloud session is unfinished work.

For the local isolation ladder that cloud sits above, see [when /sandbox is not enough](/articles/claude-code-security-sandboxing-2026). More Claude Code notes: [Claude](/topics/claude).

Sources:
- Claude Code in the cloud: a field guide to cloud sessions: https://claude.dev/blog/claude-code-in-the-cloud/
- Claude Code changelog: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md
- --cloud: finished work stranded (#100853): https://github.com/anthropics/claude-code/issues/100853
- Simon Willison on Cowork moving the VM to the cloud: https://simonwillison.net/2026/Oct/5/felix-rieseberg/
