# Executing Commands

`devbox exec` runs a command inside a Devbox without opening an interactive shell. Each run is recorded as an **execution** with its own ID, and its output is retained on the Devbox — so you can stream it live, or come back and read it later with `devbox logs`.

This makes `devbox exec` a good fit for scripted and automated work: builds, test suites, migrations, and anything driven by a coding agent.

## Running Commands

Run a command and stream its output back to your terminal.

**CLI**

```bash theme={null}
devbox exec my-devbox ls
```

When the command has flags of its own, add `--` to separate the Devbox CLI arguments from the command that should run inside the Devbox:

```bash theme={null}
devbox exec my-devbox -- ./scripts/test.sh
```

**TS SDK**

`devbox.exec()` takes the executable and its arguments, and resolves with the output and exit code:

```typescript theme={null}
const result = await devbox.exec(["./scripts/test.sh"], {
  onStdout: (data) => process.stdout.write(data),
  onStderr: (data) => process.stderr.write(data),
});

process.exitCode = result.exitCode ?? 1;
```

A non-zero exit code resolves normally rather than throwing, so check `exitCode` yourself. Use `devbox.shell()` when the command needs pipes, redirects, or variable expansion. See [Run commands](/content/docs/reference/typescript-sdk/devbox/commands.md).

## Detached Executions

Coding agents often need to start a long build or test run without blocking on it. `devbox exec -d` starts the command and returns immediately, leaving it running on the Devbox. It prints an execution ID, which the agent uses to check the output when it needs the result:

```bash theme={null}
devbox exec -d my-devbox -- ./scripts/long-build.sh
```

```bash Output nocopy theme={null}
exec_nl1f65debpkamdbdnuqra114cc
```

A detached execution keeps running after the CLI exits. A foreground execution, by contrast, is tied to your CLI session, so prefer `-d` for long-running work or when your connection might drop. However, a detached execution ends if the Devbox stops. For a process that should keep running, restart when it fails, and start again on boot, create a [service](/content/docs/devbox/services.md) instead.

### Streaming Logs

Output from every execution is retained on the Devbox, so you can read it while a command is still running or long after it has finished. Retained output survives pause and resume, and is removed when the Devbox is deleted.

Stream the output of an execution by ID:

```bash theme={null}
devbox logs my-devbox exec_nl1f65debpkamdbdnuqra114cc
```

`devbox logs` first replays the output that has already been captured, then follows the live output, and returns once the execution completes. This works for executions that have already finished too, which is how you re-read the results of an earlier run.

### Listing Executions

List the executions retained on a Devbox:

**Table**

```bash theme={null}
devbox logs list my-devbox
```

```bash Output nocopy theme={null}
 ID                               Command             Started          Status
 exec_ftv7gbs955agrel08t5u6tv67c  ./scripts/lint.sh   Jul 29 16:05:11  completed
 exec_bf1p8g8uimrcjrvclteb5t5d48  ./scripts/test.sh   Jul 29 16:07:42  failed (1)
 exec_nl1f65debpkamdbdnuqra114cc  ./scripts/build.sh  Jul 29 16:08:10  running
```

The **Status** column is `running` while the command is still going, then `completed`, or `failed` with the command's exit code.

**JSON**

```bash theme={null}
devbox logs list my-devbox -o json
```

```json Output nocopy theme={null}
{
  "actions": [
    {
      "id": "exec_bf1p8g8uimrcjrvclteb5t5d48",
      "command": {
        "command": "./scripts/test.sh"
      },
      "started_at": "2026-07-29T14:07:42.594451722Z",
      "completed_at": "2026-07-29T14:07:49.262962529Z",
      "error": "./scripts/test.sh failed: exit status 1",
      "exit_code": 1
    }
  ]
}
```

`error` and `exit_code` are only present when the execution failed, and `completed_at` is unset while it is still running. Executions are listed in the order they started.

## Next Steps

Open a shell on a Devbox with SSH or a session.

Keep a Devbox running while a build or an agent works.

Drive Devboxes from AI coding agents.
