# Running commands

Execute non-interactive commands in a Buddy Sandbox in Bash, JavaScript, TypeScript, or Python - with full history, logs, statuses, and exit codes.

Besides the interactive [terminal](/docs/sandboxes/terminal-and-ssh.md), a Sandbox runs **non-interactive commands**: you send a command, it executes, and Buddy keeps the whole record of it - status, exit code, runtime, and output.

Commands run as the `buddy` user with passwordless `sudo`, so use `sudo` for anything that installs system packages.

## In the UI

The **Exec** entry in the **Logs** tab lists every command executed in the Sandbox, newest first, each with the runtime it ran in, how long it took, and a link ot its output. Failed ones are marked, so you can see what has been run and what it printed without keeping a terminal open.

## History, statuses, and logs

Every execution is recorded for later review:

- **Status** - whether it is still running, finished, or failed
- **Exit code** - the process's result
- **Runtime** - which interpreter ran it
- **Log** - the full output, streamed live or read afterwards

Because commands are tracked individually, an agent that ran twenty of them leaves twenty inspectable records instead of one merged stream. See [Logs](/docs/sandboxes/logs.md).

## From the CLI

```bash
bdy sb exec command my-sandbox "npm test" --wait
```

### Runtimes

A command does not have to be shell. Pick the runtime and pass the source directly:

| Runtime | For |
| :--- | :--- |
| `BASH` | Shell commands - the default |
| `JAVASCRIPT` | Node scripts |
| `TYPESCRIPT` | TypeScript scripts |
| `PYTHON` | Python scripts |

```bash
bdy sb exec command my-sandbox "print(sum(range(10)))" --runtime PYTHON --wait
```

A Sandbox works as a code interpreter this way: send a snippet in the language you need, and get back stdout, stderr, and an exit code.

### Wait or return immediately

Two modes, chosen per command:

- **Wait.** With `--wait`, the call blocks until the command finishes and streams its output as it happens. 
- **Return immediately.** Without the flag, the call hands back a command id and leaves the process running. 

```bash
# start it and walk away
bdy sb exec command my-sandbox "npm run build"

# check on it later
bdy sb exec list my-sandbox
bdy sb exec status my-sandbox <command-id>
bdy sb exec logs my-sandbox <command-id>

# stop it
bdy sb exec kill my-sandbox <command-id>
```

### Working directory and user

A command starts in `/buddy` and runs as the `buddy` user. `/buddy` is also the default [app directory](/docs/sandboxes/configuration.md), which is where a fetched repository lands unless its **Path** points elsewhere - so on a default Sandbox a command already starts next to the code, see [Git and artifacts](/docs/sandboxes/git-and-artifacts.md). There is no flag for the directory or the user, so change them inside the command itself:

```bash
bdy sb exec command my-sandbox "cd /home/buddy/app && npm test"
bdy sb exec command my-sandbox "sudo -u agent-a whoami"
```

## The Sandbox has to be running

A command needs a running machine. Send one to a stopped Sandbox and it is rejected with `sandbox did not reach RUNNING state`, so start the Sandbox first:

```bash
bdy sb start my-sandbox --wait
bdy sb exec command my-sandbox "npm test" --wait
```

An executed command also counts as activity, so it holds off the Sandbox timeout while it runs. See [Lifecycle](/docs/sandboxes/lifecycle.md).

## Commands or apps?

| | Use it for |
| :--- | :--- |
| **Command** | Something that runs, finishes, and returns an exit code - tests, builds, migrations, scripts |
| **[App](/docs/sandboxes/apps.md)** | Something that stays up - a web server, a worker, a dev server |

<Hint type="info">

Commands can also be run programmatically - over the [REST API](/docs/api/sandboxes/run-command.md), from the [SDK](/docs/sandboxes/sdk.md), from inside the Sandbox with [`this exec`](/docs/sandboxes/self-management.md), and through [MCP](/docs/ai-agents/mcp.md) by AI agents.

</Hint>


---
Original source: https://buddy.works/docs/sandboxes/running-commands