NVIDIA OpenShell · Lesson 1 · Lab

Your first sandboxed Claude Code

In about 20 minutes you'll run Claude Code inside an OpenShell sandbox where it can reach only Anthropic's API. Its API key is a placeholder it can't steal, and you'll prove both facts yourself.

OpenShell is NVIDIA's open-source (Apache-2.0) runtime for "executing fleets of autonomous AI agents in sandboxed environments with kernel-level isolation", controlled by "a declarative YAML policy".overview For you, that means one thing: let Claude Code work with fewer guardrails inside it, because the guardrails now live outside it.

Read this before you search the web

OpenShell 0.1.0 (2026-09-25) broke the 0.0.x CLI.upgrade Most blog posts, including NVIDIA's March launch blog and the DGX Spark playbook, still show --from openclaw, openshell inference set or a "Privacy Router". None of those exist any more. This course targets v0.1.2.

1 · The mental model: who holds what

Your Mac (host) Gateway · 127.0.0.1:17670 encrypted credential store (your real key) policy · providers
↓ delivers policy + credentials to…
Trusted side of the boundary Supervisor checks every request vs policy swaps placeholder → real key opens approved connections
↑ the ONLY channel out (no direct network)
Workload: the sandbox (non-root · no capabilities · Landlock · seccomp) claude bash, curl, git… anything it spawns ANTHROPIC_API_KEY = <placeholder>
The agent never has a network card or a real key. Everything it sends goes to the supervisor. The supervisor asks "which binary is this, and which host is it calling?" and only then forwards the request, with the real credential if the request is allowed.

Three ideas carry the whole course:arch

  1. Deny by default. A sandbox with no policy has no network, plus read-only system paths.default
  2. Binary scoping. Network rules name the program as well as the host. Your key reaches api.anthropic.com only when the request comes from /usr/local/bin/claude.
  3. Placeholder credentials. "The agent process inside the sandbox never sees real credential values."providers

Same shape as the BlueField isolation argument: the thing that enforces policy sits where the protected workload can't tamper with it.

2 · The lab

You need

An Apple Silicon Mac with Docker Desktop ≥ 28 running (Linux amd64/arm64 also works; WSL2 is experimental),matrix and an Anthropic API key. Use an empty scratch directory. No customer data or company code goes into lab sandboxes.

  1. Install OpenShell and check the gateway. On macOS the script installs through Homebrew and starts the gateway as a Homebrew service.install
    curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
    openshell status        # gateway should be reachable
    Telemetry is on by default. The opt-out is OPENSHELL_TELEMETRY_ENABLED=false on the gateway (see the telemetry docs).
  2. Build an image that contains Claude Code. The default image (nvcr.io/nvidia/base/ubuntu:24.04) ships no agent CLIs, and --from no longer builds Dockerfiles, so you build it yourself.images Save as Dockerfile.claude:
    FROM nvcr.io/nvidia/base/ubuntu:24.04
    RUN apt-get update && apt-get install -y --no-install-recommends \
          ca-certificates curl git bash && rm -rf /var/lib/apt/lists/*
    # Native installer, then put the binary where the claude-code profile expects it
    RUN curl -fsSL https://claude.ai/install.sh | bash \
     && cp /root/.local/bin/claude /usr/local/bin/claude && chmod 755 /usr/local/bin/claude
    RUN useradd -m -d /sandbox -s /bin/bash sandbox
    USER sandbox
    WORKDIR /sandbox
    docker build -t claude-agent:local -f Dockerfile.claude .
    The /usr/local/bin/claude path matters. It is exactly what the profile's binaries: list allows. This install recipe comes from NVIDIA's (now retired) community base image.
  3. Import the Claude Code provider profile. The gateway ships no built-in profiles. Read the profile first: the key goes as x-api-key to api.anthropic.com (plus statsig.anthropic.com and sentry.io for telemetry), and only from /usr/bin/claude or /usr/local/bin/claude.
    openshell profile import \
      --url https://raw.githubusercontent.com/NVIDIA/OpenShell/main/providers/claude-code.yaml
    openshell profile list
  4. Hand your key to the gateway, never to a file. Type the key into the current shell only (it isn't echoed and stays out of history). The provider reads it, then you unset it.
    read -rs ANTHROPIC_API_KEY && export ANTHROPIC_API_KEY   # paste, Enter
    openshell provider create --name my-claude --type claude-code --from-existing
    unset ANTHROPIC_API_KEY
    openshell provider list
  5. Smoke test. This is the profile's own one-shot test.
    openshell sandbox create --name claude-smoke --from claude-agent:local \
      --provider my-claude -- claude -p 'reply with OK'
    You should see OK. The request left the sandbox through the supervisor, which swapped in your real key on the way.
  6. Start an interactive sandbox you'll keep poking at.
    openshell sandbox create --name claude-lab --from claude-agent:local \
      --provider my-claude -- claude
    If Claude Code asks whether to use the detected API key, say yes. That "key" is the placeholder.

Prove the fence (second terminal)

Don't take the diagram on faith. Leave Claude running, open another terminal, and run each probe. Predict the outcome before you press Enter.

# A · what key does the workload actually hold?
openshell sandbox exec --name claude-lab -- sh -c 'echo $ANTHROPIC_API_KEY'

# B · can an arbitrary program reach an arbitrary host?
openshell sandbox exec --name claude-lab -- curl -sS -m 5 https://example.com

# C · can curl ride on Claude's allowance to the SAME host?
openshell sandbox exec --name claude-lab -- curl -sS -m 5 https://api.anthropic.com

# D · what did the supervisor see, and what was it actually enforcing?
openshell logs claude-lab --source sandbox
openshell policy get claude-lab --full
openshell rule get claude-lab --status pending     # drafted proposals. DON'T approve yet

You should see:

Probe C is the one to remember.

The win, in one sentence

Claude Code is running with a key it can't read and a network it can't widen. Anything it (or a prompt-injected tool call) tries beyond api.anthropic.com is denied, logged, and turned into a proposal you decide on.

Clean up (keep the image and the provider for Lesson 2):

openshell sandbox delete claude-smoke claude-lab
Troubleshooting

Check yourself

In probe C, why is curl to api.anthropic.com denied?
Where does your real Anthropic key live during the lab?
You start a sandbox with no policy and no provider. What network does it get?
Primary source — read this next

NVIDIA's OpenShell Architecture page (gateway, supervisor, sandbox, network fence), then the GitHub push access tutorial, which is where we're heading.