> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-appcypher-sdk-runtime-bootstrap.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Lifecycle

> Create, start, stop, and manage sandbox state

Each sandbox runs as a child process of whatever application creates it. `Sandbox.builder(...).create()` boots a microVM, starts the guest agent inside it, and establishes a communication channel back to the host.

Understanding the lifecycle is useful once you start managing long-running sandboxes, graceful shutdown, or resilient agent workflows.

```mermaid theme={null}
stateDiagram-v2
    [*] --> Creating: create()
    Creating --> Running: boot complete
    Running --> Draining: request_drain()
    Running --> Stopped: stop()
    Running --> Crashed: unexpected exit
    Draining --> Stopped: drain complete
    Stopped --> Running: start()
    Stopped --> [*]: remove()
    Crashed --> [*]: remove()
```

## States

| Status       | Description                                                                                                                                                |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Creating** | The VM is booting. The kernel is loaded, the filesystem is mounted, and the guest agent is initializing (configuring network, setting up the environment). |
| **Running**  | The guest agent is ready. You can call `exec`, `shell`, and `fs`.                                                                                          |
| **Draining** | Graceful shutdown in progress. Existing commands run to completion, but new `exec` calls are rejected. Transitions to Stopped when all commands finish.    |
| **Stopped**  | The VM has shut down. Sandbox configuration and state are persisted to the database and can be restarted.                                                  |
| **Crashed**  | The VM exited unexpectedly (e.g., kernel panic, OOM kill).                                                                                                 |

## Create a sandbox

<Tooltip tip="Local attached SDK handles stop their sandbox when the client process exits. Cloud sandboxes are service-owned, so stop or remove them explicitly."><span className="msb-badge-limited">Limited on cloud <Icon icon="circle-info" size={11} /></span></Tooltip>

Creating a sandbox boots the microVM, mounts the filesystem, initializes the guest agent, and waits until it's ready to accept commands. Names must be non-empty and no longer than 128 UTF-8 bytes.

<CodeGroup>
  ```rust Rust theme={null}
  // Local attached handle: sandbox stops when your process exits
  let sb = Sandbox::builder("worker").image("python").create().await?;

  // Detached: sandbox survives after your process exits
  let sb = Sandbox::builder("worker")
      .image("python")
      .detached(true)
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  // Local attached handle: sandbox stops when your process exits
  await using sb = await Sandbox.builder("worker").image("python").create();

  // Detached: sandbox survives after your process exits
  const detached = await Sandbox.builder("worker")
    .image("python")
    .detached(true)
    .create();
  ```

  ```python Python theme={null}
  # Local attached handle: sandbox stops when your process exits
  sb = await Sandbox.create("worker", image="python")

  # Detached: sandbox survives after your process exits
  sb = await Sandbox.create("worker", image="python", detached=True)
  await sb.detach()
  ```

  ```go Go theme={null}
  // Local attached handle: sandbox stops when your process exits
  sb, err := m.CreateSandbox(ctx, "worker", m.WithImage("python"))

  // Detached: sandbox survives after your process exits
  detached, err := m.CreateSandbox(ctx, "worker",
      m.WithImage("python"),
      m.WithDetached(),
  )
  ```

  ```bash CLI theme={null}
  # Attached
  msb create python --name worker

  # Detached
  msb run -d python --name worker
  ```
</CodeGroup>

## Stop and restart

Stopping gracefully terminates guest processes and shuts down the VM. The sandbox moves to `Stopped` and can be restarted later with all its configuration preserved.

<CodeGroup>
  ```rust Rust theme={null}
  sb.stop().await?;

  let sb = Sandbox::start("worker").await?;
  ```

  ```typescript TypeScript theme={null}
  await sb.stop()

  // Later, resume where you left off
  const sb = await Sandbox.start("worker")
  ```

  ```python Python theme={null}
  await sb.stop()

  # Later, resume where you left off
  sb = await Sandbox.start("worker")
  ```

  ```go Go theme={null}
  _ = sb.Stop(ctx)

  // Later, resume where you left off
  sb, err := m.StartSandbox(ctx, "worker")
  ```

  ```bash CLI theme={null}
  msb stop worker

  # Later, resume where you left off
  msb start worker

  # Or stop and start in one command
  msb restart worker
  ```
</CodeGroup>

`msb restart` follows the same lifecycle semantics as `msb stop` followed by `msb start`. If the sandbox is already stopped or crashed, it starts it directly.

