# Spaces

> How moatbox spaces are sized, which states they move through, and how sleep, auto-stop, time limits, the trash and forks work.

A space is a Firecracker microVM with its own disk, where moatbox runs your coding agents. Each space belongs to a team, has a name (its "slug") and lives at `https://app.moatbox.dev/s/<space>`. This page covers the space's life: size, states, sleep and wake, auto-stop, time limits, deletion and forks. To create your first space, see the [Quickstart](https://docs.moatbox.dev/quickstart.md).

## Names

A space name is 3 to 32 characters of `a-z`, `0-9` and `-`, starting and ending with a letter or digit. Names are unique: a taken name returns `409 that slug is taken`.

## Sizes

The API counts size in **units**. Every size has a 50 GB disk.

| Units | vCPU | Memory | `moatbox new --size` |
|------:|-----:|-------:|----------------------|
| 1 | 2 | 2 GB | `small` |
| 2 | 4 | 8 GB | `medium` |
| 4 | 8 | 16 GB | `large` |
| 8 | 16 | 32 GB | `xlarge` |

Your plan sets the largest size you can pick. The dashboard marks bigger sizes as not on your plan, and the API refuses them with `409`.

### Change the size

Owners and admins change the size on the space's **Overview** page, under **Size**.

- **At next wake**: moatbox stores the new size and applies it the next time the space wakes. The Overview page shows it as "→ new size at next wake".
- **Now**: moatbox puts the space to sleep and wakes it at the new size. The disk stays; programs that were running stop.

A sleeping space takes the new size at its next wake. Over the API, send `PATCH /api/v1/spaces/<space>` with `{"units": 4, "apply": "now"}` or `"apply": "next_wake"`.

## States

| State (API) | Dashboard label | Meaning |
|-------------|-----------------|---------|
| `provisioning` | Starting | moatbox is building the machine and refuses runs and SSH until it is up. |
| `active` | Awake | Running. Runs, SSH and file access work. |
| `sleeping` | Asleep | Suspended with disk kept, and memory unless the snapshot failed. |
| `waking` | Waking | Coming back from sleep. |
| `read_only` | Read-only | The team's plan is not active. You can read the timeline and files, but you cannot start runs or SSH in. |
| `suspended` | Paused by moatbox | An operator paused the space. It cannot wake until moatbox resumes it. The API returns the reason with `423`. |
| `deleted` | In the trash | Deleted and restorable until its purge time. |

