> ## 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.

# CLI

> Install the sail command-line tool, plus every command grouped by area

The `sail` CLI manages sailboxes and apps from the terminal. It is a single
native binary with no runtime dependencies. Run `sail --help` or
`sail <command> --help` for the same information at the prompt, and see the
[Sailboxes guide](/sailboxes) for what you can do with it.

## Install

The CLI and the SDKs are separate products. If you only want to drive Sail
from code, install an [SDK](/reference/python-sdk). If you already use the
Python SDK, you have the CLI too: `pip install sail` puts `sail` on your
`PATH`.

### macOS and Linux

```bash theme={null}
curl -fsSL https://cli.sailresearch.com/install.sh | sh
```

This installs the latest `sail` into `~/.sail/bin`, a directory only sail
writes to. If that directory is not on your `PATH`, the installer adds it to
your shell startup files and prints the line to run in the current shell.

### Windows

```powershell theme={null}
irm https://cli.sailresearch.com/install.ps1 | iex
```

This installs `sail.exe` into `%LOCALAPPDATA%\sail\bin` and puts that
directory at the front of your user `PATH`. Restart your shell afterward.

### Verify

```bash theme={null}
sail --version
```

### Installer options

Both installers read a few environment variables.

| Variable           | Effect                                                                                                                                                                                                        |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SAIL_CLI_VERSION` | Install a specific version. Default: latest.                                                                                                                                                                  |
| `SAIL_HOME`        | Relocate sail's home directory (absolute path); the CLI lives in `$SAIL_HOME/bin`. The CLI and the Python SDK honor the same variable, and the installer persists it for future shells.                       |
| `SAIL_INSTALL_DIR` | Install a copy at this exact directory instead (for provisioning scripts). The `sail` command from a Python environment keeps using `$SAIL_HOME/bin`; `sail update` run from such a copy updates it in place. |

Pin a version, substituting the release you want for `X.Y.Z`:

```bash theme={null}
curl -fsSL https://cli.sailresearch.com/install.sh | SAIL_CLI_VERSION=X.Y.Z sh
```

### Update

```bash theme={null}
sail update
```

This downloads the latest release and replaces the binary you ran, which is
normally the standalone install. Re-running the installer does the same
thing, and it works the same however you first got the CLI, including
through `pip install sail`.

`sail update` updates the CLI itself. Upgrading a Sailbox is a different
operation: `sail box upgrade <sailbox>`.

The Sail API warns when your CLI version is nearing the end of its support
window. The warning includes update instructions. A version past the end of
its support window is rejected with an update error before any operation
runs.

### One binary, many channels

There is one real `sail` CLI per user: the standalone install at
`~/.sail/bin/sail` (`%LOCALAPPDATA%\sail\bin\sail.exe` on Windows). The
installer writes it, `sail update` replaces it, and upgrading the SDK with
`pip install -U sail` keeps it current too. `pip install sail` does not add
another copy: in a Python environment, the `sail` command is a small
launcher that runs the standalone install, completing the setup
automatically the first time you run it, with no separate download.
Installing the SDK into any number of Python environments still leaves
exactly one CLI to keep current.

`sail --version` prints the path of the binary that ran.

## Interactive shell

For interactive use, `sail shell` is usually the most convenient option. It opens
a REPL on your machine that accepts every command below without the leading
`sail` (so `box list`, `box create ...`), and adds touches the one-shot commands
do not: line editing and history, a picker menu when you omit a sailbox id, and
confirmation prompts.

```bash theme={null}
sail shell
```

The individual `sail <command>` subcommands are non-interactive and take their
arguments up front, which suits scripts and agents (add `--json` for
machine-readable output).

Mind the naming: `sail shell` is a shell for *managing* sailboxes from your
machine. It is not a shell *inside* a box. To open a shell inside a running
sailbox, use `sail box shell` (below).

## Global options

These work on any command.

| Option   | Effect                                                     |
| -------- | ---------------------------------------------------------- |
| `--json` | Emit machine-readable JSON instead of human-readable text. |
| `--help` | Show help for the CLI or a command.                        |

`sail --version` prints the CLI version and the path of the binary that
answered (top-level only).

Authentication comes from `SAIL_API_KEY`, falling back to the credential stored
by `sail auth login`. See [Configuration](/reference/sdk-configuration).

## Authentication

```bash theme={null}
sail auth login [--api-key <key>]   # browser login, or store/validate a key (also reads a piped key)
sail auth whoami                    # show the active key
sail auth logout                    # remove the stored key
```

## Apps

```bash theme={null}
sail app find <name>     # find an app by name
sail app create <name>   # create an app (returns the existing one if present)
sail app list            # list apps in the current org
```

## Sailbox lifecycle

| Command                                    | Description                                                      |
| ------------------------------------------ | ---------------------------------------------------------------- |
| `sail box show <id>`                       | Show a single Sailbox.                                           |
| `sail box top`                             | Live top-style view of Sailbox usage.                            |
| `sail box list`                            | List Sailboxes in the current org (see flags below).             |
| `sail box terminate <id>`                  | Permanently terminate a Sailbox.                                 |
| `sail box sleep <id>`                      | Checkpoint and release compute (`--wake-at` to schedule a wake). |
| `sail box pause <id>`                      | Freeze in place.                                                 |
| `sail box resume <id>`                     | Resume a paused or sleeping Sailbox.                             |
| `sail box checkpoint <id>`                 | Checkpoint a running Sailbox (`--name`, `--ttl-seconds`).        |
| `sail box from-checkpoint <checkpoint-id>` | Create a new Sailbox from a checkpoint (`--name`).               |
| `sail box upgrade <id>`                    | Upgrade the runtime (now if running, else at next wake).         |

### `sail box create`

```bash theme={null}
sail box create --app <name> --name <name> [options]
```

| Option                   | Description                                                                                                                                                                                                                                                                                     |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--app <name>`           | App name (created if missing). Required.                                                                                                                                                                                                                                                        |
| `--name <name>`          | Sailbox name within the app. Required.                                                                                                                                                                                                                                                          |
| `--arch <arm\|amd>`      | Base image architecture (default `arm`).                                                                                                                                                                                                                                                        |
| `--port <n>`             | HTTP ingress port to expose. Repeatable.                                                                                                                                                                                                                                                        |
| `--size <s\|m\|l>`       | Resource size (default `m`): `s` = 1 vCPU, 16 GiB memory, 32 GiB disk; `m` = 4 vCPU, 32 GiB memory, 128 GiB disk; `l` = 8 vCPU, 64 GiB memory, 256 GiB disk. Ongoing billing is by usage; each size also has a one-time creation charge. `s` gives the fastest cold starts, forks, and resumes. |
| `--memory-limit-gib <n>` | Memory ceiling in whole GiB, within the size's range: 2-64 for `s`, 8-128 for `m`, 16-256 for `l`. The size's default when omitted.                                                                                                                                                             |
| `--disk-limit-gib <n>`   | Disk ceiling in whole GiB, within the size's range: 8-128 for `s`, 32-512 for `m`, 64-1024 for `l`. The size's default when omitted.                                                                                                                                                            |
| `--private`              | Restrict all access to you (creator-only); an org admin can override some operations with a recorded reason. Requires a user-minted API key.                                                                                                                                                    |
| `--enable-ssh`           | Expose port 22, trust your org's CA, and start sshd.                                                                                                                                                                                                                                            |
| `--identity-file <path>` | Local SSH key to authenticate with (implies `--enable-ssh`).                                                                                                                                                                                                                                    |

