All Products
Search
Document Center

Function Compute:Use Claude Code Sandbox

Last Updated:Sep 16, 2026

Claude Code is Anthropic's terminal-based AI coding agent that can read code, modify files, and execute commands within a sandbox. This article focuses on real-world task scenarios: cloning repositories, connecting MCP, extending Skills, structured output, and session resume. For image addresses, building a Template, creating a sandbox, and basic usage, see Claude Code Template.

If this is your first time, complete the prerequisites, API key creation, and SDK setup in Use FC Agent Sandbox with the SDK.

Prerequisites

  • Completed SDK integration (E2B API Key, api_url, domain)

  • Built a Template with status ready following Claude Code Template, created a sandbox, and initialized ~/.claude.json

  • Prepared a model API Key to inject via envs when creating the sandbox — images do not include pre-configured keys

Usage Scenarios

The following examples assume that the Template has been built, the sandbox has been created, and ~/.claude.json has been initialized.

Clone a Repository and Execute a Task

sandbox.git.clone(
    "https://github.com/your-org/your-repo.git",
    path="/home/user/repo",
    username="x-access-token",
    password="<your-github-token>",
    depth=1,
)

result = sandbox.commands.run(
    'cd /home/user/repo && claude --dangerously-skip-permissions < /dev/null '
    '-p "Add error handling to all API endpoints"',
    on_stdout=lambda data: print(data, end=""),
    timeout=0,
)

diff = sandbox.commands.run("cd /home/user/repo && git diff")
print(diff.stdout)

Get Structured JSON Output

import json

result = sandbox.commands.run(
    'claude --dangerously-skip-permissions --output-format json < /dev/null '
    '-p "List all files and describe each" 2>&1',
    timeout=0,
)

for line in reversed(result.stdout.strip().split("\n")):
    if line.startswith("{"):
        response = json.loads(line)
        break
else:
    raise RuntimeError("no JSON in output")

print(response.get("result") or response)

Streaming JSONL Output

import json

def handle_event(data):
    for line in data.strip().split("\n"):
        if line.startswith("{"):
            event = json.loads(line)
            if event["type"] == "assistant":
                usage = event.get("message", {}).get("usage", {})
                print(f"[assistant] tokens: {usage.get('output_tokens')}")
            elif event["type"] == "result":
                print(f"[done] {event['subtype']} in {event['duration_ms']}ms")

sandbox.commands.run(
    'claude --dangerously-skip-permissions --verbose --output-format stream-json < /dev/null '
    '-p "Find and fix all TODO comments" 2>&1',
    on_stdout=handle_event,
    timeout=0,
)

Resume a Session

import json

initial = sandbox.commands.run(
    'claude --dangerously-skip-permissions --output-format json < /dev/null '
    '-p "Analyze the codebase and create a refactoring plan" 2>&1',
    timeout=0,
)

for line in reversed(initial.stdout.strip().split("\n")):
    if line.startswith("{"):
        session_id = json.loads(line)["session_id"]
        break
else:
    raise RuntimeError("no session_id in output")

sandbox.commands.run(
    f'claude --dangerously-skip-permissions --resume {session_id} < /dev/null '
    f'-p "Now implement step 1 of the plan"',
    on_stdout=lambda data: print(data, end=""),
    timeout=0,
)

Custom System Prompt

sandbox.files.write("/home/user/repo/CLAUDE.md", """
You are working on a Go microservice.
Always use structured logging with slog.
Follow the project's error handling conventions in pkg/errors.
""")

sandbox.commands.run(
    'cd /home/user/repo && claude --dangerously-skip-permissions < /dev/null '
    '-p "Add a /healthz endpoint"',
    timeout=0,
)

Connect MCP Tools

Claude Code natively supports MCP. You can manually register MCP Servers via claude mcp add; the sandbox has outbound network access.

stdio local process (recommended):

sandbox.commands.run(
    "claude mcp add --transport stdio fs -- "
    "npx -y @modelcontextprotocol/server-filesystem /home/user",
    timeout=180,
)

result = sandbox.commands.run(
    'claude --dangerously-skip-permissions < /dev/null '
    '-p "Use the fs MCP tool to list /home/user and summarize top-level entries."',
    timeout=0,
)

HTTP remote Server:

