> ## Documentation Index
> Fetch the complete documentation index at: https://code.storage/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandboxes

> Clone repositories into ephemeral sandbox environments for AI agents, code execution, and isolated development.

Sandbox environments let you run code in isolated, ephemeral containers. Using Git as your source of truth—rather than provider-specific storage like volumes—gives you version history, branching, and portability across any sandbox provider.

Code Storage integrates with popular sandbox providers through authenticated Git URLs—generate a URL with the SDK, then clone inside your sandbox.

> **Note:** For fastest cloning in ephemeral environments, consider using a shallow single-branch clone – this skips commit history and other branches—ideal for sandboxes where you only need the latest code:

```bash theme={"theme":{"light":"github-light","dark":"min-dark"}}
git clone --depth 1 --single-branch <url> repo
```

## Quick start

Generate an authenticated Git URL and use it inside any sandbox:

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import { GitStorage } from '@pierre/storage';

  const store = new GitStorage({
    name: 'your-org',
    key: process.env.PIERRE_PRIVATE_KEY,
  });

  const repo = await store.findOne({ id: 'my-project' });

  // Read-only access
  const readUrl = await repo.getRemoteURL({
    permissions: ['git:read'],
    ttl: 3600,
  });

  // Read-write access (for pushing changes)
  const writeUrl = await repo.getRemoteURL({
    permissions: ['git:read', 'git:write'],
    ttl: 3600,
  });
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import os
  from pierre_storage import GitStorage

  storage = GitStorage({
      "name": "your-org",
      "key": os.environ["PIERRE_PRIVATE_KEY"],
  })

  repo = await storage.find_one(id="my-project")

  # Read-only access
  read_url = await repo.get_remote_url(
      permissions=["git:read"],
      ttl=3600,
  )

  # Read-write access (for pushing changes)
  write_url = await repo.get_remote_url(
      permissions=["git:read", "git:write"],
      ttl=3600,
  )
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  ctx := context.Background()

  // Find the repository
  repo, err := client.FindOne(ctx, storage.FindOneOptions{ID: "my-project"})

  // Read-only access
  readURL, err := repo.RemoteURL(ctx, storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead},
  	TTL:         time.Hour,
  })

  // Read-write access (for pushing changes)
  writeURL, err := repo.RemoteURL(ctx, storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  	TTL:         time.Hour,
  })
  ```
</CodeGroup>

## Modal

[Modal](https://modal.com) provides serverless cloud functions with persistent volumes. Clone repositories into volumes, run code, and push changes back.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import { ModalClient } from 'modal';
  import { GitStorage } from '@pierre/storage';

  const modal = new ModalClient();
  const store = new GitStorage({
    name: 'your-org',
    key: process.env.PIERRE_PRIVATE_KEY,
  });

  async function runInModalSandbox(repoId: string) {
    const repo = await store.findOne({ id: repoId });
    const url = await repo.getRemoteURL({
      permissions: ['git:read', 'git:write'],
      ttl: 3600,
    });

    // Create a Modal sandbox
    const app = await modal.apps.fromName('code-runner', { createIfMissing: true });
    const image = modal.images.fromRegistry('python:3.12-slim');
    const sb = await modal.sandboxes.create(app, image);

    // Shallow clone for speed
    await sb.exec(['git', 'clone', '--depth', '1', '--single-branch', url, '/code/repo']);
    await sb.exec(['git', 'config', '--global', 'user.email', 'agent@example.com']);
    await sb.exec(['git', 'config', '--global', 'user.name', 'AI Agent']);

    // Run tests or make changes
    const result = await sb.exec(['pytest', '/code/repo/tests']);
    console.log(await result.stdout.readText());

    // Commit and push changes
    await sb.exec(['git', '-C', '/code/repo', 'add', '.']);
    await sb.exec(['git', '-C', '/code/repo', 'commit', '-m', 'Update from sandbox']);
    await sb.exec(['git', '-C', '/code/repo', 'push']);

    await sb.terminate();
  }
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import modal
  import subprocess
  import os
  from pierre_storage import GitStorage

  app = modal.App("code-runner")
  vol = modal.Volume.from_name("code-cache", create_if_missing=True)

  storage = GitStorage({
      "name": "your-org",
      "key": os.environ["PIERRE_PRIVATE_KEY"],
  })

  @app.function(volumes={"/code": vol})
  async def run_in_sandbox(repo_id: str):
      repo = await storage.find_one(id=repo_id)
      url = await repo.get_remote_url(
          permissions=["git:read", "git:write"],
          ttl=3600,
      )

      # Shallow clone for speed
      subprocess.run(
          ["git", "clone", "--depth", "1", "--single-branch", url, "/code/repo"],
          check=True,
      )
      subprocess.run(
          ["git", "config", "--global", "user.email", "agent@example.com"],
          check=True,
      )
      subprocess.run(
          ["git", "config", "--global", "user.name", "AI Agent"],
          check=True,
      )

      # Run tests or make changes
      subprocess.run(["pytest", "/code/repo/tests"], check=True)

      # Commit and push changes
      subprocess.run(["git", "-C", "/code/repo", "add", "."], check=True)
      subprocess.run(
          ["git", "-C", "/code/repo", "commit", "-m", "Update from sandbox"],
          check=True,
      )
      subprocess.run(["git", "-C", "/code/repo", "push"], check=True)

      vol.commit()
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Generate a Git URL, then use your sandbox provider's API or shell to clone and run commands
  repo, err := client.FindOne(context.Background(), storage.FindOneOptions{ID: "my-project"})

  // Read-write access (for pushing changes)
  url, err := repo.RemoteURL(context.Background(), storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  	TTL:         time.Hour,
  })

  // Example shell commands inside a sandbox:
  // exec.Command("git", "clone", "--depth", "1", "--single-branch", url, "/code/repo").Run()
  // exec.Command("git", "-C", "/code/repo", "push").Run()
  ```
