# Execute a command

> Execute `argv` in the primary container and wait for the process to exit.

> Nevia is in beta and open to selected teams. Public launch in Dec 2026. The CLI installs with `curl -fsSL https://get.nevia.cloud | sh`, and the MCP server is at https://api.nevia.cloud/mcp. A person signs in once in the browser.
> Setup, sign-in and requesting access: [SKILL.md](https://nevia.cloud/SKILL.md). When Nevia fits and when it doesn't: [why.md](https://nevia.cloud/why.md).

> For the complete documentation index, see [llms.txt](https://nevia.cloud/llms.txt). This page's HTML version: https://nevia.cloud/docs/reference/api/computers/execComputer

`POST https://api.nevia.cloud/v1/computers/{cmp}/exec`

## Authorization

- `bearerAuth`: HTTP bearer in the Authorization header

Send the token in the `Authorization: Bearer <token>` header. See [Authenticate](https://nevia.cloud/docs/reference/api.md#authenticate).

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `cmp` | path | string | yes | Computer id: 27 lowercase letters and digits. Match `^[A-Za-z0-9_-]{1,64}$`. |
| `Accept` | header | string | no | `text/event-stream` for SSE output, else JSON. |
| `Idempotency-Key` | header | string | no | Optional retry key, kept 24 hours. Length `1 <= length <= 255`. |

## Request body

Content type: `application/json`, required

Schema: `ExecRequest`

Run a command in the primary container

| Field | Type | Required | Description |
|---|---|---|---|
| `argv` | array<string> | yes | Program and its arguments. Items `1 <= items <= 4096`. |
| `env` | object | no | Extra env vars for this command only. They override stored vars of the same name and are not stored. Values can use `{{secrets.NAME}}` or `{{variables.NAME}}` templates. [Computer environment variables](https://nevia.cloud/docs/reference/computer-env.md). |
| `stdin` | string | no | Stdin text, at most 1 MiB of UTF-8. Length `length <= 1048576`. |

## Behavior

The command gets the computer's stored env, with `env` over it. Values resolve at call time, so secrets and variables take their current values.

There is no shell, cwd or timeout. Closing the request does not stop the process. An abandoned command runs until it exits.

Each `argv` item is at most 128 KiB of UTF-8, and the whole array at most 256 KiB as JSON.

With `Accept: text/event-stream`, `stdout` and `stderr` events carry a UTF-8 chunk as a JSON string, and `exit` carries `{exit_code, signal}`. A failure after the stream opens arrives as an `error` event: the error envelope plus `status`, the HTTP status it would have had.

The API accepts `Idempotency-Key` but does not replay it. Every call runs the command.

## Example request

### cURL

```bash
curl -X POST "https://api.nevia.cloud/v1/computers/01d4cnjk3xg90y576w8y6t4gdwm/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "argv": [
      "sh",
      "-c",
      "echo hello"
    ]
  }'
```

### JavaScript

```js
const body = JSON.stringify({
  "argv": [
    "sh",
    "-c",
    "echo hello"
  ]
})

fetch("https://api.nevia.cloud/v1/computers/01d4cnjk3xg90y576w8y6t4gdwm/exec", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.TOKEN}`
  },
  body
})
```

### Python

```python
import os
import requests

url = "https://api.nevia.cloud/v1/computers/01d4cnjk3xg90y576w8y6t4gdwm/exec"
body = """{
  "argv": [
    "sh",
    "-c",
    "echo hello"
  ]
}"""
response = requests.request("POST", url, data = body, headers = {
  "Content-Type": "application/json", 
  "Authorization": f"Bearer {os.environ['TOKEN']}"
})

print(response.text)
```

## Responses

### 200

The exit code, signal and buffered output, or an SSE stream.

Content type: `application/json`

Schema: `ExecResponse`

| Field | Type | Required | Description |
|---|---|---|---|
| `result` | ExecResult | yes | Raw exit of the command. |
| `operations` | array<OperationId> | yes | Operations this request started. |

Example:

```json
{
  "result": {
    "exit_code": 0,
    "signal": 0,
    "stdout": "hello\n",
    "stderr": ""
  },
  "operations": [
    "01d4cnjm89yk0r3xtv80dy0x7by"
  ]
}
```

Content type: `text/event-stream`

Server-sent events: `stdout`, `stderr`, `exit`, `error`
Type: `string`

Example:

```json
"event: stdout\ndata: \"hello\\n\"\n\nevent: exit\ndata: {\"exit_code\":0,\"signal\":0}\n\n"
```

### 400

`validation_failed`: malformed body, unknown field, or invalid id or name. Fix `details.field` and retry. `validation_failed`: `env` names a secret or variable that does not exist in the workspace.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `validation_failed: malformed body, unknown field, or invalid id or name. Fix \`details.field\` and retry`:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Unknown field `colour` in the request body. Remove it; request bodies are strict.",
    "details": {
      "field": "colour",
      "in": "body"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

Example `validation_failed: \`env\` names a secret or variable that does not exist in the workspace`:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Invalid `env.OPENAI_KEY` in the request body: secret `OPENAI_KEY` does not exist in workspace 01d4cnjjq40hnnh0nwmkg35nv2h. List them with GET /v1/secrets?workspace=01d4cnjjq40hnnh0nwmkg35nv2h.",
    "details": {
      "field": "env.OPENAI_KEY",
      "in": "body"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 401

`unauthorized`: the credential is missing, malformed, expired, or revoked. Send a valid bearer token.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `unauthorized`:

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Missing credential. Send `Authorization: Bearer <token>` with an access token.",
    "details": {},
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 403

`forbidden`: the `env` references a secret or variable the caller may not reference. Secrets need the `editor` role or higher in the workspace, variables any role.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `forbidden`:

```json
{
  "error": {
    "code": "forbidden",
    "message": "Referencing workspace secrets needs workspace#edit on workspace 01d4cnjjq40hnnh0nwmkg35nv2h. Ask a workspace admin to change your role.",
    "details": {
      "workspace": "01d4cnjjq40hnnh0nwmkg35nv2h",
      "permission": "workspace#edit"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 404

`not_found`: the computer does not exist, or you cannot see it. Both return the same response.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `not_found`:

```json
{
  "error": {
    "code": "not_found",
    "message": "Computer 01d4cnjk3xg90y576w8y6t4gdwm was not found. List the computers you can access with GET /v1/computers?workspace=<ws>.",
    "details": {
      "computer": "01d4cnjk3xg90y576w8y6t4gdwm"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 409

`invalid_state`: the computer is not `ready`, is put to sleep or deleted during the command, or a stored var names a secret or variable that no longer exists (`details.missing` lists them). `idempotency_conflict`: the `Idempotency-Key` was already used with a different body.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `invalid_state`:

```json
{
  "error": {
    "code": "invalid_state",
    "message": "Computer 01d4cnjk3xg90y576w8y6t4gdwm is sleeping and cannot run a command. Wake it first with POST /v1/computers/01d4cnjk3xg90y576w8y6t4gdwm/wake, then retry.",
    "details": {
      "computer": "01d4cnjk3xg90y576w8y6t4gdwm",
      "workspace": "01d4cnjjq40hnnh0nwmkg35nv2h",
      "state": "sleeping",
      "pending": null
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

Example `idempotency_conflict`:

```json
{
  "error": {
    "code": "idempotency_conflict",
    "message": "Idempotency-Key 8f1c2a7e-3b4d-4c5e-9f0a-1b2c3d4e5f60 was already used for a different POST /v1/computers/{cmp}/exec request. Use a new key for a new request.",
    "details": {
      "idempotency_key": "8f1c2a7e-3b4d-4c5e-9f0a-1b2c3d4e5f60"
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 422

`not_supported`: the command wrote more than 1 MiB to one stream. The JSON response does not buffer more.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `not_supported`:

```json
{
  "error": {
    "code": "not_supported",
    "message": "Computer 01d4cnjk3xg90y576w8y6t4gdwm: the command wrote more than 1024 KiB to stdout, which is all the JSON response buffers. Stream it with Accept: text/event-stream, or redirect the output to a file in the computer.",
    "details": {
      "computer": "01d4cnjk3xg90y576w8y6t4gdwm",
      "workspace": "01d4cnjjq40hnnh0nwmkg35nv2h",
      "stream": "stdout",
      "limit_bytes": 1048576
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 429

`rate_limited`: slow down. Retry after `Retry-After`.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `rate_limited`:

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after 2 seconds.",
    "details": {
      "retry_after_seconds": 2
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 500

`request_failed`, or the failed action's own code, such as `creation_failed`, `authorization_failed` or `command_execution_failed`. Quote `request_id` when reporting. The diagnostic stays in server logs.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `request_failed`:

```json
{
  "error": {
    "code": "request_failed",
    "message": "request failed",
    "details": {},
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```

### 503

The action is temporarily unavailable, named by its code (`creation_failed`, `wake_failed`, ...). Wait at least `Retry-After` seconds (60 by default). `details.retryable` says whether repeating the request is safe. Keep the original `Idempotency-Key`. Signing in again does not help.

Content type: `application/json`

Schema: `ErrorEnvelope`

Body of every error response

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | Error | yes |  |

Example `creation_failed`:

```json
{
  "error": {
    "code": "creation_failed",
    "message": "The computer could not be created. Try again later, and quote request_id if it persists.",
    "details": {
      "retryable": true
    },
    "request_id": "req_01j9k3m2p7q4r8s1"
  }
}
```
