Installation & updates
--no-update.
Global flags
These flags work with any command:--json is enabled automatically whenever output is piped or redirected, so scripts get JSONL without passing the flag.
Wherever a command takes a sandbox ID, two aliases also work: current (the last sandbox created in this shell) and self (the sandbox you are running inside, when using the CLI from within a sandbox).
Shell completion
boat completions <shell> prints a completion script for bash, zsh, fish, or PowerShell. It completes subcommands and your live sandbox IDs (plus current and self), with a 15 second cache so repeated tabs are instant.
Authentication
boat onboard
Sets this machine up: signs you in through the browser, saves your token, then asks only for what your account still needs: the third-party safety answer, and plan checkout.
--google / --email answer that question up front. See Quickstart.
Safe to re-run. On a reinstall or a second machine it recognises the account you already have and skips each step that account has finished:
The answer is recorded on the environment when you give it, so both answers are remembered, not just “a platform of mine”. A plan is never treated as an answer, since dashboard checkout does not ask the question.
See Reinstalling, or a second machine.
boat login [key]
Sign in with an existing API token, or start a browser sign-in flow if no key is given. GitHub is the default; Google and email also work.
--key-stdin reads the token from standard input instead of the command line, keeping it out of the process arguments that any other user on the host can read. Prefer it for non-interactive sign-in; see Use in Code. Passing the token positionally still works. The two are mutually exclusive. --key-stdin needs a Boat CLI newer than 0.1.211.
Without a key the CLI prints a URL, opens it, and waits up to six minutes for you to finish in the browser. --email sends a code to that address; omit the address and the browser page asks for it. Disposable email domains are refused.
Every method lands on the same account only if it is already connected to it. A method you have never used before starts a new account, even when the email matches; add connections from Dashboard > Account instead. See Quickstart.
Create production API keys with boat api-key create or from the dashboard API Keys page. See API Keys for key management and Use in Docker for Docker and hosted-worker setup.
boat api-key
Create and manage API keys for SDKs, CI, and other projects.
--ttl defaults to 90d and cannot exceed 365d. --sandbox and --env are repeatable. --preset is read-only, full-sandbox, ci, or admin. --actions and --preset cannot be combined.
Secrets are shown once at create and rotate and can never be retrieved again. list shows prefix, last four, scope, expiry, 30-day request total, and live resource count. usage still works after revoke. Revoke does not delete sandboxes or Agents.
Create calls the dedicated POST /api/v1/api-keys/scoped endpoint and requires a browser session or an admin-scoped token. During rollout it may be temporarily unavailable; api-key list remains available. Rotate and revoke stay session-gated. See API Keys.
boat webhook
Register account-wide lifecycle webhooks for automation.
sandbox.ready, sandbox.error, sandbox.archived, and sandbox.hydrated. Omit --event to subscribe to all four. The signing secret is shown only at create/rotate time. See Webhooks.
boat logout
Sign out and clear the local token.
boat status
Show API health, the signed-in account and plan, and the local config path.
Sandbox lifecycle
boat new
Create a new sandbox.
--type picks the machine size: small runs at half rate, default at 1x, large at 2x, and xlarge at $0.20 per running hour. xlarge requires the effective $100 plan or higher and a bare-metal operator allocation. A fork inherits the source sandbox’s size unless you pass --type, and boat resume --type moves an existing sandbox between sizes. See Machine Capabilities for the specs of each size and Billing & Limits for what they cost.
On the free trial,
--no-auto-stop and a --ttl above 2 hours are refused, and --type large is not available. See On the free trial.--env sets per-sandbox environment variables on top of your dashboard secrets; per-sandbox values win on name conflicts. See Environments.
--environment <name> picks which environment the sandbox starts from: its repositories, secrets, and credentials. Omit it to use your default. An unknown name is rejected before the sandbox is created, so a typo costs you nothing. Note that --environment and --env are unrelated: one picks a template, the other sets a variable on this one sandbox. See Environments.
--no-env creates a sandbox that receives none of the secrets attached to your account, and confines the sandbox to itself so it can’t act on your account or other sandboxes. Use it for sandboxes you give to your own users. SSH, SCP, desktop, snapshots, and public URLs still work. See Environments. For more than the occasional sandbox, prefer an environment marked safe for third parties, which applies the same protection to every sandbox that uses it and survives forks and resumes.
--setup-file reads a local shell script (UTF-8, up to 64KB) and runs it on the sandbox in the background after the sandbox is ready, and it never delays ready. Watch the outcome as setupStatus (pending, running, done, failed) and setupError in boat info. It combines with --from.
--personal bills you even when an org wallet is active. Day to day, run boat org switch once and every later boat new follows it. Override one create with boat --org <org> new or boat --org personal new. See boat org.
--from <name> starts the sandbox from a named snapshot you saved with boat snapshot <id> <name>, so the stack is already installed. It does not carry the source sandbox’s environment: pass --environment, or take your default. Note this is unrelated to boat env set-file --from, which reads a local file. See Snapshots & Copies.
Returns the sandbox ID, IP, and initial state.
For a long uninterrupted workflow, disable auto-stop:
boat list
List your up/running sandboxes with their current state and ID. By default, boat list is equivalent to boat list --filter r.
--filter with state group letters:
Combine letters, for example
boat list --filter sr lists stopped and up/running sandboxes. Use --all to include every state.
boat extend <id>
Change the auto-stop timer for an existing sandbox.
--hours or --ttl for a timed extension. Use --no-auto-stop when the sandbox should keep running until you stop it yourself.
boat info <id>
Get details for a specific sandbox: state, IP, desktop availability, TTL remaining.
boat stop <id>
Pause a running sandbox. Creates a snapshot then stops billing. The sandbox enters archiving → archived.
Snapshotting takes a moment. The sandbox is not yet stopped when the command returns; poll
boat info to confirm archived state.--force stops the sandbox anyway and permanently loses everything written since the last successful snapshot. It is irreversible, so only use it after a stop has already failed.
boat delete <id>
Permanently delete a sandbox and its snapshots. The sandbox is force-stopped without a final snapshot, then every snapshot chain it exclusively owns is deleted from storage.
--yes to skip the prompt; in scripts (--json, or no terminal attached) --yes is required and the command refuses without it rather than hanging.
Deletion is not instant: the machine has to be torn down before its data can be removed. The sandbox disappears from boat list right away, the command prints the deletion operation id (bdop_…), and then follows that operation until it finishes.
What survives. Snapshot data shared with something else is kept, because deleting it would break whatever else reads it:
- a sandbox you forked from this one, or a resume of it, restores from the same physical snapshot objects
- a named snapshot saved from this sandbox (
boat snapshot <id> <name>) keeps its data; remove it withboat snapshot rm <name>if you want those bytes gone too
boat deletion status <operation-id>
Check back on a deletion you started earlier, here or through the API. Statuses are pending, processing, blocked and completed. blocked is not a dead end: an attempt hit something it could not finish yet, most often a snapshot another sandbox still reads, and it is retried automatically with backoff.
boat resume <id>
Resume a stopped sandbox from its last snapshot. The CLI waits for a ready state and a successful no-op command before printing its final ready event. This checks the command-execution restore gate; it does not wait for background hydration or setup scripts. The wait is bounded to 30 minutes and fails on terminal sandbox states or non-retryable API errors. Older installed Box and Boat binaries need an updated CLI to get this readiness check. See Snapshots.
boat stop).
Use -e/--env to set per-sandbox environment variables on resume, with the same semantics as boat new -e: repeat for multiple values, per-sandbox values override dashboard variables with the same name, and the set you pass replaces the sandbox’s current per-sandbox variables.
Use --environment <name> to move the sandbox onto a different environment as it resumes. Omit it and the sandbox keeps the environment version it already had; a resume never silently moves a sandbox to a newer version. An unknown name is rejected before anything changes. If the new environment withholds something the sandbox currently holds, that secret is scrubbed off the disk during the resume and does not come back. See Environments.
Use --no-env to resume a stopped sandbox after dropping your account secrets and scrubbing owner secrets inherited from the snapshot. This is one-way: the sandbox stays no-env afterward.
Use --type to resume onto a different machine size (small, default, large, or xlarge). Omit it to keep the sandbox’s current size. Shrinking is refused if the sandbox holds more data than the smaller machine can take, and the sandbox is left untouched. See Machine Capabilities.
Use --ttl <seconds> to set the resumed sandbox’s lifetime, or --no-auto-stop to switch auto-stop off. Omit both and the sandbox keeps the setting it already had, so a resume never quietly shortens or extends it.
Resume behaves like a server reboot: systemd services you enabled start again automatically. Processes you ran by hand (dev servers, background jobs, tunnels, desktop sessions) do not survive; restart them, or make them a systemd service.
For xlarge, resume with the same explicit bare-metal operator pin. The effective billing plan must be $100 or higher.
boat fork <id>
Clone a sandbox from its latest snapshot into a new independent sandbox.
--type to give the fork a different machine size from its source. The source sandbox is never modified.
Use --ttl <seconds> or --no-auto-stop to set the fork’s lifetime. A fork does not inherit its source’s: it defaults to 1 hour, so forking a sandbox with auto-stop switched off does not silently produce another sandbox nothing will stop.
Use --environment <name> to point the fork at a different environment. Omit it and the fork inherits exactly the environment version its source is on, so a fork never picks up configuration the source never had. The source sandbox is never modified either way. See Environments.
Use --no-env to fork into a no-env sandbox. A fork of a no-env source is always no-env.
Use -e/--env to set per-sandbox environment variables on the fork, with the same semantics as boat new -e. The set you pass replaces the per-sandbox variables the fork would inherit from the source sandbox; omit it to inherit them unchanged.
boat events <id>
Read the agent’s work on a Sandbox: prompts and responses. By default it streams every conversation on the sandbox; each event carries a conversationId (visible with --json). Add --follow to keep polling for new events, or --convo to watch a single conversation.
These are the agent’s conversations, not the sandbox’s lifecycle. A Sandbox that has never been prompted returns an empty list even though it started, stopped and resumed. For lifecycle state use
boat info.boat conversations [id]
List a sandbox’s conversations, most recently prompted first: id, last activity, prompt count, whether a turn is running, the last harness and model, and a preview of the last prompt. Alias sandbox convos.
sandbox current is the conversation a bare boat prompt from anywhere would continue (the sandbox’s most recently prompted one); this shell is the one a bare boat prompt from this shell continues. Copy an id into boat prompt --resume <id>, boat steer --convo <id>, boat events --convo <id> or boat interrupt --convo <id>.
boat steer <id> <message>
Send a message to a turn that is already running, without stopping it. The agent takes it into account and keeps what it was doing. This is the third option next to boat prompt (which waits for the turn to end) and boat interrupt (which throws it away).
--convo and it steers the conversation this shell last prompted, the same one a bare boat prompt continues. Steering a conversation with nothing in flight is refused with no_running_turn; use boat prompt for that.
Claude Code, Codex, pi and Prime Agent take the message into the running turn natively, so nothing is interrupted; if a harness accepts the message but its turn ends without acting on it, Boat continues it immediately as its own turn on the same session, so a steer is always acted on. OpenCode has no mid-turn primitive, so sandbox stops that turn and immediately continues the same conversation with your instruction, keeping all of its memory. The JSON output’s native field says which path ran, and the steer appears in boat events as a steer event carrying the settled mode (native, native-continued, fallback, late). See Integrated agents.
boat interrupt <id>
Interrupt running agent work in a sandbox. By default it stops every conversation on the sandbox; scope it to one with --convo and the others keep running.
Access
boat ssh <id> [command]
SSH into a sandbox, or run a command non-interactively. Manages the key at ~/.ssh/ascii_box_ed25519 automatically (the same key file the box CLI used, so nothing to re-authorize).
boat exec <id> [command...]
Run a command in a sandbox over the Boat API, without an SSH session or key setup. boat exec exits with the remote command’s exit code, so it drops straight into scripts and CI.
Wait for the sandbox to reach
ready before running boat exec; earlier calls are refused with a retryable boat_starting error.
For anything that may run longer than the 600 second synchronous cap, detach and poll instead:
--detach starts the command in the background and answers with a JSON object; take processId from it, as above. Remember that --json turns itself on whenever output is piped or captured, so inside a script you always get JSON here even without the flag. Output goes to ~/.ascii/processes/<pid>.log on the sandbox. --status <pid> prints whether it is still running, the exit code once finished, and a tail of stdout/stderr. If the sandbox’s agent restarts (stop/resume), the status degrades to lost but the log files stay on disk. See Long-Running Tasks.
boat env
Manage the templates new sandboxes start from: repositories, secrets, and which of your credentials a sandbox may use. Every change mints a new immutable version. Running sandboxes stay on the version they started with until boat env upgrade. See Environments.
boat env set <name>
Change what the environment injects.
Contents
set-file reads contents from --from <local-file>, or from stdin when --from is omitted. Paths are relative to the sandbox work directory (/home/user).
boat env upgrade <name>
Move this environment’s sandboxes onto its latest version. Live sandboxes get the new configuration pushed immediately, with any secret the new version withholds scrubbed off the machine first. Stopped sandboxes pick it up when they resume. Nothing upgrades on its own.
boat host <id> <port>
Expose a running service inside a sandbox on a stable HTTPS URL without opening an interactive SSH session.
boat scp
Copy files to/from a sandbox. Use bx_<id>:/path as the remote address.
On macOS and Linux, recursive copies to a new directory stream one archive over SSH when
tar is available on both ends, avoiding per-file network round trips. The new directory becomes visible only after a complete transfer. Files, existing-directory merges, and unsupported trees use the installed OpenSSH scp.
boat forward <id>
Forward one TCP port from a sandbox to your local machine.
--reverse: reach your machine from the sandbox
--reverse sends the tunnel the other way. A port on your machine becomes
reachable inside the sandbox at 127.0.0.1:<remote>, so an agent in the sandbox can
call an MCP server, a local model, or a webhook receiver that never leaves your
laptop.
Both directions run in the foreground until Ctrl+C. If the tunnel drops because
the sandbox moved (
boat stop then boat resume brings it back on a new IP), the CLI
refetches the connection and redials up to five times before giving up. A
failure at startup, such as the port already being taken on the far side, is
reported straight away instead of being retried.
Nothing is exposed publicly by either direction: the tunnel rides the same SSH
session as boat ssh, and the sandbox side listens on loopback only. For a public
HTTPS URL for a port inside the sandbox, use boat host.
boat desktop <id>
Open the sandbox’s desktop streaming URL in your browser.
--vnc for
a VNC stream that tunnels over plain HTTPS and is far more tolerant of poor
connections. The viewer also offers a one-click switch to VNC if the default
stream struggles.
The first
--vnc on a sandbox takes a few seconds while it prepares the VNC
stack (the CLI shows a spinner); subsequent opens are instant.boat browser <id>
Return a browser-only stream from the same running sandbox.
--profile lets you keep several signed-in Chrome profiles on one sandbox and pick
one per stream. The directory is created and given to the browser user for you.
It must be an absolute path outside system directories, and it must not live
under /home/user, which the browser sandbox masks with an empty directory.
Because the profile lives on the sandbox filesystem, snapshots and forks carry it
along. Switching profiles restarts Chrome and leaves the stream up. Sandboxes
created before this feature return chrome_profile_unsupported; recreate the
sandbox on a current image to use the flag.
The stream is 1920x1080 at 60 fps. It shows Chrome with tabs and an address bar, uses an isolated streaming process and identity, does not expose the desktop clipboard bridge, does not create a separate sandbox, and cannot fall back to the desktop or VNC. Window-close chrome is hidden. Mute, reconnect, and fullscreen stay on the viewer. Closing the last tab opens a new tab and leaves the stream up. Running the command again leaves the live stream up. Opening the new URL in a second tab replaces the first tab and keeps the same Chrome session. New sandboxes receive the browser-view files at provision. Treat the URL as a secret.
This is display and input confinement, not isolation from the sandbox itself. Code already running in the sandbox, especially code with root access, can inspect or modify the browser process and its data.
Snapshots
boat snapshots [id]
List snapshots across your sandboxes, or for one sandbox.
boat snapshot <id> <name>
Save a sandbox’s disk under a name, so boat new --from <name> can deploy it as many times as you like. Reuse a name to replace it.
ready. You can keep up to 10 named snapshots. See Snapshots & Copies.
boat snapshot latest|tree|pull
Inspect or download a snapshot. Works while the sandbox is stopped.
pull writes home_user/ (your /home/user) and docker/ (named volumes). See Snapshots.
boat snapshot delete <snapshotId>
Permanently delete one ordinary filesystem snapshot. Refused with 409 while a later incremental snapshot or an active restore still depends on it. Named snapshots are removed by name with boat snapshot rm <name> instead.
AI agents
boat prompt [id]
Send a natural-language prompt to an AI agent running inside the sandbox. Omit the ID to target the current sandbox of your shell (the last boat new there), or the sandbox you are running inside. Omit --provider to use the default harness and model selected on the Agents page of the dashboard.
Run
boat prompt --help to fetch the current provider, model, and reasoning-effort list from the Boat API.
Conversations (running agents in parallel)
A sandbox runs many conversations at once, each with its own history, so one sandbox can drive several independent agent tasks (different features, different users, a demo) in parallel rather than queuing them one behind another.--newstarts a fresh conversation and makes it this shell’s current one. Every prompt prints its conversation id right underqueued:(conversation: <id>, with(new)when--newcreated it) and carries it asconversationIdin--json.--resume <id>continues a specific conversation;--resume currenttargets this shell’s current one.- No flag continues this shell’s current conversation. The “current conversation” is scoped to your shell, exactly like the
currentsandbox id, so two shells (or two people) prompting the same sandbox each keep their own thread and don’t disturb each other. boat conversationslists every conversation on the sandbox with its id, prompt count, running state and last prompt, so a thread from another shell or another day can be resumed by id.- Conversations run in parallel up to a per-sandbox limit that scales with the sandbox’s memory; beyond it, further prompts queue and start as turns finish. Continue a conversation on a different
--providerand its history carries across the switch.
Account
boat limits
Show remaining machine starts, compute time, and credits. Create, fork, and resume each count as one start.
--json is the same payload the API returns, including starts.minute.remaining, creditBalanceHours, and packBalanceDollars.
boat usage <id>
Show the machine time one sandbox has consumed and what it costs, over its whole life or a window. Works on running and stopped sandboxes; a running sandbox’s figure keeps growing until it stops, and running in the JSON says whether it still is (false once stopped, or while a refused stop holds the meter paused).
Human output prints billable machine time (the sandbox type’s multiplier applied), the cost at list price, and the window.
--json is the API payload: seconds, dollars, secondsPerDollar, sandboxType, billingMultiplier, since, until and running. See Per-sandbox usage.
boat dashboard
Open your web dashboard in the browser, already signed in. The link carries a single-use code that expires in 15 minutes and cannot call the API (never your sandbox token), so it is safe in a terminal, a log, or a message. If you signed in with a service API key, the link opens the dashboard signed out: creating, rotating, or revoking API keys requires the browser sign-in flow.
boat org
Show, switch, create, transfer, or delete the organization wallet that new sandboxes bill to. One shared plan and balance. boat org switch is sticky; --org (or BOAT_ORG) overrides it for one command.
boat org transfer and boat org delete target the invocation scope (--org / BOAT_ORG if set, otherwise the sticky wallet). Deleting an org with --org does not clear a different sticky wallet.
boat data-retention
Show or enable zero data retention, which queues every archived sandbox for permanent deletion.
boat login without a key), not an API key. See Data retention and deletion.
boat self-update
Check for and install the latest CLI release on your current channel.
~/.config/ascii/boat/config.json. boat status prints its path along with the resolved API URL, account and plan.