</CodeGroup>

## E2B

[E2B](https://e2b.dev) provides cloud sandboxes for AI agents. Clone repositories, execute code, and push results back to Code Storage.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import { Sandbox } from 'e2b';
  import { GitStorage } from '@pierre/storage';

  const store = new GitStorage({
    name: 'your-org',
    key: process.env.PIERRE_PRIVATE_KEY,
  });

  async function runAgentTask(repoId: string) {
    const repo = await store.findOne({ id: repoId });
    const url = await repo.getRemoteURL({
      permissions: ['git:read', 'git:write'],
      ttl: 3600,
    });

    const sandbox = await Sandbox.create();

    // Shallow clone for speed
    await sandbox.commands.exec(`git clone --depth 1 --single-branch ${url} /home/user/repo`);
    await sandbox.commands.exec('git config --global user.email "agent@example.com"');
    await sandbox.commands.exec('git config --global user.name "AI Agent"');

    // Run commands and make changes
    await sandbox.commands.exec('cd /home/user/repo && npm install');
    await sandbox.commands.exec('cd /home/user/repo && npm test');

    // Agent generates new code...
    await sandbox.commands.exec('echo "// Generated by AI" >> /home/user/repo/src/index.ts');

    // Commit and push
    await sandbox.commands.exec('cd /home/user/repo && git add .');
    await sandbox.commands.exec('cd /home/user/repo && git commit -m "Agent changes"');
    await sandbox.commands.exec('cd /home/user/repo && git push');

    await sandbox.kill();
  }
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import os
  from e2b import Sandbox
  from pierre_storage import GitStorage

  storage = GitStorage({
      "name": "your-org",
      "key": os.environ["PIERRE_PRIVATE_KEY"],
  })

  async def run_agent_task(repo_id: str):
      repo = await storage.find_one(id=repo_id)
      url = await repo.get_remote_url(
          permissions=["git:read", "git:write"],
          ttl=3600,
      )

      sandbox = Sandbox()

      # Shallow clone for speed
      sandbox.commands.run(f"git clone --depth 1 --single-branch {url} /home/user/repo")
      sandbox.commands.run('git config --global user.email "agent@example.com"')
      sandbox.commands.run('git config --global user.name "AI Agent"')

      # Run commands and make changes
      sandbox.commands.run("cd /home/user/repo && pip install -r requirements.txt")
      sandbox.commands.run("cd /home/user/repo && pytest")

      # Agent generates new code...
      sandbox.commands.run('echo "# Generated by AI" >> /home/user/repo/main.py')

      # Commit and push
      sandbox.commands.run("cd /home/user/repo && git add .")
      sandbox.commands.run('cd /home/user/repo && git commit -m "Agent changes"')
      sandbox.commands.run("cd /home/user/repo && git push")

      sandbox.kill()
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Find the repository
  repo, err := client.FindOne(context.Background(), storage.FindOneOptions{ID: "my-project"})

  // Generate a Git URL with read-write access
  url, err := repo.RemoteURL(context.Background(), storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  	TTL:         time.Hour,
  })

  // In your sandbox shell:
  // git clone --depth 1 --single-branch <url> /home/user/repo
  // git -C /home/user/repo push
  ```
</CodeGroup>

## Daytona

[Daytona](https://daytona.io) provides secure sandboxes for AI agents. Clone repositories using Daytona's built-in Git API, run commands, and push changes back.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import { Daytona } from '@daytonaio/sdk';
  import { GitStorage } from '@pierre/storage';

  const store = new GitStorage({
    name: 'your-org',
    key: process.env.PIERRE_PRIVATE_KEY,
  });

  const daytona = new Daytona();

  async function runInDaytona(repoId: string) {
    const repo = await store.findOne({ id: repoId });
    const url = await repo.getRemoteURL({
      permissions: ['git:read', 'git:write'],
      ttl: 3600,
    });

    // Create sandbox
    const sandbox = await daytona.create();

    // Clone using Daytona's Git API
    await sandbox.git.clone(url, '/home/daytona/repo');

    // Run commands
    await sandbox.process.executeCommand('npm install', '/home/daytona/repo');
    await sandbox.process.executeCommand('npm test', '/home/daytona/repo');

    // Make changes and commit using Git API
    await sandbox.git.add('/home/daytona/repo', ['.']);
    await sandbox.git.commit('/home/daytona/repo', 'Update from sandbox', 'AI Agent', 'agent@example.com');
    await sandbox.git.push('/home/daytona/repo');

    await sandbox.delete();
  }
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  import os
  from daytona_sdk import Daytona
  from pierre_storage import GitStorage

  storage = GitStorage({
      "name": "your-org",
      "key": os.environ["PIERRE_PRIVATE_KEY"],
  })

  daytona = Daytona()

  async def run_in_daytona(repo_id: str):
      repo = await storage.find_one(id=repo_id)
      url = await repo.get_remote_url(
          permissions=["git:read", "git:write"],
          ttl=3600,
      )

      # Create sandbox
      sandbox = daytona.create()

      # Clone using Daytona's Git API
      sandbox.git.clone(url, "/home/daytona/repo")

      # Run commands
      sandbox.process.exec("pip install -r requirements.txt", cwd="/home/daytona/repo")
      sandbox.process.exec("pytest", cwd="/home/daytona/repo")

      # Make changes and commit using Git API
      sandbox.git.add("/home/daytona/repo", ["."])
      sandbox.git.commit("/home/daytona/repo", "Update from sandbox", "AI Agent", "agent@example.com")
      sandbox.git.push("/home/daytona/repo")

      sandbox.delete()
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Find the repository
  repo, err := client.FindOne(context.Background(), storage.FindOneOptions{ID: "my-project"})

  // Generate a Git URL with read-write access
  url, err := repo.RemoteURL(context.Background(), storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  	TTL:         time.Hour,
  })

  // Use the Daytona Go SDK if available, or run git commands in the sandbox shell.
  ```