## Configuration

Use `msb modify`, or the SDK `modify()` methods, to change an existing sandbox without recreating it. Some changes apply live, some affect future execs only, and some need a restart or the next start.

<CodeGroup>
  ```rust Rust theme={null}
  let plan = sb.modify()
      .cpus(4)
      .memory(4096)
      .apply()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  const plan = await sandbox.modify({ cpus: 4, memory: 4096 });
  ```

  ```python Python theme={null}
  plan = await sb.modify(cpus=4, memory=4096)
  ```

  ```go Go theme={null}
  plan, err := sb.Modify(ctx, m.ModifyOptions{CPUs: 4, MemoryMiB: 4096})
  ```

  ```bash CLI theme={null}
  msb modify api --cpus 4 --memory 4G
  ```
</CodeGroup>

See [Tuning](/sandboxes/tuning) for the change model, CPU and memory resize, labels, environment variables, secrets, and storage sizing.

## Ping and touch

<Tooltip tip="Not yet available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

Use `ping` to check that a running sandbox's guest agent is reachable, and `touch` to intentionally refresh its idle timer. Ping is a health check only: it does not count as sandbox activity and will not keep an idle sandbox alive by itself. Touch is the explicit keepalive.

<CodeGroup>
  ```rust Rust theme={null}
  let ping = sb.ping().await?;
  println!("agent reachable in {:?}", ping.latency);

  sb.touch().await?;
  ```

  ```bash CLI theme={null}
  msb ping worker
  msb touch worker

  # Health check and then keep alive if reachable
  msb ping worker --touch
  ```
</CodeGroup>

## Kill immediately

<Tooltip tip="Not yet available on microsandbox cloud; use a graceful stop instead."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

If a sandbox is unresponsive (e.g., stuck in a tight loop or a panic), force-kill it. The sandbox is terminated immediately with no graceful shutdown.

<CodeGroup>
  ```rust Rust theme={null}
  sb.kill().await?;
  ```

  ```typescript TypeScript theme={null}
  await sb.kill()
  ```

  ```python Python theme={null}
  await sb.kill()
  ```

  ```go Go theme={null}
  err := sb.Kill(ctx)
  ```

  ```bash CLI theme={null}
  msb stop --force worker
  ```
</CodeGroup>

## Detach

Keeps a sandbox running after the parent process exits. It becomes a background process that you can reconnect to later with `Sandbox::get("worker")`.

<CodeGroup>
  ```rust Rust theme={null}
  sb.detach().await;
  ```

  ```typescript TypeScript theme={null}
  await sb.detach()
  ```

  ```python Python theme={null}
  await sb.detach()
  ```

  ```go Go theme={null}
  err := sb.Detach(ctx)
  ```
</CodeGroup>

## Request drain

<Tooltip tip="Not yet available on microsandbox cloud; use a graceful stop instead."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

Trigger a graceful shutdown that lets existing commands finish but rejects new ones. The sandbox moves to `Draining` and transitions to `Stopped` when all in-flight commands complete. This is useful for zero-downtime rotation of worker sandboxes.

<CodeGroup>
  ```rust Rust theme={null}
  sb.request_drain().await?;
  ```

  ```typescript TypeScript theme={null}
  await sb.requestDrain()
  ```

  ```python Python theme={null}
  await sb.request_drain()
  ```

  ```go Go theme={null}
  err := sb.RequestDrain(ctx)
  ```
</CodeGroup>

## Wait until stopped

Block until the sandbox is observed in a terminal non-running state, without triggering a stop or kill request.

<CodeGroup>
  ```rust Rust theme={null}
  let result = sb.wait_until_stopped().await?;
  ```

  ```typescript TypeScript theme={null}
  const result = await sb.waitUntilStopped()
  ```

  ```python Python theme={null}
  result = await sb.wait_until_stopped()
  ```

  ```go Go theme={null}
  result, err := sb.WaitUntilStopped(ctx)
  ```
</CodeGroup>

## Remove

Delete a stopped sandbox. Every local SDK entry point and `msb rm` uses the same deletion scope.

<CodeGroup>
  ```rust Rust theme={null}
  Sandbox::remove("worker").await?;
  ```

  ```typescript TypeScript theme={null}
  await Sandbox.remove("worker")
  ```

  ```python Python theme={null}
  await Sandbox.remove("worker")
  ```

  ```go Go theme={null}
  err := m.RemoveSandbox(ctx, "worker")
  ```

  ```bash CLI theme={null}
  msb rm worker
  ```
