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

# Run commands

> Run a shell command on a cloud machine and wait for its output, or start a long job and follow its logs, wait for it and cancel it.

`POST /v1/machines/{id}/run` runs a command on the machine. Running a command on a paused machine resumes it first, and the response says `"resumed": true`.

| Body field | Description |
| - | - |
| `command` | A shell command line, run with `sh -c`. Send `command` or `argv`. |
| `argv` | The program and its arguments as a list, run without a shell. |
| `cwd` | Working folder on the machine (default `/project`). |
| `env` | Extra environment variables, as an object. |
| `timeout` | Seconds before the command is killed. |
| `wait` | `true` to wait up to about 60 seconds for it to finish and return its output. |

## Short commands: wait for the output

With `"wait": true` the call waits up to about 60 seconds and returns `{job_id, status, exit_code, stdout, stderr, truncated, resumed, next}`. `stderr` is merged into `stdout` in order, so `stderr` is always empty. When the output is longer than 256 KB, `stdout` holds the last 256 KB and `truncated` is `true`; read all of it from the job's logs. If the command is still running after about 60 seconds, the call returns the running job instead (`202`), and you follow it as below.

```sh curl theme={"system"}
curl -s https://api.voyager.so/v1/machines/$MACHINE/run \
  -H "Authorization: Bearer $VOYAGER_API_KEY" -H "Content-Type: application/json" \
  -d '{"command": "nvidia-smi --query-gpu=name,memory.total --format=csv", "wait": true}'
```

```python Python theme={"system"}
import os, requests

r = requests.post(
    f"https://api.voyager.so/v1/machines/{os.environ['MACHINE']}/run",
    headers={"Authorization": f"Bearer {os.environ['VOYAGER_API_KEY']}"},
    json={"argv": ["nvidia-smi"], "wait": True},
).json()
print(r["exit_code"], r["stdout"])
```

```sh CLI theme={"system"}
voyager-cloud exec $MACHINE -- nvidia-smi
```

A non-zero `exit_code` means the command failed. `voyager-cloud exec` waits for any length of command, streams its output and exits with the same code.

## Long commands: jobs

Without `wait`, the call returns `202` with a **job** (`mjb_…`) straight away.

| Call | What it does |
| - | - |
| `GET /v1/machines/jobs/{job}?wait=N` | The job: `{id, machine_id, status, exit_code, output_tail, started_at, ended_at, next}`, holding up to `N` seconds (at most 60) for it to finish. `status` is `running`, `succeeded`, `failed` or `canceled`; `output_tail` is the last few KB of output. |
| `GET /v1/machines/jobs/{job}/logs?cursor=` | The output so far, a page at a time: `{text, next_cursor, eof}`. Pass `next_cursor` as `cursor` for the next page; `eof` is `true` once the job has ended and everything was returned. Add `follow=true` to stream the output as plain text until the job ends. |
| `POST /v1/machines/jobs/{job}/cancel` | Stops the job. |

With the CLI:

```sh theme={"system"}
job=$(voyager-cloud exec --detach $MACHINE -- ./long-render.sh)
voyager-cloud logs $job --follow
voyager-cloud wait $job     # exits with the job's exit code
```

A machine pauses itself after `idle_timeout` seconds without a command or file transfer.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.