# Sandboxes (/docs/concepts/sandboxes)



A sandbox is an isolated live execution environment. You create one from a
template, run commands and manage files inside it, and it's destroyed when
you kill it or its TTL expires. Sandboxes are the unit of isolation,
billing, and lifecycle in CrowNest.

## Lifecycle and statuses [#lifecycle-and-statuses]

Every sandbox moves through a fixed set of statuses. The `status` field on
the sandbox object always reflects the current state.

| Status      | Meaning                                            |
| ----------- | -------------------------------------------------- |
| `creating`  | CrowNest is provisioning the sandbox.              |
| `starting`  | The environment is booting.                        |
| `ready`     | The sandbox is available for work.                 |
| `running`   | Ready, with a command actively executing.          |
| `idle`      | Ready, with no active work.                        |
| `expiring`  | Cleanup has begun; new operations are rejected.    |
| `destroyed` | The sandbox is gone. The record remains queryable. |
| `failed`    | The sandbox could not start or stopped abnormally. |

`running` and `idle` are derived from `ready`: a sandbox is `running` while
it has an active command and `idle` otherwise.

Destroyed sandboxes carry a `destroyedReason`:

| `destroyedReason`  | Meaning                                           |
| ------------------ | ------------------------------------------------- |
| `user_killed`      | You deleted the sandbox via the API, SDK, or CLI. |
| `ttl_expired`      | The sandbox reached its `expiresAt` time.         |
| `idle_expired`     | The sandbox was reclaimed after sitting idle.     |
| `platform_cleanup` | CrowNest removed the sandbox during maintenance.  |

List endpoints return live sandboxes by default. Pass `include=historical`
to also get `destroyed` and `failed` records.

## TTL [#ttl]

Every sandbox has a time-to-live. You request it as `ttlMs` (milliseconds)
when creating the sandbox, and responses surface the resolved deadline as
`expiresAt` (ISO 8601). The API default is 3600000 ms (1 hour). Maximum TTL
varies by plan tier: 1 hour for Free, 24 hours for Builder, 72 hours for Scale,
and 168 hours for Enterprise. Requesting more returns `sandbox_ttl_exceeded`.
Read `quotas` from `GET /v1/usage` for current limits.

You can reset a live sandbox's remaining TTL with
`POST /v1/sandboxes/{sandboxId}/extend`, `client.sandboxes.extend(...)`,
`sandbox.extend(...)`, or `crownest sandboxes extend <sandbox-id> --ttl-ms <ms>`.
Each extend accepts up to 86400000 ms (24 hours), and the total session is
capped at 24 hours from creation.

When a sandbox expires:

* Running commands move to status `killed` with `killedReason`
  `sandbox_destroyed`.
* The filesystem is gone unless you exported files as artifacts first.
* The sandbox record remains with status `destroyed`.
* Billing stops at `expiresAt`.

<Callout type="warn" title="Important">
  Export anything you need to keep as an artifact before the sandbox expires. The
  workspace is not preserved.
</Callout>

## Templates [#templates]

A template is the user-facing slug that selects the sandbox environment.
Two curated templates are available:

| Template      | Contents                                                                |
| ------------- | ----------------------------------------------------------------------- |
| `python-node` | Python, Node.js, package managers, shell tools, and repo-runner basics. |
| `node`        | Node.js 22 with npm for JavaScript and TypeScript repositories.         |

`python-node` is also the default when you omit `template`. It includes
`bash`, `git`, `tar`, `gzip`, `curl`, `jq`, `rg`, `node`, `npm`, `corepack`,
`pnpm`, `python3`, `python3 -m pip`, and `uv`. `uv` is the recommended Python
package path, but pip-shaped repositories still work.

Additional curated templates and custom Dockerfile templates are planned.
Requesting a slug outside the discovered catalogue returns `invalid_request`.
Each template resolves to a TemplateVersion, an immutable resolved environment.
The sandbox stores the `templateVersionId` that was resolved at creation, so
the environment never changes underneath a running sandbox. You can also pass a
`templateVersionId` directly when creating a sandbox to pin a specific
version.

## Metadata [#metadata]

Metadata is a flat string map you set at creation to label sandboxes for
correlation, filtering, and display. It's never used for authorization, and
you must not store secrets in it.

Limits:

* Maximum 16 keys.
* Keys up to 64 characters; values up to 512 characters.
* Total size up to 4 KB.
* Allowed characters: `a-z A-Z 0-9 _ - . :`.

## Injected environment context [#injected-environment-context]

CrowNest injects a small set of non-secret environment variables into every
sandbox so processes can discover their own context:

| Variable                       | Value                            |
| ------------------------------ | -------------------------------- |
| `CROWNEST`                     | `1`                              |
| `CROWNEST_SANDBOX_ID`          | The sandbox ID.                  |
| `CROWNEST_PROJECT_ID`          | The project ID.                  |
| `CROWNEST_ORG_ID`              | The organization ID.             |
| `CROWNEST_TEMPLATE_ID`         | The template ID.                 |
| `CROWNEST_TEMPLATE_VERSION_ID` | The resolved TemplateVersion ID. |
| `CROWNEST_WORKSPACE`           | `/workspace`                     |

The `CROWNEST` prefix is reserved: setting any `CROWNEST*` key in command
`env` is rejected with `reserved_env_key`. Environment values you pass to
commands are ephemeral and never persisted.

## Next steps [#next-steps]

* [Commands](/docs/concepts/commands) — run processes inside a sandbox.
* [Files and the workspace](/docs/concepts/files) — read and write files
  under `/workspace`.
* [Artifacts](/docs/concepts/artifacts) — export files before the sandbox
  expires.
* [SDK quickstart](/docs/quickstart/sdk) — create your first sandbox.
* [Sandboxes API reference](/docs/api/sandboxes)