The [events](https://docs.moatbox.dev/events-and-webhooks.md) `space.ready`, `space.sleeping`, `space.stopped`, `space.deleted` and `space.restored` report these changes.

## Sleep and wake

A sleeping space keeps its memory and disk, so a wake picks up where it stopped. If moatbox cannot snapshot the memory at sleep or restore it at wake, the space boots from its disk and programs that were running stop. Its address, SSH host key and IP stay the same across sleep, wake and resize.

You put a space to sleep with **Sleep** on its Overview page, from the row menu on the **Spaces** page, or with `POST /api/v1/spaces/<space>/sleep`. Sleeping a space closes its open SSH sessions.

These actions wake a sleeping space:

- opening the space in the dashboard, or `GET /api/v1/spaces/<space>` without `?peek=1`
- pressing **Wake**, or `POST /api/v1/spaces/<space>/wake` (add `?wait=1` to block until it is up)
- starting a run, sending a run a message, or running a command
- deciding an approval
- reading or copying files through the API or `moatbox cp`
- testing an integration, or clearing the command history
- connecting over SSH
- joining or leaving a Tailscale tailnet
- an HTTP request to an app the space hosts, when the space has `public_wake` on

A request that wakes the space as a side effect, such as starting a run, deciding an approval, copying a file or a Tailscale change, gets `503` with `Retry-After: 15` when the wake takes longer than 20 seconds, and moatbox keeps waking the space in the background. `POST /wake` without `?wait=1` answers `202` at once. A wake counts against the number of spaces your plan runs at once; at that limit the API refuses the wake with `409`.

## Auto-stop

Every space has an auto-stop rule, set on the **Overview** page under **Auto-stop** or in the create form. Owners and admins change it.

- **Sleep after idle for**: minutes with no work before the space sleeps. The default is 10 minutes. The dashboard offers 5 minutes to 8 hours; the API accepts `idle_minutes` from 1 to 1440.
- **And sleep after awake for, busy or not**: an optional hard limit on one awake stretch. The dashboard offers 1 hour to 7 days; the API accepts `max_awake_hours` from 1 to 720, and `0` removes the limit.
- **Always on**: idle time and the awake limit do not put the space to sleep while the team's plan is active. The space still sleeps when the team reaches its spend cap or its wallet runs out. Your plan sets how many always-on spaces the team may have. Turning it on wakes a sleeping space.

moatbox checks once a minute. These count as work and keep a space awake:

- a run that has not ended, unless it waits for input or for an approval
- an SSH session, file transfer or port forward moving data
- a file copy through the API or `moatbox cp`
- an HTTP request to an app the space hosts, when the space has `public_wake` on (set it with `PATCH /api/v1/spaces/<space>`)

The **Sleeps in** field on the Overview page counts down to the next sleep. It reads "never" for an always-on space.

## Recover a stuck space

moatbox power-cycles an awake space without **Always on** after 3 minutes with no answer: programs that were running stop and the disk stays. **Recover** on the Overview page does the same at once. moatbox allows one power-cycle per space every 10 minutes; an earlier request gets `409` with the minutes left.

## Time limit

A space can carry a time limit. Once the limit passes, moatbox moves the space to the trash.

```sh
curl -X PUT https://app.moatbox.dev/api/v1/spaces/my-space/expiry \
  -H "Authorization: Bearer mbx_…" \
  -H "Content-Type: application/json" \
  -d '{"seconds": 3600}'
```

`seconds` runs from 1 to 30 days (2592000); `0` clears the limit. Only owners and admins set it. An API key needs the `space.delete` action, or `space.delete-own` for a space that key created. `moatbox new --ttl 30m` sets the same limit when it creates a space; see [Connect to a space](https://docs.moatbox.dev/connect.md#cli-commands).

## Delete, trash and restore

Owners and admins delete a space with **Delete…** on its Overview page or from the **Spaces** page, and confirm by typing the space's name. Over the API, send `DELETE /api/v1/spaces/<space>` with the header `X-Moatbox-Confirm-Delete: <space>`.

Deleting stops the space and moves it to the **Trash** section of the Spaces page, with its disk and memory. You can restore it for 72 hours; after that moatbox erases it and frees the name. You cannot delete a space while it is starting or waking.

**Restore** in the Trash section brings the space back asleep. A space moatbox had paused comes back paused. Over the API: `POST /api/v1/teams/<team>/trash/<space>/restore`.

## Forks

A fork makes one or more copies of an awake space on the same server. moatbox snapshots the parent's memory and disk at that moment, so each copy starts from the parent's running state. Copies keep the parent's size, idle and awake limits, network allowlist, environment version and workspace mode. **Always on** starts off in a copy.

Owners and admins press **Fork** on the Overview page and name the copy; the default name is `<space>-copy`. Over the API, one call can make several copies:

```sh
curl -X POST https://app.moatbox.dev/api/v1/spaces/my-space/fork \
  -H "Authorization: Bearer mbx_…" \
  -H "Content-Type: application/json" \
  -d '{"slugs": ["my-space-a", "my-space-b"]}'
```

Each copy counts as a running space against your plan. If the parent's server has no room, the API answers `503` with `Retry-After: 300`.

## Where a space runs

By default a space runs on moatbox servers. If your team has linked its own server and that server is ready, the create form shows a **Where** field for a fresh space: a space placed there stays on that server and works only while the server is on.

## Who can do what

| Action | Who |
|--------|-----|
| Create, fork, delete, restore, resize, change auto-stop or always-on, set a time limit | Team owners and admins |
| Sleep, wake, recover, start runs | Any team member |

[API keys](https://docs.moatbox.dev/api-keys.md) carry their own permissions for each of these actions.