</CodeGroup>

For a local sandbox, removal deletes sandbox-owned state while leaving independently managed resources intact:

| Removed                                                                        | Kept                                   |
| ------------------------------------------------------------------------------ | -------------------------------------- |
| Sandbox record, configuration, status, labels, and run history                 | Cached OCI images and layers           |
| Managed OCI writable root disk (`upper.ext4`) and its guest filesystem changes | Named volumes and their contents       |
| Captured sandbox logs                                                          | Snapshots created from the sandbox     |
| Runtime staging files, including generated scripts                             | Bind-mounted host files or directories |
| Root filesystem pin metadata for this sandbox                                  | User-supplied root disk images         |

Removing a sandbox does not undo writes made to a named volume, bind mount, or user-supplied disk image. On cloud, removal deletes the remote sandbox resource; the local disk details above do not apply.

## List and inspect

<CodeGroup>
  ```rust Rust theme={null}
  for handle in Sandbox::list().await?.sandboxes {
      println!("{}: {:?}", handle.name(), handle.status_snapshot());
  }
  ```

  ```typescript TypeScript theme={null}
  const page = await Sandbox.list();
  for (const handle of page.sandboxes) {
      console.log(`${handle.name}: ${handle.status}`);
  }

  const handle = await Sandbox.get("worker");
  console.log(handle.status); // "running" | "stopped" | ...
  ```

  ```python Python theme={null}
  for handle in (await Sandbox.list()).sandboxes:
      print(f"{handle.name}: {handle.status}")

  handle = await Sandbox.get("worker")
  print(handle.status)  # "running" | "stopped" | ...
  ```

  ```go Go theme={null}
  page, err := m.ListSandboxes(ctx)
  for _, handle := range page.Sandboxes {
      fmt.Printf("%s: %s\n", handle.Name(), handle.Status())
  }

  handle, err := m.GetSandbox(ctx, "worker")
  fmt.Println(handle.Status()) // "running" | "stopped" | ...
  ```

  ```bash CLI theme={null}
  msb ls
  msb ps worker
  ```
</CodeGroup>

## Runtime process architecture

At runtime, your application talks to a host-side sandbox process, and that process relays requests to the guest agent inside the VM.

```mermaid theme={null}
graph TD
    subgraph Host["Host"]
        A["Your Application<br/><small>microsandbox SDK</small>"]
        B["Sandbox Process<br/><small>VM + networking + lifecycle</small>"]
    end

    subgraph Guest["Guest VM"]
        F["agentd<br/><small>exec, fs</small>"]
    end

    A -- "spawn" --> B
    B -- "boot" --> F
    A -. "commands & responses" .-> F

    style Host fill:#f5f0ff,stroke:#a770ef,color:#333
    style Guest fill:#fef4e8,stroke:#e8a838,color:#333
    style A fill:#d4bfff,stroke:#8b5cf6,color:#1a1a1a
    style B fill:#d4bfff,stroke:#8b5cf6,color:#1a1a1a
    style F fill:#fdd49e,stroke:#d97706,color:#1a1a1a
```

The sandbox process also handles:

* Graceful stop and drain signals
* Cleanup when the sandbox exits
* Idle detection and maximum lifetime enforcement

## Logs and diagnostics

Use [`msb logs`](/cli/sandbox-commands#msb-logs) or the SDK `logs()` method to read captured output from running, stopped, or crashed sandboxes. For source semantics, boot errors, and diagnostic flows, see [Logs](/sandboxes/logs).

## Sandbox process policies

For production workloads, configure how the sandbox process handles shutdown, idle detection, and maximum lifetime.

<CodeGroup>
  ```rust Rust theme={null}
  let sb = Sandbox::builder("worker")
      .image("python")
      .max_duration(3600)
      .idle_timeout(300)
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  await using sb = await Sandbox.builder("worker")
      .image("python")
      .maxDuration(3600)   // maximum sandbox lifetime in seconds
      .idleTimeout(300)    // auto-drain after 5 minutes of inactivity
      .create();
  ```

  ```python Python theme={null}
  sb = await Sandbox.create(
      "worker",
      image="python",
      max_duration=3600,
      idle_timeout=300,
  )
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "worker",
      m.WithImage("python"),
      m.WithMaxDuration(time.Hour),
      m.WithIdleTimeout(5*time.Minute),
  )
  ```
</CodeGroup>
