--json and parse stdout when automating the Boat CLI. For typed HTTP clients, use the Python SDK or TypeScript/JavaScript SDK.
Some commands emit one JSON object. Long-running commands emit JSON Lines: one JSON object per line.
Argument parsing errors can still be emitted by the CLI parser on stderr before Boat’s JSON error handler runs.
For non-interactive environments, create a Boat API key with boat api-key create and pass it as BOAT_API_KEY; see API Keys for setup.
For runtime secrets inside sandboxes, use Dashboard > Environment. Dashboard secrets are injected as environment variables and secret files; configure them before running setup scripts or prompts that need credentials.
See Environments for the dashboard workflow and setup-script guidance.
Authenticate
Authenticate once before the first command in a process or container:--key-stdin reads the token from standard input, so it never reaches the process arguments, where any other user on the host can read it with ps or /proc/<pid>/cmdline while the command runs. Passing the token positionally (boat login "$BOAT_API_KEY") still works and is still supported, but it discloses the key on a shared or multi-tenant host. --key-stdin needs a Boat CLI newer than 0.1.211; check yours with boat --version. Older binaries only accept the positional form.
Output:
boat api-key list --json returns metadata without secrets.
If you run boat login --json with no key at all, the CLI starts the browser flow instead:
Output contract
Commands that return a single JSON object:
Commands that emit JSONL:
boat prompt takes an optional --provider (codex, claude, pi, opencode, prime, kimi), --model, and --reasoning-effort; --attach <path> (repeatable) to attach files/images; and the conversation flags --new, --resume <id>, and (on events/interrupt) --convo <id>. A single sandbox runs many conversations in parallel; every queued and chat line carries a conversationId, and boat conversations --json lists the ids to resume.
Setup Scripts and Secrets
The usual setup flow is:- Configure secrets in Dashboard > Environment.
- Create a sandbox with
boat new --jsonand wait for thereadyevent. - Run a non-interactive command with
boat ssh.
boat ssh <id> <command> prepares and registers the CLI-managed SSH key, then runs the command without opening an interactive shell. It streams stdin, stdout, and stderr, so a setup script can run without copying it into the sandbox first.
cmd.exe.
If you need the sandbox to keep running for a long uninterrupted workflow, disable auto-stop when creating it:
boat resume or boat fork, check app servers, workers, dev servers, tunnels, and desktop sessions, and run your setup or start command again if needed.
Prompt and events
boat prompt --provider codex <id> "..." --json first emits a queued line:
boat events --json emits the same chat line shape for persisted events. It may return fewer lines than boat prompt --json; in a live check, boat prompt emitted queued, queued-prompt, running-prompt, finished-prompt, and response lines, while boat events later returned the persisted finished-prompt and response lines.
response chat events can include tool data in data.tools; keep the full object if you need exact agent traces.
Bash JSONL parser
Node.js
Use a single-object helper for commands likeinfo, and a JSONL helper for commands like new.
Python
Direct SSH
The CLI manages the SSH key. For an interactive shell, prefer:boat scp, remote paths are passed through to OpenSSH scp after the <sandbox-id>: prefix. Absolute paths such as /home/user/setup.sh are the safest. Relative remote paths are resolved from the SSH user’s home directory (/home/user on hosted sandboxes). Avoid relying on ~ in automation because expansion can vary by local shell and scp mode.
For non-interactive commands, pass the command after the sandbox ID:
Errors
Most failed CLI commands in--json mode emit one final JSON line to stdout and exit non-zero. Commands that normally emit one JSON object still use this JSONL error line on runtime failure. Argument parsing failures, such as missing required flags or invalid numeric flag values, are emitted by the CLI parser on stderr and may not be JSON.
The error line
code and status. The backend field is named error; the CLI exposes that backend code as code so error can stay human-readable.
code or status because no Boat API error response was received:
Backend error shapes
The backend error object for Boat CLI API paths is one of these shapes:message when present. If there is no message, it humanizes known backend codes such as unauthorized, not_found, account_not_ready, method_not_allowed, and rate_limited; otherwise it formats the backend code and HTTP status.
For backend errors that include billingUrl, setupUrl, or dashboardUrl, the CLI appends that URL to the human-readable error string. Those URLs carry no credential: opening one lands on a signed-out dashboard.
Backend error codes
Common backend codes used by the Boat CLI paths:Local CLI errors
Local CLI validation can fail before the backend is called. These errors have no stablecode today. Examples from the current CLI source include invalid provider, invalid model, invalid reasoning effort, empty API key, missing local login, unsupported HTTP method, invalid local JSON from the API, SSH/SCP exit failures, and unreachable API host.
Common types
Boat
provisioned becomes ready, archiving becomes stopping, and archived becomes stopped.
SandboxListResult
boat list --json defaults to up/running sandboxes, the same as boat list --filter r --json. Use boat list --filter s --json for stopped sandboxes, combine groups like --filter sr, or use --all --json to include every state.
Example:
SandboxInfoResult
SandboxActionResult
Used bystop, resume, fork, and interrupt.
DesktopResult
HostResult
VncDesktopResult
ApiKeySecretResult
Returned byboat api-key create --json and boat api-key rotate --json. The secret exists only in this response and can never be retrieved again.
ApiKeyListResult
boat api-key list --json returns keys you created; add --all to include platform-managed per-sandbox machine keys (sandboxId set).
boat api-key usage <id> --json returns the same totals. Add --verbose to keep createdResources. The command still works after the key is revoked.
SandboxUsageResult
boat usage <id> --json returns the API payload unchanged. seconds already includes the sandbox type’s multiplier; dollars is seconds / secondsPerDollar. See Per-sandbox usage.
ConfigResult
LimitsResult
Create a sandbox
boat new --json emits JSONL, not a single JSON object.
Prompt and events
boat prompt --provider codex <id> "..." --json first emits a queued line:
boat events --json emits the same chat line shape for persisted events. It may return fewer lines than boat prompt --json; in a live check, boat prompt emitted queued, queued-prompt, running-prompt, finished-prompt, and response lines, while boat events later returned the persisted finished-prompt and response lines.
response chat events can include tool data in data.tools; keep the full object if you need exact agent traces.
Bash JSONL parser
Node.js
Use a single-object helper for commands likeinfo, and a JSONL helper for commands like new.
Python
Direct SSH
The CLI manages the SSH key. For an interactive shell, prefer:boat scp, remote paths are passed through to OpenSSH scp after the <sandbox-id>: prefix. Absolute paths such as /home/user/setup.sh are the safest. Relative remote paths are resolved from the SSH user’s home directory (/home/user on hosted sandboxes). Avoid relying on ~ in automation because expansion can vary by local shell and scp mode.
For non-interactive commands, pass the command after the sandbox ID: