> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boat.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Readiness and resume speed

> What ready means, what already works at ready, what comes a few seconds later (Docker, services, system files), and how to wait for each in a script.

A sandbox is **ready** when the API reports its state as `ready`, `idle` or `running`. From then on, commands, SSH and prompts work at once.

`boat new`, `boat fork` and `boat resume` return when the sandbox is ready and a first command works. In a script, you can run your next command right after them.

## Ready, in one table

| State (API) | CLI and dashboard show | Commands | Billed |
| - | - | - | - |
| `provisioning` | `provisioning` | Wait (see below) | No |
| `provisioned` | `starting` | Wait (see below) | Yes |
| `cloning` | `cloning` | Wait (see below) | Yes |
| `ready`, `idle`, `running` | same | **Run at once** | Yes |
| `archiving` | `stopping` | Refused | No |
| `archived` | `stopped` | Refused | No |
| `error` | `error` | Refused | No |

<Note>
  The CLI and the dashboard show `provisioned` as `starting`. At `provisioned`, the machine is up, but Boat still applies your environment, secrets and repositories.
</Note>

A command that you send while the sandbox starts does not fail. The API holds it for up to 60 seconds and runs it when the sandbox is ready. After 60 seconds, it answers `409 sandbox_starting`. Send it again.

A command sent to a stopped sandbox, or to one in `error`, fails with `409 sandbox_not_ready`. Resume the sandbox first.

## What works at ready

| Part | At `ready` |
| - | - |
| Commands, SSH, prompts | Work |
| Environment variables and secret files | Set |
| Files in `/home/user` | All visible. Content downloads in the background. A read of a file waits for that file only |
| Repositories of the environment | Cloned |
| Public URLs | Normally open. A port can answer a moment later |
| The IP address | New. It changes at every resume and fork |

## What comes a few seconds after ready

On a resume, a fork or a deploy from a named snapshot, Boat restores in the background. These parts come after `ready`:

| Part | When | How to wait for it |
| - | - | - |
| Your changes in `/usr`, `/etc`, `/opt`, `/var`, `/srv`, `/root` | A few seconds after `ready`. Until then, a program sees the files of the base image there | Wait for Docker or your service, below |
| Docker and your containers | After the system files. Containers that ran start again | `docker info` answers |
| Systemd services that you enabled | After the system files | `systemctl is-active <service>` |
| Repository setup scripts | They start at `ready`, at every start | Wait for what the script makes, for example a file or a port. Read [Setup scripts](/setup) |
| Per-sandbox setup script (`--setup-file`) | It starts after `ready`, one time | `setupStatus` in `boat info` is `done` or `failed` |
| The rest of the file content | In the background | `hydrated` is `true`, or the `sandbox.hydrated` webhook |

A new sandbox, made with `boat new` and no `--from`, restores nothing. Docker and services start with the machine.

Some users see the first outbound connection fail in the first second after `ready`. Retry a failed first connection.

## Wait in a script

The common case needs no wait. Run your command after `boat new` or `boat resume`:

```bash theme={null}
ID=$(boat new --json | jq -r 'select(.event == "ready") | .id')
boat exec "$ID" "cd my-repo && npm test"
```

Wait for Docker:

```bash theme={null}
boat exec "$ID" --timeout 120 "until docker info >/dev/null 2>&1; do sleep 1; done"
```

Wait for a systemd service:

```bash theme={null}
boat exec "$ID" --timeout 120 "until systemctl is-active --quiet my-app; do sleep 1; done"
```

Wait until every file is downloaded:

```bash theme={null}
until [ "$(boat info "$ID" --json | jq -r .sandbox.hydrated)" = "true" ]; do sleep 2; done
```

With the API, poll `GET /sandboxes/{sandboxId}` and read `sandbox.state` and `sandbox.hydrated`. Or subscribe to the `sandbox.ready` and `sandbox.hydrated` [webhooks](/webhooks).

Wait for a stop:

`boat stop` returns at `stopping`. Poll `boat info` until the state is `stopped`. Read [Wait for the stop in a script](/snapshots/stop#wait-for-the-stop-in-a-script).

## How fast a sandbox comes back

A resume, a fork or a deploy is ready in **a few seconds, whatever the size of the disk**. You see all your files at once. Boat downloads their content in the background.

| What | What happens |
| - | - |
| Every resume, fork and deploy | It runs on a new machine. Boat downloads your files again in the background, even if the sandbox had all its files before the stop. `hydrated` is `false` until the download ends. |
| During the download | `GET /v1/sandboxes/{id}` returns `hydration`: the step, `entriesDone` of `entriesTotal` (files, folders and links) and a `percent`. Use `hydrated` as the end signal, not `percent`. |
| A file that is not downloaded yet | When you open or read it, Boat gets that file first. Then you get the right bytes. |
| End of the download | `hydrated` becomes `true`, `hydratedAt` is set, and the `sandbox.hydrated` webhook fires. Docker volumes move to the local disk at this point. |
| Files of the base image | They are already on every machine. Boat downloads only the files that differ from the image. |
| Paths in `.boatignore` | Boat does not save them, so it does not download them. Read [Leave files out](/snapshots/whats-saved#leave-files-out-with-boatignore). |
| A resume during `stopping` | Boat takes back the same machine. Nothing is downloaded. |

A restore does not need space for a second copy of your disk. Boat removes each downloaded part when it has used it. The [restore limits of each machine](/machines) count the size of your files, not the smaller download size.

Permissions, owners, times and extended attributes come back with your files and folders. Two of them come back later:

* **Extended attributes of a file** come back when the content of that file arrives. Folders have theirs from the start.
* **Folder modification times** come back when the download ends. Each new file in a folder changes the time of that folder, so Boat sets the time last.

The time to a working app depends on what your app reads first. Large first reads, Docker images and services that start late add seconds. The next section makes the first start faster.

## Make the first start faster

When a sandbox starts from a snapshot, it records which files open first. It keeps this list in `~/.ascii/playbook.json`. At the next start, Boat downloads these files first. Your app then works before the rest of the disk arrives. `ready` does not wait for these files.

The list is a normal file. It goes into the snapshot, so forks and deploys get it too.

The list is recorded **only while a sandbox starts from a snapshot**. Do these steps in this order:

<Steps>
  <Step title="Start the sandbox from a snapshot">
    Resume a stopped sandbox, or deploy one from the named snapshot that you want to update. A new, empty sandbox has nothing to record.

    ```bash theme={null}
    boat resume bx_f7k2q9hd
    ```
  </Step>

  <Step title="Start your app at once">
    Run your normal start command at once, while files still download. Boat records each file that your app opens, in order. Boat does not record files that open after the download ends.

    ```bash theme={null}
    boat exec bx_f7k2q9hd --detach "cd my-repo && npm run dev"
    ```
  </Step>

  <Step title="Wait for the download to end, then save">
    Boat writes the list when the download ends. Save after that. If you save too early, the named snapshot does not have this run.

    ```bash theme={null}
    until [ "$(boat info bx_f7k2q9hd --json | jq -r .sandbox.hydrated)" = "true" ]; do sleep 2; done
    boat snapshot bx_f7k2q9hd web-stack
    ```
  </Step>
</Steps>

Each run adds to the list. It does not replace it. The newest run counts most. Each time you repeat these steps, the named snapshot starts a little faster. The list holds the first 5,000 paths.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.