### `sail box list`

| Option              | Description                  |
| ------------------- | ---------------------------- |
| `--app <name>`      | Filter by app name.          |
| `--status <status>` | Filter by status.            |
| `--search <text>`   | Filter by id/name substring. |
| `--limit <n>`       | Maximum rows.                |
| `--offset <n>`      | Rows to skip.                |

## Run commands and connect

### `sail box exec`

Run a command in a sailbox, streaming its output.

```bash theme={null}
sail box exec [options] <id> -- <command> [args...]
```

| Option                 | Description                                                                    |
| ---------------------- | ------------------------------------------------------------------------------ |
| `--cwd <dir>`          | Working directory inside the guest.                                            |
| `--timeout <dur>`      | Kill the command after this long (e.g. `30s`, `5m`).                           |
| `-e`, `--env <K=V>`    | Environment variable for the command (repeatable).                             |
| `-i`, `--stdin`        | Pipe local stdin to the guest command.                                         |
| `-t`, `--tty`          | Run under a pseudo-terminal driven by your terminal.                           |
| `--no-forward`         | With `--tty`, turn off all local forwarding (browser, ports, paste/clipboard). |
| `--no-forward-browser` | With `--tty`, keep everything forwarded except the box's browser opens.        |
| `--background`         | Start the command and return once accepted (no output captured).               |

### `sail box run`

Create an ephemeral sailbox, run a command, then terminate it. A shortcut for
`create` + `exec` + `terminate`; for workflows that reuse a sailbox, use those
directly.

```bash theme={null}
sail box run --app <name> [options] -- <command> [args...]
```

Takes the same `create` sizing/port flags plus `--name` (default `run-<hex>`),
`--cwd`, `--timeout`, `--env`, and `--keep` (leave the sailbox running instead of
terminating it).

### `sail box shell`

