Skip to main content

Overview

This example creates a Daytona sandbox with Claude Code pre-installed using the declarative image builder, and uses Oshu Vault to securely inject your Anthropic API key.

Prerequisites

  • Daytona account and DAYTONA_KEY set
  • Oshu Vault instance running
  • SECRETS_PROXY_API_KEY — your proxy management API key
  • ANTHROPIC_API_KEY — your real Anthropic key

Install Dependencies

npm install @daytonaio/sdk @oshu/vault-sdk

Full Example

import { Daytona, Image } from "@daytonaio/sdk";
import { SecretsProxyClient } from "@oshu/vault-sdk";

// --- Config ---
const PROXY_BASE_URL = "https://pv.oshu.dev";
const PROXY_HOST = "pv.oshu.dev";
const API_KEY = process.env.SECRETS_PROXY_API_KEY!;
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY!;

// 1. Create a Oshu Vault session
const client = new SecretsProxyClient({
  baseUrl: PROXY_BASE_URL,
  apiKey: API_KEY,
});

const session = await client.createSession({
  secrets: { ANTHROPIC_API_KEY },
});

const proxyUrl = `https://${session.session_id}:${session.token}@${PROXY_HOST}`;

// 2. Build a sandbox image with Claude Code + trusted CA cert
const image = Image.base("node:22-slim").runCommands(
  "apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*",
  `curl -fsSL ${PROXY_BASE_URL}/v1/ca.pem -o /usr/local/share/ca-certificates/proxy-ca.crt && update-ca-certificates`,
  "npm install -g @anthropic-ai/claude-code",
);

// 3. Create sandbox with proxy env vars
const daytona = new Daytona({ apiKey: process.env.DAYTONA_KEY });

const sandbox = await daytona.create(
  {
    image,
    envVars: {
      ANTHROPIC_API_KEY: session.sealed_secrets["ANTHROPIC_API_KEY"],
      HTTP_PROXY: proxyUrl,
      HTTPS_PROXY: proxyUrl,
      NODE_EXTRA_CA_CERTS: "/etc/ssl/certs/ca-certificates.crt",
    },
  },
  { timeout: 0, onSnapshotCreateLogs: console.log },
);

try {
  // 4. Run claude -p — no special flags, just works
  const result = await sandbox.process.executeCommand(
    `claude -p "Write a hello world program in Python"`,
  );

  console.log(result.result);
} finally {
  await client.deleteSession(session.session_id);
  await daytona.delete(sandbox);
}

Declarative Image Builder

The key difference from E2B is Daytona’s declarative image builder. Instead of installing tools and uploading certificates at runtime, everything is baked into the image — including the proxy’s CA certificate:
const image = Image.base("node:22-slim").runCommands(
  "apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*",
  `curl -fsSL ${PROXY_BASE_URL}/v1/ca.pem -o /usr/local/share/ca-certificates/proxy-ca.crt && update-ca-certificates`,
  "npm install -g @anthropic-ai/claude-code",
);
The CA certificate is static per proxy instance, so it’s safe to bake into the image. update-ca-certificates adds it to the system trust store (used by curl, wget, etc.). Node.js ignores the system store, so you still need NODE_EXTRA_CA_CERTS in envVars — but it can point to the system bundle that already contains the cert. Daytona caches this image for 24 hours, so subsequent sandbox creations skip the build step entirely. You can also pre-build it as a named snapshot:
await daytona.snapshot.create(
  { name: "claude-code", image },
  { onLogs: console.log },
);

// Then use it later — instant startup
const sandbox = await daytona.create({
  snapshot: "claude-code",
  envVars: { /* ... */ },
});

What’s Happening

1

Session created

The SDK sends your real ANTHROPIC_API_KEY to the proxy and gets back a sealed token like SEALED_7f3a9b2c....
2

Image built with Claude Code + trusted CA

Daytona builds a Docker image from node:22-slim with curl, Claude Code, and the proxy CA certificate pre-installed. The cert is fetched from /v1/ca.pem and added to the system trust store via update-ca-certificates. This image is cached for reuse.
3

Sandbox configured

The sandbox receives ANTHROPIC_API_KEY=SEALED_7f3a9b2c... and the proxy env vars. Everything looks normal to code running inside.
4

Secret injected on-the-fly

When Claude Code calls the Anthropic API, the proxy intercepts the request and replaces SEALED_7f3a9b2c... with your real API key.
The sandbox never sees your real API key. The declarative image builder runs before any secrets are configured, so even the build process has no access to sensitive values.