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

# Autosleep

> Automatically sleep idle Sailboxes and wake them on demand

Autosleep is on by default. Sail watches each Sailbox and, once it has been
truly idle for a while, puts it to sleep. The next request or command wakes it.
You are not charged while a Sailbox sleeps.

Waking takes a few seconds, so the first request or command after a sleep is
slower than usual.

## When a Sailbox sleeps

Sail uses heuristics to tell when a Sailbox is truly idle, meaning nothing
running inside it would notice a sleep. A Sailbox doing work, or holding open
connections, stays awake.

Once a Sailbox is idle, Sail waits a minimum time before sleeping it. The wait
is 30 seconds by default, and you can change it per Sailbox.

## What survives

Sleeping checkpoints the whole machine. Disk, memory, and running processes
come back exactly as they were.

## What wakes it

* A request to one of its exposed ports, HTTP or raw TCP. The connection is
  held while the Sailbox wakes, then forwarded.
* A command: `sail box exec`, `sail box shell`, a file transfer, or an SSH
  connection. Running a command on a sleeping Sailbox wakes it in every SDK.
* A wall-clock alarm a process inside set, such as a job scheduled for 9:00.
* An explicit resume, a scheduled wake, or a
  [cron job](#run-a-command-on-a-schedule) that is due.

## Configure it

Set the minimum idle time to a number of seconds from 1 through 3600. `never`
keeps the Sailbox running until you sleep, pause, or terminate it yourself.
`auto` restores the default. You can change the setting at any time, and it
has no effect on your own `sleep`, `pause`, `resume`, and scheduled wakes.

<div className="sail-prompt-cli">
  <CodeGroup>
    ```bash CLI theme={null}
    sail box create --app my-app --name session --auto-sleep never
    sail box auto-sleep <id> 600
    ```

    ```python Python theme={null}
    sb = sail.Sailbox.create(app=app, name="session", auto_sleep=sail.AutoSleep.never())
    sb.set_auto_sleep(sail.AutoSleep.not_before(600))
    ```

    ```typescript TypeScript theme={null}
    const sb = await Sailbox.create({
      app,
      name: "session",
      autoSleep: { automatic: false },
    });
    await sb.setAutoSleep({ automatic: true, minSecondsBeforeSleep: 600 });
    ```

    ```rust Rust theme={null}
    use sail::{AutoSleep, CreateSailboxRequest};
    use std::time::Duration;

    let sb = client
        .create_sailbox(
            &CreateSailboxRequest {
                app_id: app.id,
                name: "session".into(),
                auto_sleep: AutoSleep::Never,
                ..Default::default()
            },
        )
        .await?;
    sb.set_auto_sleep(AutoSleep::NotBefore(Duration::from_secs(600))).await?;
    ```
  </CodeGroup>
</div>

## Sleep it yourself

`sleep` checkpoints the Sailbox and powers it down right away. It wakes on the
same triggers as an automatic sleep. `pause` does the same but ignores traffic
and commands: only an explicit `resume` brings it back.

<div className="sail-prompt-cli">
  <CodeGroup>
    ```bash CLI theme={null}
    sail box sleep <id>
    sail box pause <id>
    sail box resume <id>
    ```

    ```python Python theme={null}
    sb.sleep()
    sb.pause()
    sb.resume()
    ```

    ```typescript TypeScript theme={null}
    await sb.sleep();
    await sb.pause();
    await sb.resume();
    ```

    ```rust Rust theme={null}
    sb.sleep(/* wake_at */ None).await?;
    sb.pause().await?;
    sb.resume().await?;
    ```
  </CodeGroup>
</div>

## Wake at a time

Give `sleep` a wake time and Sail restores the Sailbox when it arrives. Use it
for agents and services that sleep between runs and need to be up at a known
moment, such as a daily job or a follow-up an agent scheduled for itself.

<div className="sail-prompt-cli">
  <CodeGroup>
    ```bash CLI theme={null}
    sail box sleep <id> --wake-at 2h
    ```

    ```python Python theme={null}
    from datetime import datetime, timedelta, timezone

    sb.sleep(wake_at=datetime.now(timezone.utc) + timedelta(hours=2))
    ```

    ```typescript TypeScript theme={null}
    await sb.sleep(new Date(Date.now() + 2 * 60 * 60 * 1000));
    ```

    ```rust Rust theme={null}
    use sail::time::{Duration, OffsetDateTime};

    sb.sleep(Some(OffsetDateTime::now_utc() + Duration::hours(2))).await?;
    ```
  </CodeGroup>
</div>

A Sailbox has one scheduled wake at a time. A request for an earlier time
replaces it, and a request for a later time leaves the sooner wake in place.
The call returns the wake that remains scheduled.
Calling `sleep` with a time on a Sailbox that is already asleep just updates
the wake. The CLI takes a delay like `30m` or `2h`, or an RFC 3339 timestamp.
The wake can be a little late, so give it a minute or two of headroom.
A paused Sailbox rejects a scheduled wake. Only `resume` brings it back.

## Run a command on a schedule

A cron job runs a shell command in a Sailbox on a schedule. If the Sailbox is
asleep when a run is due, Sail wakes it and starts the command. Autosleep then
puts the Sailbox back to sleep once it is idle.

<div className="sail-prompt-cli">
  <CodeGroup>
    ```bash CLI theme={null}
    sail box cron add <id> "0 9 * * 1-5" "python /app/report.py" --timezone America/New_York
    sail box cron list <id>
    sail box cron remove <id> <cron-job-id>
    ```

    ```python Python theme={null}
    job = sb.cron.add(
        "0 9 * * 1-5",
        "python /app/report.py",
        timezone="America/New_York",
    )
    sb.cron.list()
    job.remove()
    ```

    ```typescript TypeScript theme={null}
    const job = await sb.cron.add("0 9 * * 1-5", "python /app/report.py", {
      timezone: "America/New_York",
    });
    await sb.cron.list();
    await job.remove();
    ```

    ```rust Rust theme={null}
    use sail::CronOptions;

    let job = sb
        .cron()
        .add(
            "0 9 * * 1-5",
            "python /app/report.py",
            CronOptions {
                timezone: Some("America/New_York".into()),
                ..Default::default()
            },
        )
        .await?;
    sb.cron().list().await?;
    sb.cron().remove(&job.id).await?;
    ```
  </CodeGroup>
</div>

The schedule is a cron expression with five fields: minute, hour, day of
month, month, and day of week. The one above runs at 9:00 on weekdays. Times
are UTC unless you name a time zone.

The command runs the way an `exec` command does. See the
[`cron` namespace](/sailbox-sdk#cron) for its options.

* **A run can start a little late**, more so when the Sailbox has to wake
  first.
* **Output is not kept.** Have the command write what you need to a file, for
  example `python /app/report.py >> /var/log/report.log 2>&1`.
* **A run that cannot start is skipped**, and is not made up later. That
  happens when the Sailbox is paused or fails to wake.
* **Runs do not wait for each other.** A run still going when the next is due
  does not delay it.
* **Jobs belong to one Sailbox**, which holds up to 50. They are removed when
  it is terminated, and a fork or a Sailbox created from a checkpoint starts
  with none.
