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

# POST /v1/capsules/{id}/exec — Execute a command

> POST /v1/capsules/{id}/exec — Execute a shell command inside a capsule. Supports foreground (blocking) and background (non-blocking) execution modes.

Use this endpoint to run a command inside a running capsule. In foreground mode (the default), the request blocks until the process exits and returns the full stdout, stderr, and exit code. In background mode, the server starts the process and returns immediately with its PID and a tag you can use to stream or kill it later.

## Endpoint

```
POST https://app.wrenn.dev/api/v1/capsules/{id}/exec
```

## Authentication

<ParamField header="X-API-Key" type="string" required>
  Your team's API key. Pass the full `wrn_...` key value.
</ParamField>

## Path parameters

<ParamField path="id" type="string" required>
  The capsule ID.
</ParamField>

## Request body

<ParamField body="cmd" type="string" required>
  The command to execute, e.g. `"python"` or `"/bin/bash"`.
</ParamField>

<ParamField body="args" type="string[]">
  Arguments to pass to the command, e.g. `["-u", "train.py"]`.
</ParamField>

<ParamField body="timeout" type="integer" default="30">
  Maximum number of seconds to wait for the process to exit (foreground only). Set to `0` for no timeout.
</ParamField>

<ParamField body="envs" type="object">
  Additional environment variables to inject into the process, e.g. `{"DEBUG": "1"}`. Background exec only.
</ParamField>

<ParamField body="cwd" type="string">
  Working directory for the process, e.g. `"/workspace"`. Background exec only.
</ParamField>

<ParamField body="background" type="boolean" default="false">
  When `true`, the process is started in the background and the server responds immediately with HTTP 202. Use the returned `pid` or `tag` to stream or kill the process later.
</ParamField>

## Responses

### 200 — Foreground execution complete

Returned when `background` is `false` (or omitted). The process has exited and the full output is included.

<ResponseField name="stdout" type="string">
  Captured standard output. Base64-encoded when the output contains binary data (check the `encoding` field).
</ResponseField>

<ResponseField name="stderr" type="string">
  Captured standard error.
</ResponseField>

<ResponseField name="exit_code" type="integer">
  Exit code returned by the process. `0` conventionally indicates success.
</ResponseField>

<ResponseField name="duration_ms" type="integer">
  Wall-clock time the process ran, in milliseconds.
</ResponseField>

<ResponseField name="encoding" type="string">
  Output encoding. Either `"utf-8"` or `"base64"`. Check this field before decoding `stdout`/`stderr`.
</ResponseField>

### 202 — Background process started

Returned when `background` is `true`. The process is running inside the capsule; use the `pid` or `tag` with the processes endpoints to manage it.

<ResponseField name="pid" type="integer">
  Operating system PID of the process inside the capsule.
</ResponseField>

<ResponseField name="tag" type="string">
  Stable identifier for this background process. Auto-generated if you did not supply one in the request. Use this tag to stream or kill the process.
</ResponseField>

## Examples

### Foreground execution

Run a command and wait for the result:

```bash theme={null}
curl -X POST https://app.wrenn.dev/api/v1/capsules/cap_abc123/exec \
  -H "X-API-Key: wrn_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "cmd": "python",
    "args": ["-c", "print(\"hello\")"]
  }'
```

```json theme={null}
{
  "stdout": "hello\n",
  "stderr": "",
  "exit_code": 0,
  "duration_ms": 83,
  "encoding": "utf-8"
}
```

### Background execution

Start a long-running process without blocking:

```bash theme={null}
curl -X POST https://app.wrenn.dev/api/v1/capsules/cap_abc123/exec \
  -H "X-API-Key: wrn_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "cmd": "python",
    "args": ["-u", "server.py"],
    "background": true,
    "envs": {"PORT": "8080"},
    "cwd": "/workspace"
  }'
```

```json theme={null}
{
  "pid": 42,
  "tag": "bg-a1b2c3d4"
}
```

## Python SDK

```python theme={null}
from wrenn import Capsule

with Capsule(wait=True) as capsule:
    # Foreground — blocks until done
    result = capsule.commands.run("python -c 'print(\"hello\")'")
    print(result.stdout)     # "hello\n"
    print(result.exit_code)  # 0

    # Background — returns immediately
    handle = capsule.commands.run("python -u server.py", background=True)
    print(handle.pid)  # e.g. 42
    print(handle.tag)  # e.g. "bg-a1b2c3d4"
```

## Errors

| Status | Meaning                                                                   |
| ------ | ------------------------------------------------------------------------- |
| `404`  | Capsule not found or does not belong to your team.                        |
| `409`  | Capsule is not in the `running` state. Start or resume the capsule first. |
