Skip to main content
Freestyle provides performant ephemeral VMs that are full linux systems. Freestyle is ideal when you want to give your AI a whole computer, not just run code snippets. This guide shows the full end-to-end flow: use the Mesa SDK outside the sandbox to set up resources, then use the Freestyle SDK to configure and mount Mesa inside the sandbox. The general flow for any sandbox integration is:
  1. Outside the sandbox — use the Mesa SDK (TypeScript or Python) to create repos, manage API keys, and orchestrate your workflow.
  2. Inside the sandbox — install the mesa CLI, configure it with your API key, and run mesa mount --daemonize to mount your repos as local directories.
  3. Run your agentcd into the mount path and launch your agent (e.g. Claude Code, Codex, or a custom agent). Any file edits are automatically persisted back to Mesa.
For details on FUSE setup, system dependencies, and container configuration, see OS-level Virtualization.

Setup

The example uses three environment variables:
MESA_ORG=your-org
MESA_API_KEY=your-mesa-api-key
FREESTYLE_API_KEY=your-freestyle-api-key

Example Code

Freestyle sandboxes are Debian-based by default, so the standard Mesa install script works out of the box.
import { Sandbox } from "e2b";
import { Mesa } from "@mesadev/sdk";

const mesa = new Mesa({ apiKey: process.env.MESA_API_KEY });
const freestyle = new Freestyle({ apiKey: process.env.FREESTYLE_API_KEY });

// --- Outside the sandbox: set up Mesa resources ---

// Create a repo (or use an existing one)
const repo = await mesa.repos.create({ name: "agent-workspace" });

// Create a scoped, short-lived API key for the sandbox
const ephemeralKey = await mesa.apiKeys.create({
  name: "sandbox-session",
  scopes: ["read", "write"],
  expires_in_seconds: 3600, // 1 hour
  // Optional: scope the key to a specific repo for better security
  // repo_ids: [repoId1, repoId2, ...],
});

// --- Inside the sandbox: install and mount Mesa ---

const { vm } = await freestyle.vms.create();

// Set up Mesa within the Freestyle sandbox.
//
// We recommend installing Mesa as part of the container definition (e.g. Docker image),
// but here we install it directly to keep the example small.

// You can install Mesa as per the guide in https://docs.mesa.dev/content/virtual-filesystem/os-level.
//
// Mesa's installer will install all its dependencies through your system's package manager.
await vm.exec('curl -fsSL https://mesa.dev/install.sh | sh');

// It is critical that you enable the user_allow_other flag in your fuse configuration.
//
// This allows users outside of yourself to also access the mesa mount you mounted. Mesa requires this for
// operation. See https://www.man7.org/linux/man-pages/man8/mount.fuse3.8.html for more details.
await vm.exec(
  [
    "sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf",
    // Some sandbox images expose /dev/fuse as root-only by default.
    'chmod 666 /dev/fuse',
  ].join(' && ')
);

// You can run mesa in daemon mode to kick it off in the background.
//
// The flags we are using here are:
//   -d, --daemonize        Spawns mesa in the background
//   -y, --non-interactive  Tells mesa to use the default values for all its configuration values. It will create a
//                          new config file for you.
//
// We also pass the environment variable:
//   MESA_ORGS=<org>:<api-key>,... Tells mesa to configure the given organization with the given API key.
//                                 Mesa will store this information in its configuration file. See
//                                 https://docs.mesa.dev/content/reference/mesa-cli-configuration for more details.
//
// Note that mesa will write the orgs to the config file the first time it is booted up, so you do not need to
// specify it again. When mesa is already configured, it will append the orgs given through the environment to the
// ones in the config.toml.
//
// Additionally, we recommend creating and specifying an ephemeral key which persists for the lifetime of the sandbox,
// rather than using the main API key. In the spirit of keeping this example small, we use the main API key. See
// https://docs.mesa.dev/content/getting-started/auth-and-permissions for more details.
await vm.exec(`MESA_ORGS=${ORG}:${MESA_API_KEY} mesa mount -d -y`);


// --- Run your agent ---

await vm.exec(
  'cd ~/.local/share/mesa/mnt/my-org/agent-workspace \
    && claude "Implement the feature described in TODO.md"'
);

Tips

  • Prefer short-lived scoped keys in production. The example uses MESA_API_KEY directly to stay small, but production flows should mint an ephemeral key outside the VM and pass that into MESA_ORGS. See Auth and Permissions for details.
  • Install Mesa ahead of time when startup time matters. Installing at runtime is fine for a demo, but preinstalling Mesa and its dependencies makes VM startup faster and more predictable.
  • Always use --daemonize. This keeps Mesa mounted while your shell or agent continues to run.
  • Don’t forget user_allow_other. See OS-level Virtualization for the most common FUSE setup issue in sandbox environments.
  • Expect mount paths to depend on the VM user. In this example the VM runs as root, so Mesa mounts under /root/.local/share/mesa/mnt.