Skip to main content

OpenShell Claude Code Sandbox

Back to agent catalog | main doc

Type: Builtin Sandbox Framework: Claude Code CLI (Anthropic) LLM: Anthropic API (requires real API key) Supervisor: Yes (all protection layers active) Sandbox Model: Tier 1 (OpenShell Sandbox CR, full supervisor) Status: Sandbox CR tested, LLM execution blocked (needs Anthropic key)

1. Overview

Pre-installed Claude Code CLI in the OpenShell base sandbox image. Claude Code is the highest-value integration target because it natively reads .claude/skills/ — no prompt injection needed for rossoctl skill execution. Session transcripts are stored as JSONL files on disk, enabling rich session browsing via the Rossoctl FileBrowser.

2. Architecture

3. Files

# No custom files — uses upstream OpenShell base image
# Image: ghcr.io/nvidia/openshell-community/sandboxes/base:latest (~1.1GB)
# CRD: agents.x-k8s.io/v1alpha1 Sandbox

4. Deployment

kubectl apply -f - <<EOF
apiVersion: agents.x-k8s.io/v1alpha1
kind: Sandbox
metadata:
name: claude-sandbox
namespace: team1
spec:
podTemplate:
spec:
containers:
- name: sandbox
image: ghcr.io/nvidia/openshell-community/sandboxes/base:latest
volumeMounts:
- name: workspace
mountPath: /sandbox
volumes:
- name: workspace
persistentVolumeClaim:
claimName: claude-workspace-pvc
EOF

LLM Provider Configuration

kubectl set env statefulset/openshell-gateway -n openshell-system \
ANTHROPIC_API_KEY=<real-anthropic-key>

5. Capabilities

CapabilitySupportedNotes
A2A protocolNoCLI agent, accessed via SSH or ExecSandbox gRPC
Multi-turn contextYesTerminal session maintains full conversation context
Tool callingYesNative: file edit, bash, web fetch, LSP, MCP servers
Subagent delegationYesNative subagent dispatch (Task system)
Memory/knowledgeYes.claude/agent-memory/ persistent across sessions
Skill executionNativeReads .claude/skills/ directly — best skill support
HITL approvalL0-L3Permission prompts for destructive actions

Claude Code-Specific Features

FeatureStorageFormatRossoctl Exposure
Session transcripts~/.claude/projects/{uuid}.jsonlJSONL (append-only)FileBrowser + SessionSidebar
Task system~/.claude/tasks/JSON DAGsSubSessionsPanel
Agent memory.claude/agent-memory/*/MEMORY.mdMarkdownFileBrowser (read-only)
Skills.claude/skills/*/SKILL.mdMarkdownSkill catalog
Settings.claude/settings.jsonJSONConfig panel
Keybindings.claude/keybindings.jsonJSONN/A (terminal-only)
Tool callsEmbedded in JSONL transcriptsPart objectsAgentLoopCard
Thinking blocksEmbedded in JSONL transcriptsContent blocksLoopDetail (collapsible)

6. Rossoctl Integration

6.1 Communication Adapter

ExecSandbox gRPC (Phase 2) — Rossoctl backend calls ExecSandbox RPC on the OpenShell gateway to send prompts to Claude Code running in the sandbox.

Alternative: Terminal Adapter (Phase 3) — WebSocket → SSH tunnel for interactive browser-based terminal via xterm.js.

6.2 Session Management

DataStorageSurvives Restart?Rossoctl Access
Conversation transcript/sandbox/.claude/projects/*.jsonlYes (PVC)FileBrowser
Task list/sandbox/.claude/tasks/Yes (PVC)SubSessionsPanel
Agent memory/sandbox/.claude/agent-memory/Yes (PVC)FileBrowser
In-memory contextProcess memoryNo (lost on restart)N/A
Workspace files/sandbox/project/Yes (PVC)FileBrowser

6.3 Observable Events

EventSourceRossoctl UI ComponentPhase
Session transcriptJSONL on PVCFileBrowser, SessionSidebarPhase 2
Task creation/completion~/.claude/tasks/SubSessionsPanelPhase 2
Subagent dispatchTask metadataSubSessionsPanelPhase 2
Tool calls (bash, edit)JSONL content blocksAgentLoopCard, EventsPanelPhase 2
Thinking blocksJSONL content blocksLoopDetail (collapsible)Phase 2
File modificationsWorkspace PVC diffFileBrowserPhase 2
Permission promptsHook eventsHitlApprovalCardPhase 3
Memory updates.claude/agent-memory/FileBrowserPhase 2
Token usageSession metadataLlmUsagePanelPhase 2
Git operations.git/ in workspaceFileBrowserPhase 2

6.4 FileBrowser Integration

PathContentBrowsablePreview
/sandbox/.claude/projects/*.jsonlSession transcriptsYesJSONL → Markdown conversion
/sandbox/.claude/tasks/Task DAGsYesJSON tree view
/sandbox/.claude/agent-memory/Persistent knowledgeYesMarkdown rendering
/sandbox/.claude/skills/*/SKILL.mdRossoctl skillsYesMarkdown rendering
/sandbox/.claude/settings.jsonPermissions configYesJSON syntax highlight
/sandbox/project/Agent-modified codeYesFull syntax highlight

