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

# Long-Running Tasks

> Keep a Box running longer and restart processes after resume or fork.

Boxes have an auto-stop timer. The default is 1 hour. The timer counts from creation, not from your last activity: a box with a 1 hour TTL stops one hour after it started, even mid-work. Resuming a stopped box restarts the timer.

For work that should keep running until you stop it yourself, disable auto-stop when you create the Box or update an existing Box's TTL to `null`:

<CodeGroup>
  ```bash CLI theme={null}
  box new --no-auto-stop
  box extend bx_f7k2q9hd --no-auto-stop
  ```

  ```bash curl theme={null}
  curl -sS -X POST "$BOX_API_BASE/boxes" \
    -H "Authorization: Bearer $BOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"ttlSeconds":null}'

  curl -sS -X PATCH "$BOX_API_BASE/boxes/bx_f7k2q9hd" \
    -H "Authorization: Bearer $BOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"ttlSeconds":null}'
  ```

  ```ts TypeScript theme={null}
  const created = await box.create({ createBoxRequest: { ttlSeconds: null } });

  await box.update({
    boxId: "bx_f7k2q9hd",
    updateBoxRequest: { ttlSeconds: null },
  });
  ```

  ```python Python theme={null}
  created = box.create(CreateBoxRequest(ttl_seconds=None))

  box.update("bx_f7k2q9hd", UpdateBoxRequest(ttl_seconds=None))
  ```
</CodeGroup>

You can also set **No auto-stop** from the dashboard.

Use this for demos, browser sessions, long setup jobs, or unattended workflows where stopping the VM would interrupt work and force you to restart processes.

## Timed Extension

If you still want an auto-stop deadline, extend the Box instead:

<CodeGroup>
  ```bash CLI theme={null}
  box extend bx_f7k2q9hd --hours 12
  box extend bx_f7k2q9hd --ttl 2592000
  ```

  ```bash curl theme={null}
  curl -sS -X PATCH "$BOX_API_BASE/boxes/bx_f7k2q9hd" \
    -H "Authorization: Bearer $BOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"ttlSeconds":43200}'
  ```

  ```ts TypeScript theme={null}
  await box.update({
    boxId: "bx_f7k2q9hd",
    updateBoxRequest: { ttlSeconds: 12 * 60 * 60 },
  });
  ```

  ```python Python theme={null}
  box.update("bx_f7k2q9hd", UpdateBoxRequest(ttl_seconds=12 * 60 * 60))
  ```
</CodeGroup>

`2592000` seconds is 30 days. This is the maximum numeric TTL accepted by the Box API; larger values are capped to 30 days.

## Resume and Fork

`box stop` snapshots the filesystem. `box resume` restores that filesystem, and `box fork` creates a new Box from the latest snapshot. Resume takes a few seconds regardless of how much data the Box holds. See [Snapshots](/box/snapshots) for what is captured, restore behavior, retention, and how to inspect or download a snapshot.

Stop/resume behaves like a server reboot: **systemd services you enabled start again automatically**. Processes you ran by hand (dev servers, background jobs, tunnels, browser sessions) do not survive a reboot; restart them, or make them a systemd service so they come back on their own (see below).

## Run an Always-On Service

To make a process survive stop, resume, and fork without any action on your side, run it as an enabled systemd service. The unit file lives under `/etc`, which is snapshotted, so a resumed or forked box starts it automatically.

```bash theme={null}
sudo tee /etc/systemd/system/my-app.service >/dev/null <<'UNIT'
[Unit]
Description=My app
After=network.target

[Service]
User=user
WorkingDirectory=/home/user/my-app
ExecStart=/usr/bin/npm run start
Restart=always

[Install]
WantedBy=multi-user.target
UNIT

sudo systemctl daemon-reload
sudo systemctl enable --now my-app
```

`Restart=always` also revives the process if it crashes. Check on it with `systemctl status my-app` and read its logs with `journalctl -u my-app`.

These are in-box shell commands: run them over `box ssh`, or programmatically through the [command endpoint](/box/api/reference/agent/execute-box-command) or the SDKs' `command` method.

If the service serves HTTP, expose it with `host <port>`. Hosting the same port again after a resume returns the same URL and token, so links you handed out keep working. See [Hosting](/box/hosting).

Resume or fork from the latest snapshot when a user needs to continue or branch prior work:

<CodeGroup>
  ```bash CLI theme={null}
  box resume bx_f7k2q9hd
  box fork bx_f7k2q9hd
  ```

  ```bash curl theme={null}
  curl -sS -X POST "$BOX_API_BASE/boxes/bx_f7k2q9hd/resume" \
    -H "Authorization: Bearer $BOX_API_KEY"

  curl -sS -X POST "$BOX_API_BASE/boxes/bx_f7k2q9hd/fork" \
    -H "Authorization: Bearer $BOX_API_KEY"
  ```

  ```ts TypeScript theme={null}
  await box.resume({ boxId: "bx_f7k2q9hd" });
  const forked = await box.fork({ boxId: "bx_f7k2q9hd" });
  ```

  ```python Python theme={null}
  box.resume("bx_f7k2q9hd")
  forked = box.fork("bx_f7k2q9hd")
  ```
</CodeGroup>

For repeatable workflows, keep setup and start commands idempotent:

<CodeGroup>
  ```bash CLI theme={null}
  box ssh "$box_id" -- bash -s < ./setup.sh
  box ssh "$box_id" "cd /home/user/ariana-ide-private && npm run dev"
  ```

  ```bash curl theme={null}
  curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/commands" \
    -H "Authorization: Bearer $BOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command":"bash ./setup.sh","cwd":"ariana-ide-private"}'

  curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/commands" \
    -H "Authorization: Bearer $BOX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command":"npm run dev","cwd":"ariana-ide-private"}'
  ```

  ```ts TypeScript theme={null}
  await box.command({ boxId, commandRequest: { command: "bash ./setup.sh", cwd: "ariana-ide-private" } });
  await box.command({ boxId, commandRequest: { command: "npm run dev", cwd: "ariana-ide-private" } });
  ```

  ```python Python theme={null}
  box.command(box_id, CommandRequest(command="bash ./setup.sh", cwd="ariana-ide-private"))
  box.command(box_id, CommandRequest(command="npm run dev", cwd="ariana-ide-private"))
  ```
</CodeGroup>

## Related

* [Snapshots](/box/snapshots)
* [Secrets & Setup](/box/secrets)
* [SSH Access](/box/ssh-access)
* [Desktop Streaming](/box/desktop-streaming)
* [Hosting](/box/hosting)