</CodeGroup>

## Ephemeral branches for isolation

Use [ephemeral branches](/guides/ephemeral-branches) to isolate sandbox work from your main codebase. Changes stay in the ephemeral namespace until you promote them.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  const repo = await store.findOne({ id: 'my-project' });

  // Get URL for ephemeral namespace
  const ephemeralUrl = await repo.getEphemeralRemoteURL({
    permissions: ['git:read', 'git:write'],
    ttl: 3600,
  });

  // In your sandbox:
  // git clone --depth 1 --single-branch <ephemeralUrl> repo
  // git checkout -b sandbox/experiment-123
  // ... make changes ...
  // git push -u origin sandbox/experiment-123

  // When ready, promote the ephemeral branch
  await repo.promoteEphemeralBranch({
    baseBranch: 'sandbox/experiment-123',
    targetBranch: 'feature/new-capability',
  });
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  repo = await storage.find_one(id="my-project")

  # Get URL for ephemeral namespace
  ephemeral_url = await repo.get_ephemeral_remote_url(
      permissions=["git:read", "git:write"],
      ttl=3600,
  )

  # In your sandbox:
  # git clone --depth 1 --single-branch <ephemeral_url> repo
  # git checkout -b sandbox/experiment-123
  # ... make changes ...
  # git push -u origin sandbox/experiment-123

  # When ready, promote the ephemeral branch
  await repo.promote_ephemeral_branch(
      base_branch="sandbox/experiment-123",
      target_branch="feature/new-capability",
  )
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Find the repository
  repo, err := client.FindOne(context.Background(), storage.FindOneOptions{ID: "my-project"})

  // Get URL for ephemeral namespace
  ephemeralURL, err := repo.EphemeralRemoteURL(context.Background(), storage.RemoteURLOptions{
  	Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  	TTL:         time.Hour,
  })

  // When ready, promote the ephemeral branch
  result, err := repo.PromoteEphemeralBranch(context.Background(), storage.PromoteEphemeralBranchOptions{
  	BaseBranch: "sandbox/experiment-123",
  	// TargetBranch: "feature/new-capability", // optional, defaults to BaseBranch
  })
  fmt.Println(result.TargetBranch)
  ```
</CodeGroup>

## Provider resilience

Many teams run multiple sandbox providers for maximum resilience. With Git as your source of truth, you can failover between providers without losing work—if one has an outage or capacity issues, spin up a sandbox elsewhere and clone the same repository:

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  async function runWithFallback(repoId: string, task: () => Promise<void>) {
    const repo = await store.findOne({ id: repoId });
    const url = await repo.getRemoteURL({
      permissions: ['git:read', 'git:write'],
      ttl: 3600,
    });

    try {
      // Try primary provider
      const e2b = await E2BSandbox.create();
      await e2b.commands.exec(`git clone --depth 1 --single-branch ${url} /repo`);
      await task();
    } catch (err) {
      // Fallback to secondary provider
      const daytona = new Daytona();
      const sandbox = await daytona.create();
      await sandbox.git.clone(url, '/repo');
      await task();
    }
  }
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  async def run_with_fallback(repo_id: str, task):
      repo = await storage.find_one(id=repo_id)
      url = await repo.get_remote_url(
          permissions=["git:read", "git:write"],
          ttl=3600,
      )

      try:
          # Try primary provider
          e2b = Sandbox()
          e2b.commands.run(f"git clone --depth 1 --single-branch {url} /repo")
          await task()
      except Exception:
          # Fallback to secondary provider
          daytona = Daytona()
          sandbox = daytona.create()
          sandbox.git.clone(url, "/repo")
          await task()
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  func runWithFallback(ctx context.Context, repoID string, task func() error) error {
  	repo, err := client.FindOne(ctx, storage.FindOneOptions{ID: repoID})
  	if err != nil {
  		return err
  	}
  	url, err := repo.RemoteURL(ctx, storage.RemoteURLOptions{
  		Permissions: []storage.Permission{storage.PermissionGitRead, storage.PermissionGitWrite},
  		TTL:         time.Hour,
  	})
  	if err != nil {
  		return err
  	}

  	// Try primary provider...
  	if err := task(); err != nil {
  		// Fallback to secondary provider using the same URL.
  		return task()
  	}
  	return nil
  }
  ```
</CodeGroup>

Your code stays safe in Code Storage regardless of which sandbox runs it.

## Security considerations

* **Short TTLs**: Use the shortest TTL practical for your use case. Sandbox sessions are typically short-lived.
* **Minimal permissions**: Grant `git:read` only unless the sandbox needs to push changes.
* **Ephemeral branches**: Isolate experimental or untrusted code in the ephemeral namespace.
* **Audit commits**: When sandboxes push code, review changes before merging to protected branches.