```bash theme={null}
sail box shell <id> [--shell <path>] [--no-forward] [--no-forward-browser]
```

Open an interactive shell inside a running sailbox. This is the simplest and
preferred way in: it runs a PTY over `exec`, so it opens no port and does not
count against your org's raw-TCP endpoint limit. (Not to be confused with `sail shell`,
the local REPL for managing boxes.)

While the shell is open, the session forwards to your machine:

* **Browser opens.** When a program in the box opens a browser, the page opens
  in your local browser instead. This covers logins like `claude login`,
  `codex login`, and `gh auth login`. A login that redirects to a `localhost`
  callback completes end to end.
* **Localhost servers.** A server the box starts on `localhost` (say a dev
  server on port 3000) becomes reachable at `http://localhost:3000` on your
  machine. The same port is used on your machine, so if it is already in use
  locally that server is not forwarded.
* **Paste and drag-and-drop.** Files dragged onto the terminal upload to
  `/tmp/sail-drops` in the box and paste as their guest paths. Press Ctrl+V to
  forward your clipboard. On devbox images an image or text lands on the box's
  clipboard, so pasting a screenshot into `claude` or `codex` works as it does
  locally, and text copied inside the box is copied back to yours. On other
  images a Ctrl+V image uploads as a file and pastes its path, while text uses
  your terminal's own paste. Large uploads show a progress line; press Esc to
  cancel one.

Pass `--no-forward` to turn all of it off, for example for an untrusted or
automated session, or `--no-forward-browser` to keep everything but the box's
browser opens. `sail box exec --tty` forwards the same way (and takes both
flags too).

### `sail box cp`

```bash theme={null}
sail box cp <src> <dst>
```

Copy a file to or from a sailbox; `<id>:<path>` denotes the remote side.

## Networking

```bash theme={null}
sail box expose <id> <guest-port> [--tcp] [--allowlist <addr|app>]...  # expose a guest port at runtime
sail box unexpose <id> <guest-port>                                    # remove a runtime ingress port
sail box listeners <id>                                                # list a sailbox's ingress listeners
sail box address <id> <guest-port>                                     # print the external address for one port
```

`--tcp` exposes raw TCP instead of HTTP. `--allowlist` restricts sources to an
address or a range (e.g. `203.0.113.0/24`), or, for HTTP listeners, a Sail app
name. Re-exposing a port replaces its whole list; omitting `--allowlist`
reopens the port. See [Networking](/sailboxes-networking) for the full model.

## Custom domains

`sail box domain` serves a Sailbox HTTP listener on a hostname you own, with
TLS certificates obtained and renewed for you.

```bash theme={null}
sail box domain target                             # print the custom-domain and wildcard certificate targets
sail box domain attach <id> <domain> --port <guest-port>  # attach a domain to an exposed HTTP listener
sail box domain list <id>                          # list the domains attached to a Sailbox
sail box domain detach <id> <domain>               # stop routing a domain to the Sailbox
```

`attach` requires `--port` naming an exposed HTTP listener, and checks that
your DNS record points at your target first. See
[Custom domains](/sailboxes-custom-domains) for the DNS setup, apex-domain
options, and certificate behavior.

## SSH

`sail box ssh` sets up SSH access so you can reach a box as `ssh <name>.sail`.

For a quick interactive shell, prefer [`sail box shell`](#sail-box-shell): it
needs no open port. Reach for SSH when you need a real SSH endpoint rather than a
PTY over `exec`, such as `scp`/`rsync`, an editor's remote mode, or a devbox you
work in day to day. Enabling it exposes port 22 as a TCP ingress port, which
counts against your org's raw-TCP endpoint limit.

```bash theme={null}
sail box ssh enable <id> [--identity-file <path>] [--allowlist <addr>]... [--no-wait] [--timeout <dur>]
sail box ssh alias <id>... [--identity-file <path>]
sail box ssh disable <id>
```

* **enable**: turn on SSH for a box (expose port 22, install your org's CA, start
  sshd), certify your key on this machine, and add the `<name>.sail` shortcut.
  `--allowlist <addr>` restricts the sources allowed to reach port 22 to an
  address or a range (repeatable).
* **alias**: add `ssh <name>.sail` shortcuts for boxes already SSH-enabled
  elsewhere (e.g. from the SDK), without waking them.
* **disable**: stop SSH on a box and drop its local shortcut.

Only the public half of your key is certified; the private key is referenced in
your SSH config, never read.

## Configuration

Manage `~/.sail/config.toml`.

```bash theme={null}
sail config get [key]          # print one value, or the whole file
sail config set <key=value>... # set one or more entries
sail config unset <key>...     # remove one or more keys
sail config reset              # reset user-settable settings (run 'sail auth logout' to remove the stored key)
```
