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

# 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:

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

The `--` separates Devbox CLI arguments from the command that should run inside the Devbox. You need it whenever the command has flags of its own. For a bare command, you can leave it out:

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

When the command fails, `devbox exec` exits with a non-zero status.

<Info>
  Commands run as the `devbox` user with `/workspaces` as the working directory, and flags for `devbox exec` itself go before the Devbox name.

  If the Devbox is paused, it is resumed automatically before the command runs.
</Info>

For interactive programs or piped input, use [`devbox ssh`](#interactive-access) instead.

### Detached Executions

Pass `-d` to start a command and return immediately. The CLI prints the execution ID instead of waiting:

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

```
exec_nl1f65debpkamdbdnuqra114cc
```

<Info>
  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.
</Info>

Use the printed ID with `devbox logs` to follow the output or collect it later. In a script, capture it as you start the command:

```bash theme={null}
EXEC=$(devbox exec -d my-devbox -- ./scripts/long-build.sh)
devbox logs my-devbox "$EXEC"
```

## Reading Command 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.

### Streaming Logs

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:

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

```
 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.

For scripting, use JSON output:

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

```json 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.

## Interactive Access

`devbox exec` runs commands non-interactively: no terminal is allocated, and standard input is not forwarded. When a task needs either, use `devbox ssh`.

`devbox ssh` opens an interactive shell, and can also run a single command with `devbox ssh [command]`:

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

Because it allocates a terminal and forwards standard input, it handles interactive programs and piped data:

```bash theme={null}
cat local.sql | devbox ssh my-devbox -- psql
```

## Choosing an Approach

| Feature                  | `devbox exec`  | `devbox ssh` | Session                 |
| ------------------------ | -------------- | ------------ | ----------------------- |
| Interactive terminal     | No             | Yes          | Yes                     |
| Standard input forwarded | No             | Yes          | Yes                     |
| Recorded and listable    | Yes            | No           | N/A                     |
| Output re-readable later | Yes            | No           | While the session lives |
| Runs after the CLI exits | Yes, with `-d` | No           | Yes                     |

* Use **`devbox exec`** for scripted and automated runs, and whenever you want the output kept.
* Use **`devbox ssh`** for interactive work, or when you need to pipe data into a command.
* Use a **[Session](/docs/devbox/sessions)** for a long-lived interactive process, such as a dev server you want to reattach to.

## Next Steps

**[Sessions →](/docs/devbox/sessions)**
Persistent terminal sessions that survive disconnections.

**[Remote Development →](/docs/devbox/remote-development)**
Connect to your Devbox via SSH, VS Code, Cursor, Zed, or JetBrains.

**[Coding Agents →](/docs/devbox/agents)**
Drive Devboxes from AI coding agents.