7. LLM Compatibility

ProviderProtocolWorks?Notes
Anthropic APIClaude messagesYesNative — required
LiteMaaSOpenAI-compatNoClaude CLI validates model names against Anthropic catalog
OllamaOpenAI-compatNoSame validation issue
OpenRouterMulti-providerPartialCan route to Claude models

Key limitation: Claude CLI requires a real Anthropic API key. It cannot use OpenAI-compatible proxies because it validates the model name against Anthropic's model catalog at startup.

8. Policy Configuration

All supervisor protection layers are active in the base image:

LayerMechanismConfig
FilesystemLandlock LSMread-only: /usr, /etc; read-write: /sandbox, /tmp
Networknetns + OPA proxyHTTP CONNECT via 10.200.0.1:3128
ProcessSeccomp BPFDangerous syscalls blocked
InferenceCredential strippingGateway injects Anthropic key

9. Skill Execution

Claude Code is the highest-value skill target because it natively reads .claude/skills/ directories — no prompt injection needed. Rossoctl skills can be mounted into the sandbox workspace and Claude Code discovers them automatically.

Supported Skills (Blocked — Needs Real Anthropic Key)

SkillTestStatusBlocker
PR Reviewtest_pr_review__openshell_claudeSKIPReal Anthropic API key required
RCAtest_rca__openshell_claudeSKIPReal Anthropic API key required
Security Reviewtest_security_review__openshell_claudeSKIPReal Anthropic API key required
TDDNot testedSame blocker
Docs ReviewNot testedSame blocker

Why Claude Code Can't Use LiteLLM

Claude Code validates model names against Anthropic's model catalog at startup. It cannot use OpenAI-compatible proxies (LiteMaaS, LiteLLM, Ollama) because:

  1. The CLI sends requests to the Anthropic messages API format, not OpenAI format
  2. It validates that the model ID matches claude-* patterns
  3. It checks for a valid ANTHROPIC_API_KEY (not OPENAI_API_KEY)

Path to Enabling Skills (Paolo's Provider Workflow)

Once TLS + ingress are configured (see architecture alignment):

# 1. Create provider with real Anthropic key (or LiteLLM with Anthropic routing)
openshell provider create --name anthropic \
--type generic \
--credential "ANTHROPIC_AUTH_TOKEN=<real-anthropic-key>"

# 2. Policy allowing Anthropic API (or your LiteLLM endpoint)
cat > /tmp/policy-anthropic.yaml << 'EOF'
version: 1
network_policies:
anthropic:
name: Anthropic API
endpoints:
- host: api.anthropic.com
port: 443
access: full
binaries:
- path: /usr/local/bin/claude
- path: /usr/bin/node
- path: /usr/local/bin/node
EOF

# 3. Create Claude Code sandbox with provider
openshell sandbox create --name skill-test \
--provider anthropic \
--policy /tmp/policy-anthropic.yaml \
--no-auto-providers

# 4. Inside sandbox — skills are auto-discovered from .claude/skills/
claude --print "Review this PR diff: ..."

Alternative: LiteLLM with Anthropic Model Routing

If your LiteLLM instance can route to a real Anthropic model:

# LiteLLM config with real Anthropic model
model_list:
- model_name: claude-sonnet-4-20250514
litellm_params:
model: anthropic/claude-sonnet-4-20250514
api_key: sk-ant-...

Then set ANTHROPIC_BASE_URL to the LiteLLM endpoint. Claude Code will see the claude-* model name and accept it.

10. Testing Status

Test FileTestsPassSkipNotes
test_04_sandbox_lifecycle110Sandbox CR created
test_07_skill_execution303Needs real Anthropic key
test_10_workspace_persistence211PVC write passes; sandbox creation skips

11. Sandbox Deployment Models

ModelSupportedNotes
Mode 1: Rossoctl DeploymentNot applicableCLI agent, not a standalone service
Mode 2: Sandbox CRCurrentGateway creates pod from base image
Mode 2 + PVCSupportedWorkspace persists via PVC
Mode 2 + dtachPlannedSession survives CLI disconnect

A2A Adapter Design for Claude Code

Claude Code is not an A2A service. To integrate with the Rossoctl backend:

The -p flag sends a single prompt to Claude Code in non-interactive mode. The response streams back via ExecSandbox's stdout event stream.

For multi-turn, the backend includes conversation history in the prompt:

claude -p "Previous conversation: ... \n\nNew message: ..."

Claude Code's session files on the PVC provide an alternative history source.