claude-code-on-the-web.md +58 −9
109 </Step>109 </Step>
110</Steps>110</Steps>
111 111
112### Link artifacts back to the session
113
114Each cloud session has a transcript URL on claude.ai, and the session can read its own ID from the `CLAUDE_CODE_REMOTE_SESSION_ID` environment variable. Use this to put a traceable link in PR bodies, commit messages, Slack posts, or generated reports so a reviewer can open the run that produced them.
115
116Ask Claude to construct the link from the environment variable. The following command prints the URL:
117
118```bash theme={null}
119echo "https://claude.ai/code/${CLAUDE_CODE_REMOTE_SESSION_ID}"
120```
121
112### Run tests, start services, and add packages122### Run tests, start services, and add packages
113 123
114Claude runs tests as part of working on a task. Ask for it in your prompt, like "fix the failing tests in `tests/`" or "run pytest after each change." Test runners like pytest, jest, and cargo test work out of the box since they're pre-installed.124Claude runs tests as part of working on a task. Ask for it in your prompt, like "fix the failing tests in `tests/`" or "run pytest after each change." Test runners like pytest, jest, and cargo test work out of the box since they're pre-installed.
115 125
116126PostgreSQL and Redis are pre-installed but not running by default. Start each one in a [setup script](#setup-scripts) or ask Claude to start it during the session:PostgreSQL and Redis are pre-installed but not running by default. Ask Claude to start each one during the session:
117 127
118```bash theme={null}128```bash theme={null}
119service postgresql start129service postgresql start
123service redis-server start133service redis-server start
124```134```
125 135
126136Docker is available for running containerized services. Network access to pull images follows your environment's [access level](#access-levels).Docker is available for running containerized services. Ask Claude to run `docker compose up` to start your project's services. Network access to pull images follows your environment's [access level](#access-levels), and the [Trusted defaults](#default-allowed-domains) include Docker Hub and other common registries.
127 137
128138To add packages that aren't pre-installed, use a [setup script](#setup-scripts) so they're available at session start. You can also ask Claude to install packages during the session, but those installs don't persist across sessions.If your images are large or slow to pull, add `docker compose pull` or `docker compose build` to your [setup script](#setup-scripts). The pulled images are saved in the [cached environment](#environment-caching), so each new session has them on disk. The cache stores files only, not running processes, so Claude still starts the containers each session.
139
140To add packages that aren't pre-installed, use a [setup script](#setup-scripts). The script's output is [cached](#environment-caching), so packages you install there are available at the start of every session without reinstalling each time. You can also ask Claude to install packages mid-session, but those installs don't carry over to other sessions.
129 141
130### Resource limits142### Resource limits
131 143
171apt update && apt install -y gh183apt update && apt install -y gh
172```184```
173 185
174Setup scripts run only when creating a new session. They are skipped when resuming an existing session.
175
176If the script exits non-zero, the session fails to start. Append `|| true` to non-critical commands to avoid blocking the session on an intermittent install failure.186If the script exits non-zero, the session fails to start. Append `|| true` to non-critical commands to avoid blocking the session on an intermittent install failure.
177 187
178<Note>188<Note>
179 Setup scripts that install packages need network access to reach registries. The default **Trusted** network access allows connections to [common package registries](#default-allowed-domains) including npm, PyPI, RubyGems, and crates.io. Scripts will fail to install packages if your environment uses **None** network access.189 Setup scripts that install packages need network access to reach registries. The default **Trusted** network access allows connections to [common package registries](#default-allowed-domains) including npm, PyPI, RubyGems, and crates.io. Scripts will fail to install packages if your environment uses **None** network access.
180</Note>190</Note>
181 191
192### Environment caching
193
194The setup script runs the first time you start a session in an environment. After it completes, Anthropic snapshots the filesystem and reuses that snapshot as the starting point for later sessions. New sessions start with your dependencies, tools, and Docker images already on disk, and the setup script step is skipped. This keeps startup fast even when the script installs large toolchains or pulls container images.
195
196The cache captures files, not running processes. Anything the setup script writes to disk carries over. Services or containers it starts do not, so start those per session by asking Claude or with a [SessionStart hook](#setup-scripts-vs-sessionstart-hooks).
197
198The setup script runs again to rebuild the cache when you change the environment's setup script or allowed network hosts, and when the cache reaches its expiry after roughly seven days. Resuming an existing session never re-runs the setup script.
199
200You don't need to enable caching or manage snapshots yourself.
201
182### Setup scripts vs. SessionStart hooks202### Setup scripts vs. SessionStart hooks
183 203
184Use a setup script to install things the cloud needs but your laptop already has, like a language runtime or CLI tool. Use a [SessionStart hook](/en/hooks#sessionstart) for project setup that should run everywhere, cloud and local, like `npm install`.204Use a setup script to install things the cloud needs but your laptop already has, like a language runtime or CLI tool. Use a [SessionStart hook](/en/hooks#sessionstart) for project setup that should run everywhere, cloud and local, like `npm install`.
186Both run at the start of a session, but they belong to different places:206Both run at the start of a session, but they belong to different places:
187 207
188| | Setup scripts | SessionStart hooks |208| | Setup scripts | SessionStart hooks |
189209| ------------- | ------------------------------------------------- | -------------------------------------------------------------- || ------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
190| Attached to | The cloud environment | Your repository |210| Attached to | The cloud environment | Your repository |
191| Configured in | Cloud environment UI | `.claude/settings.json` in your repo |211| Configured in | Cloud environment UI | `.claude/settings.json` in your repo |
192212| Runs | Before Claude Code launches, on new sessions only | After Claude Code launches, on every session including resumed || Runs | Before Claude Code launches, when no [cached environment](#environment-caching) is available | After Claude Code launches, on every session including resumed |
193| Scope | Cloud environments only | Both local and cloud |213| Scope | Cloud environments only | Both local and cloud |
194 214
195SessionStart hooks can also be defined in your user-level `~/.claude/settings.json` locally, but user-level settings don't carry over to cloud sessions. In the cloud, only hooks committed to the repo run.215SessionStart hooks can also be defined in your user-level `~/.claude/settings.json` locally, but user-level settings don't carry over to cloud sessions. In the cloud, only hooks committed to the repo run.
235* **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, check the `CLAUDE_CODE_REMOTE` environment variable as shown above.255* **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, check the `CLAUDE_CODE_REMOTE` environment variable as shown above.
236* **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.256* **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.
237* **Proxy compatibility**: all outbound traffic passes through a [security proxy](#security-proxy). Some package managers don't work correctly with this proxy. Bun is a known example.257* **Proxy compatibility**: all outbound traffic passes through a [security proxy](#security-proxy). Some package managers don't work correctly with this proxy. Bun is a known example.
238258* **Adds startup latency**: hooks run each time a session starts or resumes. Keep install scripts fast by checking whether dependencies are already present before reinstalling.* **Adds startup latency**: hooks run each time a session starts or resumes, unlike setup scripts which benefit from [environment caching](#environment-caching). Keep install scripts fast by checking whether dependencies are already present before reinstalling.
239 259
240To persist environment variables for subsequent Bash commands, write to the file at `$CLAUDE_ENV_FILE`. See [SessionStart hooks](/en/hooks#sessionstart) for details.260To persist environment variables for subsequent Bash commands, write to the file at `$CLAUDE_ENV_FILE`. See [SessionStart hooks](/en/hooks#sessionstart) for details.
241 261
242262Custom environment images and snapshots are not yet supported.Replacing the base image with your own Docker image is not yet supported. Use a setup script to install what you need on top of the [provided image](#installed-tools), or run your image as a container alongside Claude with `docker compose`.
243 263
244## Network access264## Network access
245 265
734* **Credential protection**: sensitive credentials such as git credentials or signing keys are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials.754* **Credential protection**: sensitive credentials such as git credentials or signing keys are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials.
735* **Secure analysis**: code is analyzed and modified within isolated VMs before creating PRs755* **Secure analysis**: code is analyzed and modified within isolated VMs before creating PRs
736 756
757## Troubleshooting
758
759For runtime API errors that appear in the conversation such as `API Error: 500`, `529 Overloaded`, `429`, or `Prompt is too long`, see the [Error reference](/en/errors). Those errors and their fixes are shared with the CLI and Desktop app. The sections below cover issues specific to cloud sessions.
760
761### Session creation failed
762
763If a new session fails to start with `Session creation failed` or stalls at provisioning, Claude Code could not allocate a cloud environment.
764
765* Check [status.claude.com](https://status.claude.com) for cloud session incidents
766* Retry after a minute, as capacity is provisioned on demand
767* Confirm your repository is reachable. Private repositories require either the GitHub App installed with access to that repository, or a `gh` token synced via `/web-setup`. See [GitHub authentication options](#github-authentication-options).
768
769### Remote Control session expired or access denied
770
771`--teleport` connects through the same Remote Control session infrastructure that cloud sessions use, so authentication and session-expiry errors surface with Remote Control wording. You may see `Remote Control session has expired` or `Access denied`. The connection token is short-lived and scoped to your account.
772
773* Run `/login` locally to refresh your credentials, then reconnect
774* Confirm you are signed in to the same account that owns the session
775* If you see `Remote Control may not be available for this organization`, your admin has not enabled remote sessions for your plan
776
777### Environment expired
778
779Cloud sessions stop after a period of inactivity and the underlying environment is reclaimed. From a local terminal, this surfaces as `Could not resume session ... its environment has expired. Creating a fresh session instead.` On the web, the session is marked expired in the session list.
780
781Reopen the session from [claude.ai/code](https://claude.ai/code) to provision a fresh environment with your conversation history restored.
782
737## Limitations783## Limitations
738 784
739Before relying on cloud sessions for a workflow, account for these constraints:785Before relying on cloud sessions for a workflow, account for these constraints:
741* **Rate limits**: Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel consumes more rate limits proportionately. There is no separate compute charge for the cloud VM.787* **Rate limits**: Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel consumes more rate limits proportionately. There is no separate compute charge for the cloud VM.
742* **Repository authentication**: you can only move sessions from web to local when you are authenticated to the same account788* **Repository authentication**: you can only move sessions from web to local when you are authenticated to the same account
743* **Platform restrictions**: repository cloning and pull request creation require GitHub. Self-hosted [GitHub Enterprise Server](/en/github-enterprise-server) instances are supported for Team and Enterprise plans. GitLab, Bitbucket, and other non-GitHub repositories can be sent to cloud sessions as a [local bundle](#send-local-repositories-without-github), but the session can't push results back to the remote789* **Platform restrictions**: repository cloning and pull request creation require GitHub. Self-hosted [GitHub Enterprise Server](/en/github-enterprise-server) instances are supported for Team and Enterprise plans. GitLab, Bitbucket, and other non-GitHub repositories can be sent to cloud sessions as a [local bundle](#send-local-repositories-without-github), but the session can't push results back to the remote
790* **Organization IP allowlist**: cloud sessions call the Anthropic API from Anthropic-managed infrastructure, not your network. If your organization has [IP allowlisting](https://support.claude.com/en/articles/13200993-restrict-access-to-claude-with-ip-allowlisting) enabled, every cloud session fails with an authentication error. The same applies to [Code Review](/en/code-review) and [Routines](/en/routines). Contact [Anthropic support](https://support.claude.com/) to exempt Anthropic-hosted services from your organization's IP allowlist.
744 791
745## Related resources792## Related resources
746 793
794* [Ultraplan](/en/ultraplan): draft a plan in a cloud session and review it in your browser
795* [Ultrareview](/en/ultrareview): run a deep multi-agent code review in a cloud sandbox
747* [Routines](/en/routines): automate work on a schedule, via API call, or in response to GitHub events796* [Routines](/en/routines): automate work on a schedule, via API call, or in response to GitHub events
748* [Hooks configuration](/en/hooks): run scripts at session lifecycle events797* [Hooks configuration](/en/hooks): run scripts at session lifecycle events
749* [Settings reference](/en/settings): all configuration options798* [Settings reference](/en/settings): all configuration options