sandbox.commands.run(
    "claude mcp add --transport http deepwiki https://mcp.deepwiki.com/mcp",
)

result = sandbox.commands.run(
    'claude --dangerously-skip-permissions < /dev/null '
    '-p "Use deepwiki MCP: what tools are available?"',
    timeout=0,
)

For MCP support and limitations, see “MCP and Skill Conventions” in Claude Code Template.

Extend Capabilities with Skills

The image does not preload custom Skills. A Skill is a Claude Code filesystem convention: place a directory that contains SKILL.md. For details, see Extend Claude with skills.

ScopePath
Personal (global within this sandbox)/home/user/.claude/skills/<name>/SKILL.md
Project<project>/.claude/skills/<name>/SKILL.md

How to trigger: explicitly call /skill-name in the -p prompt, or describe a matching task so the model loads it automatically. Claude Code also ships bundled skills such as /debug and /code-review that require no extra installation.

Write a personal Skill at runtime:

sandbox.files.write(
    "/home/user/.claude/skills/summarize-changes/SKILL.md",
    """---
description: Summarizes uncommitted changes and flags risks. Use when reviewing diffs or writing commit messages.
---

## Instructions
1. Run `git diff HEAD` and summarize changes in 2–3 bullets.
2. List risks such as missing error handling or hardcoded values.
3. If the diff is empty, say there are no uncommitted changes.
""",
)

result = sandbox.commands.run(
    'claude --dangerously-skip-permissions < /dev/null '
    '-p "/summarize-changes"',
    timeout=0,
)
print(result.stdout)

Project Skill (takes effect with the repository / working directory):

sandbox.files.write(
    "/home/user/repo/.claude/skills/api-conventions/SKILL.md",
    """---
description: API design conventions for this codebase. Use when adding or changing HTTP endpoints.
---

When writing API endpoints:
- Use RESTful naming
- Return consistent error formats
- Include request validation
""",
)

sandbox.commands.run(
    'cd /home/user/repo && claude --dangerously-skip-permissions < /dev/null '
    '-p "/api-conventions Add a /healthz endpoint"',
    timeout=0,
)

Upload a multi-file Skill directory from your local machine:

If a Skill includes accompanying files such as scripts/ or references/, use files.write_files to write them in one batch instead of calling files.write for each file:

from pathlib import Path

def upload_skill_dir(sandbox, local_dir: str, remote_root: str) -> None:
    local = Path(local_dir).resolve()
    entries = []
    for path in local.rglob("*"):
        if path.is_file():
            rel = path.relative_to(local).as_posix()
            entries.append({
                "path": f"{remote_root.rstrip('/')}/{rel}",
                "data": path.read_bytes(),
            })
    sandbox.files.write_files(entries)

# Example local directory layout:
# ./my-skills/echo-marker/SKILL.md
# ./my-skills/echo-marker/scripts/marker.txt
upload_skill_dir(
    sandbox,
    "./my-skills/echo-marker",
    "/home/user/.claude/skills/echo-marker",
)

result = sandbox.commands.run(
    'claude --dangerously-skip-permissions < /dev/null '
    '-p "/echo-marker"',
    timeout=0,
)
print(result.stdout)

For project scope, set remote_root to /home/user/repo/.claude/skills/<name> instead. You can also clone a repository that already contains .claude/skills/ and use it directly.

About Template.copy: Prefilling files with .copy("local-dir", "/home/user/.claude/skills/...") during Template.build is not supported yet. Use the runtime files.write / files.write_files approaches above for custom Skills.

Billing

Sandboxes are billed based on CPU and memory specifications and runtime duration; model API call costs are billed separately by the model provider. See Billing Overview for details.

FAQ

IssueSolution
Corrupted config errorecho '{}' > /home/user/.claude.json
Agent not respondingVerify that envs includes the model Key; for China, use the Bailian envs configuration; for International, confirm ANTHROPIC_API_KEY is injected
Build failureVerify that FROM_IMAGE matches the region
name 'TEMPLATE_NAME' is not definedObtain the template name from the console and replace TEMPLATE_NAME
Other SDK / build issuesSee Template Management

References

  • Claude Code Template (image addresses, build Template, create sandbox and basic run, environment overview, MCP/Skill capability notes)