This tutorial walks through an iterative sandbox policy workflow. You launch a sandbox, ask Claude Code to push code to GitHub, and observe the default network policy denying the request. You then diagnose the denial from your machine and from inside the sandbox, apply a policy update, and verify that the update takes effect. After completing this tutorial, you will have:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/NVIDIA/OpenShell/llms.txt
Use this file to discover all available pages before exploring further.
- A running sandbox with Claude Code that can push to a GitHub repository.
- A custom network policy that grants GitHub access for a specific repository.
- Experience with the policy iteration workflow: fail, diagnose, update, verify.
This tutorial shows example prompts and responses from Claude Code. The exact
wording you see might vary between sessions. Use the examples as a guide for
the type of interaction, not as expected output.
Prerequisites
- A working OpenShell installation. Complete the Quickstart before proceeding.
- A GitHub personal access token (PAT) with
reposcope. Generate one from the GitHub personal access token settings page by selecting Generate new token (classic) and enabling thereposcope. - An Anthropic account with access to Claude Code. OpenShell provides the sandbox runtime, not the agent. You must authenticate with your own account.
- A GitHub repository you own to use as the push target. A scratch repository is sufficient. You can create one with a README if needed.
- Terminal 1: The sandbox terminal. You create the sandbox in this terminal by running
openshell sandbox createand interact with Claude Code inside it. - Terminal 2: A terminal outside the sandbox on your machine. You use this terminal for viewing sandbox logs with
openshell termand applying an updated policy withopenshell policy set.
Tutorial
Set up a sandbox with your GitHub token
- Starting a new sandbox
- Using an existing sandbox
In Terminal 2, create a credential provider that injects your GitHub token into the sandbox automatically. The provider reads
GITHUB_TOKEN from your host environment and sets it as an environment variable inside the sandbox.The default policy is applied automatically, which allows read-only access to GitHub.openshell sandbox create keeps the sandbox running after Claude Code exits so you can apply policy updates without recreating the environment. Add --no-keep if you want the sandbox deleted automatically instead.Claude Code starts inside the sandbox. It prints an authentication link. Open it in your browser, sign in to your Anthropic account, and return to the terminal. When prompted, trust the /sandbox workspace to allow Claude Code to read and write files.Push code to GitHub
In Terminal 1, ask Claude Code to write a simple script and push it to your repository. Replace Claude recognizes that it needs GitHub credentials. It asks how you want to authenticate. Provide your GitHub personal access token by pasting it into the conversation. Claude configures authentication and attempts the push.The push fails. Claude reports an error, but the failure is not an authentication problem. The default sandbox policy permits read-only access to GitHub and blocks write operations, so the proxy denies the push before the request reaches the GitHub server.
<org> with your GitHub organization or username and <repo> with your repository name.Diagnose the denial
View the logs from your machine
In Terminal 2, launch the OpenShell terminal:l7_decision=deny. Select a deny entry to see the full detail:PUT request to api.github.com and denied it. The github_rest_api policy allows read operations (GET) but blocks write operations (PUT, POST, DELETE). A similar denial appears for github.com if Claude attempted a git push over HTTPS.Ask Claude Code to check the sandbox logs
In Terminal 1, ask Claude Code to investigate:
The sandbox runs a proxy that enforces policies on outbound traffic.
The github_rest_api policy allows GET requests (used to read the file)
but blocks PUT/write requests to GitHub. This is a sandbox-level restriction,
not a token issue. No matter what token you provide, pushes through the API
will be blocked until the policy is updated.
Both perspectives confirm the same thing: the proxy is doing its job. The default policy is designed to be restrictive. To allow GitHub pushes, you need to update the network policy.Copy the deny reason from Claude’s response. You paste it into an agent on your machine in the next step.Generate an updated policy
In Terminal 2, paste the deny reason from the previous step into your coding agent on your machine (such as Claude Code or Cursor) and ask it to recommend a policy update. The deny reason gives the agent the context it needs to generate the correct policy rules.The agent will:
- Inspect the deny reasons.
- Write an updated policy that adds
github_gitandgithub_apiblocks granting write access to your repository. - Save the policy to
/tmp/sandbox-policy-update.yaml.
Review the generated policy
Before applying, review the generated policy against the reference below. Confirm it grants only the access you expect — in this case,
git push operations and GitHub REST API access scoped to a single repository.Full reference policy
Full reference policy
The following YAML shows a complete policy that extends the default policy with GitHub access for a single repository. Replace The following table summarizes the two GitHub-specific blocks:
The remaining blocks (
<org> with your GitHub organization or username and <repo> with your repository name.The filesystem_policy, landlock, and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox.| Block | Endpoint | Behavior |
|---|---|---|
github_git | github.com:443 | Git Smart HTTP protocol. Permits info/refs (clone/fetch), git-upload-pack (fetch data), and git-receive-pack (push) for the specified repository. Denies all operations on unlisted repositories. |
github_api | api.github.com:443 | REST API. Permits all HTTP methods for the specified repository path and GraphQL queries. Denies API access to unlisted repositories. |
claude_code, nvidia_inference, pypi, vscode) are identical to the default policy. The default policy’s github_ssh_over_https and github_rest_api blocks are replaced by github_git and github_api, which grant write access to the specified repository.Apply the policy
After reviewing the generated policy, apply it to the running sandbox:Network policies are hot-reloadable. The
--wait flag blocks until the policy engine confirms the new revision loaded. The update takes effect immediately without restarting the sandbox or reconnecting Claude Code.Retry the push
In Terminal 1, ask Claude Code to retry:The push completes successfully. The
openshell term dashboard now shows l7_decision=allow entries for api.github.com and github.com where it previously showed denials.What’s next
Policy schema reference
Add per-repository access levels, restrict to specific API methods, and explore all available policy fields.
Sandbox policies
Learn the full policy iteration workflow: pull, edit, push, verify.
Manage providers
Inject credentials automatically instead of pasting tokens.
First network policy
Go back to the basics: create a sandbox and apply an L7 read-only rule.