> Fetch the index of every Tonbo docs page as Markdown at https://tonbo.dev/llms.txt

# Run commands

Last updated 3 November 2026

> Machines are not open yet. These pages describe Machines as they will open; until then, a create answers [`region_not_offered`](https://tonbo.dev/docs/machines/troubleshooting/manage.md#region_not_offered) (422), “Machines are not offered in any region yet.”

Run one command in a Machine over HTTPS and get its output, its exit status and how it ended in the answer. The command lives exactly as long as the call: an agent’s tool call, a test run, a quick look at what is on disk.

> Planned Not served yet. This page describes how it will work, as decided; until it is served, every request below answers 404 at `https://api.us-east-1.tonbo.sh/v1`. The [Machines API reference](https://tonbo.dev/docs/reference/management/machines.md) lists each operation, marked Planned.

## Run a command

Send the command as an argv to the cell origin of the Machine’s region, with a key of your account:

```shell
curl -sS https://api.us-east-1.tonbo.sh/v1/machines/hello/exec \
  -H "Authorization: Bearer $TONBO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"command": ["ls", "-la", "/app"], "timeout_seconds": 60}'
```

The answer is one document once the command has ended:

```json
{
  "data": {
    "op": "0193a6c4e8a07d2c9f3b5a1e6d4c2b10",
    "deadline": "2026-11-03T09:31:00Z",
    "reason": "exited",
    "exit_code": 0,
    "signal": null,
    "duration_ms": 41,
    "killed_processes": 0,
    "stdout": { "encoding": "utf-8", "head": "total 8\n…", "tail": "", "bytes": 312, "omitted_bytes": 0 },
    "stderr": { "encoding": "utf-8", "head": "", "tail": "", "bytes": 0, "omitted_bytes": 0 },
    "machine": { "woke": false, "…": "…" }
  }
}
```

With `Accept: application/x-ndjson` it streams instead, one JSON object per line: a `start` line, then `stdout` and `stderr` lines (base64) in the order the command wrote them, a `tick` after 30 seconds without output, and an `end` line with the same fields as the document.

## How the command runs

- Without a shell: `command[0]` is found on the program’s `PATH`. Run `["sh", "-c", "…"]` for pipes and globs.
- In `cwd`, the image’s working directory by default, with the program’s environment plus the call’s `env`, and stdin from `stdin` (base64, up to 1 MiB) or empty.
- As `user`: a name or uid from the image’s `/etc/passwd`, or `root`; the image’s user when you leave it out.
- With the program’s resource limits, 1,048,576 open files among them; a command may lower its own, or raise them as root.

## Limits

- `timeout_seconds` is 10 minutes by default and at most 1 hour, counted from the command’s start, after any wake. Longer work is a [background process](https://tonbo.dev/docs/machines/processes.md).
- Output is capped at 64 MiB, both streams together; the document keeps the first and the last 512 KiB of each.
- The request body is at most 2 MiB, and a Machine runs at most 16 commands at once, an account 64.

The command ends, and everything it started with it, when it exits, at its deadline, at the output cap, when it is killed, or when your connection closes or stops reading.

## Waking and staying awake

A call wakes an asleep Machine first, with the same checks and the same credit as any wake (see [Sleep, wake and stop](https://tonbo.dev/docs/machines/sleep.md)), and its answer says whether it woke the Machine. While a command runs, it keeps the Machine awake. Every wake starts fresh, so a command that woke the Machine sees its image, its database and its Volume, not files an earlier wake left on other disks (see [What lasts](https://tonbo.dev/docs/machines/files.md#lasts)).

- `Tonbo-Wake: never` runs the command only if the Machine is awake, and otherwise answers 409 without waking it.
- `expect_activation`, the `Tonbo-Activation` of an earlier answer, runs it only in that same boot, and otherwise answers 409 `activation_changed`, so a sequence of calls never lands half on a fresh boot.
- Between calls, a [hold](https://tonbo.dev/docs/machines/holds.md) keeps the Machine awake.

## When the answer is lost

- A 200 means the command started exactly once.
- Any refusal other than 502 `lost` means it did not start.
- A 502 `lost`, or a connection that broke before the answer began, means Tonbo does not know whether it started. Send the same request with the same `Idempotency-Key`: the repeat answers the first call’s record and never runs it again. Keys are kept 24 hours.

## Refusals

- 422 `command_not_found`, `command_not_executable`, `cwd_not_found` or `user_not_found`: nothing ran.
- 409 `activation_changed`: another boot runs, or none does; nothing woke.
- 429 `exec_limit`: too many commands run at once; wait for one to end.
- A wake’s own refusals, such as 402 `payment_required`, pass through as a request to a port gets them.

What a command writes outside the Volume is gone at the next sleep: keep results in the [database or on the Volume](https://tonbo.dev/docs/machines/database.md).
