---
title: "Local or cloud"
description: "Choose where CLI and SDK operations run"
icon: "cloud-arrow-up"
---

microsandbox exposes one CLI and SDK surface across the local runtime and [microsandbox cloud](/cloud/overview). Local is the default; cloud requires explicit intent and a usable credential.

Use the simplest selector that matches who owns the decision:

| Selector | Best for |
| --- | --- |
| `MSB_BACKEND` | One command, a shell, CI, or deployment configuration |
| SDK | Applications that must choose independently of their environment |
| Named profile | Regular switching or shared environment defaults |

## Environment

The `MSB_BACKEND` environment variable selects a backend for a single command or shell, unless an administrator has set a managed active profile:

<CodeGroup>
```bash Shell
MSB_BACKEND=local msb run python -- python -V
MSB_BACKEND=cloud MSB_API_KEY="msb_..." msb ls
```
</CodeGroup>

Cloud selection and credentials are separate. `MSB_API_KEY` does not select cloud by itself. `MSB_API_URL` only overrides the cloud endpoint and does not select cloud either.

## SDK

Programmatic selection wins over environment and profile resolution. Use it when the application should decide regardless of where it is launched:

<CodeGroup>
```typescript TypeScript
import { setDefaultBackend } from "microsandbox";

setDefaultBackend({ kind: "cloud", apiKey: process.env.MSB_API_KEY! });

// Or force the local runtime.
setDefaultBackend("local");
```

```rust Rust
use microsandbox::{set_default_backend, CloudBackend, LocalBackend};

// Reads MSB_API_KEY.
set_default_backend(CloudBackend::from_env()?);

// Or pass the key explicitly.
set_default_backend(CloudBackend::with_api_key(api_key)?);

// Or force the local runtime.
set_default_backend(LocalBackend::lazy()?);
```

```python Python
import os
from microsandbox import set_default_backend

set_default_backend("cloud", api_key=os.environ["MSB_API_KEY"])

# Or force the local runtime.
set_default_backend("local")
```

```ruby Ruby
require "microsandbox"

Microsandbox.use_cloud_backend!(ENV.fetch("MSB_API_KEY"))

# Or force the local runtime.
Microsandbox.use_local_backend!
```
</CodeGroup>

Go selects its backend through the [environment](#environment) or [profiles](#profiles); it does not expose a programmatic selector. For an explicit configuration file in Rust, see [backend configuration](/sdk/rust/configuration#config_path).

Local and cloud backends read user and managed configuration during construction. Invalid files cause an error even when cloud credentials are supplied explicitly. Existing backends retain their settings; construct a new backend to load file changes.

## Profiles

Profiles are named backend configurations in `~/.microsandbox/config.json`. Use them when you switch regularly or want a shared default for an environment:

<CodeGroup>
```json JSON
{
  "active_profile": "production",
  "profiles": {
    "production": {
      "backend": "cloud",
      "api_key_ref": "env:MSB_API_KEY"
    },
    "local": {
      "backend": "local"
    }
  }
}
```
</CodeGroup>

`active_profile` sets the default. `MSB_PROFILE=<name>` selects another profile for one command:

<CodeGroup>
```bash Shell
MSB_PROFILE=production msb run python -- python -V
```
</CodeGroup>

Cloud profiles require `api_key_ref`. The optional `url` field defaults to `https://api.microsandbox.dev`; set it only for a development, self-hosted, or on-premises control plane. See the [profiles schema](/configuration#profiles) for every field and credential-reference format.

## Precedence

Backend resolution uses this order:

1. Programmatic backend set by the SDK
2. Managed `active_profile`, if supplied
3. `MSB_BACKEND=local|cloud`
4. `MSB_PROFILE=<name>`
5. User `active_profile`
6. Local runtime

A managed `active_profile` set to `null` or an empty string clears saved and environment-selected profiles while preserving `MSB_BACKEND`. With no explicit backend, it uses the local fallback. To enforce local execution over `MSB_BACKEND`, select a named managed profile with `backend: local`. Managed profile entries replace same-named user entries. See [Managed deployment](/enterprise/managed-configuration) for deployment and file format. An explicitly constructed SDK backend keeps its identity. Both local and cloud backends apply managed sandbox settings and host-side SSH policy.

Selecting a cloud profile with `MSB_PROFILE` or `active_profile` is explicit cloud intent when that profile has `"backend": "cloud"`. `MSB_BACKEND=cloud` without a usable API key or cloud profile returns a configuration error; it never falls back to local execution.

### Permit local, cloud, or both

Set `"allowed_backends": ["local"]`, `["cloud"]`, or `["local", "cloud"]` in user config or managed overrides. The default is both. An empty list is invalid; `null` removes the restriction. Managed values replace user values.

Permission is separate from selection. A cloud-only policy rejects local selection; it does not select cloud for you. Checks apply when standard SDK or CLI backends are constructed, including explicitly supplied backends. Existing backend instances keep their captured settings.

Use `msb context list` to inspect profiles without loading credentials, `msb context use <name>` to save a preference, and `msb context reset` to remove it. See [context commands](/cli/management#msb-context) for precedence and recovery.

## Verify

Use `msb context` to inspect the backend kind, selection source, profile, and cloud API URL without exposing the API key:

<CodeGroup>
```bash Shell
msb context
msb context --format json
```
</CodeGroup>

Use the SDK accessors to inspect the active backend without exposing its API key. Detailed backend info includes the kind, cloud API URL, selection source, and profile when applicable:

<CodeGroup>
```typescript TypeScript
import { defaultBackendInfo } from "microsandbox";

console.log(defaultBackendInfo());
console.log(sandbox.backendKind);
```

```rust Rust
let info = microsandbox::default_backend_info()?;
println!("{}", info.kind.as_str());
println!("{}", sandbox.backend_kind().as_str());
```

```python Python
from microsandbox import default_backend_info

print(default_backend_info())
print(sandbox.backend_kind)
```

```go Go
info, err := microsandbox.DefaultBackendInfo()
if err != nil {
    return err
}
fmt.Println(info.Kind)
fmt.Println(sandbox.BackendKind())
```

```ruby Ruby
require "microsandbox"

puts Microsandbox.default_backend_kind
puts sandbox.backend
```
</CodeGroup>

Backend diagnostics return configuration errors when selection fails or policy prohibits the selected backend. Successful output keeps the same fields.

For global defaults and profile storage, see [Configuration](/operations/configuration). For backend feature differences, see [Cloud compatibility](/cloud/overview#compatibility).
