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

# Run commands

> Execute structured commands and shell scripts in a Devbox.

Run non-interactive commands with `exec()` or `shell()`. Choose between structured arguments and shell evaluation based on the command you need to run.

<Info>
  Command operations start a stopped Devbox automatically. Commands run with `exec()` and `shell()` are retained with their output and can be inspected later with `devbox logs`.
</Info>

## `exec()`

Use `exec()` to pass an executable and its arguments without invoking a shell. Arguments are passed literally, so shell expansion, pipelines, redirects, and environment-variable interpolation do not apply.

### Example

Run a command and inspect its result:

```typescript {2,6} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const result = await devbox.exec(["node", "--version"]);
if (result.exitCode !== 0) {
  throw new Error(result.error ?? result.stderr);
}
console.log(result.stdout.trim());
```

### API reference

```typescript theme={null}
exec(argv: readonly string[], options?: ExecOptions): Promise<ExecResult>
```

#### Arguments and options

<ResponseField name="argv" type="readonly string[]" required>
  The executable followed by its arguments. The array must contain at least one item.
</ResponseField>

<ResponseField name="options" type="ExecOptions">
  Options for the command.

  <Expandable title="properties" defaultOpen>
    <ResponseField name="cwd" type="string">
      The working directory. Absolute paths are used as provided. Relative paths resolve from the Devbox workspace directory.
    </ResponseField>

    <ResponseField name="env" type="Record<string, string>">
      Additional environment variables. Names must start with a letter or underscore and contain only letters, numbers, and underscores.
    </ResponseField>

    <ResponseField name="stdin" type="string | Uint8Array">
      Data provided to standard input. Strings are encoded as UTF-8.
    </ResponseField>

    <ResponseField name="onStdout" type="(data: Uint8Array) => void">
      Called for each standard-output chunk. Output is also collected in the returned result.
    </ResponseField>

    <ResponseField name="onStderr" type="(data: Uint8Array) => void">
      Called for each standard-error chunk. Output is also collected in the returned result.
    </ResponseField>

    <ResponseField name="signal" type="AbortSignal">
      Cancels the operation when the signal is aborted.
    </ResponseField>

    <ResponseField name="timeoutMs" type="number">
      The total timeout budget in milliseconds, including activation and connection time. The value must be finite and non-negative.
    </ResponseField>
  </Expandable>
</ResponseField>

When `cwd` is omitted, the command runs in the Devbox's default directory. If the Devbox checks out a repository during creation, that directory may not exist until the checkout completes. Pass an explicit `cwd` when running a command immediately after creation.

#### Return value

`exec()` resolves with an `ExecResult` after the command finishes.

```typescript theme={null}
interface ExecResult {
  exitCode: number | null;
  signal: string | null;
  error?: string;
  stdout: string;
  stderr: string;
}
```

<ResponseField name="exitCode" type="number | null" required>
  The command's exit code, or `null` when no exit code is available.
</ResponseField>

<ResponseField name="signal" type="string | null" required>
  The signal that ended the command, or `null` when no signal is available.
</ResponseField>

<ResponseField name="error" type="string">
  Agent-reported failure detail, such as a command-not-found message.
</ResponseField>

<ResponseField name="stdout" type="string" required>
  The complete standard output decoded as UTF-8.
</ResponseField>

<ResponseField name="stderr" type="string" required>
  The complete standard error decoded as UTF-8.
</ResponseField>

<Warning>
  A non-zero exit code does not reject the promise. Check `exitCode` to determine whether the command succeeded. The promise rejects for failures such as an invalid request, an aborted operation, a timeout, or a transport error.
</Warning>

### More examples

#### Pass arguments containing spaces

Arguments containing spaces remain single arguments.

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.exec(["printf", "%s\n", "hello world"]);
```

#### Stream command output

Stream output while retaining it in the returned result.

```typescript {2,4-5} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const result = await devbox.exec(["npm", "test"], {
  cwd: "/workspace",
  onStdout: (data) => process.stdout.write(data),
  onStderr: (data) => process.stderr.write(data),
  timeoutMs: 10 * 60_000,
});
```

***

## `shell()`

Use `shell()` when a command requires shell syntax such as pipelines, redirects, variable interpolation, or multiple statements.

### Example

Run a script that chains two commands, then print its standard output:

```typescript {2-3} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const result = await devbox.shell("npm install && npm test");
process.stdout.write(result.stdout);
```

### API reference

```typescript theme={null}
shell(script: string, options?: ShellOptions): Promise<ExecResult>
```

#### Arguments and options

<ResponseField name="script" type="string" required>
  The script to evaluate with the Devbox shell.
</ResponseField>

<ResponseField name="options" type="ShellOptions">
  All `ExecOptions`, plus the `shell` property.

  <Expandable title="additional property" defaultOpen>
    <ResponseField name="shell" type="string">
      The shell executable. The SDK uses the Devbox's configured shell when available and otherwise falls back to `/bin/sh`.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Return value

`shell()` returns the same `ExecResult` as `exec()`. A non-zero exit code resolves normally and must be checked by the caller.

### More examples

#### Set the working directory and environment variables

```typescript {3-4} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.shell("npm install && npm test", {
  cwd: "/workspace",
  env: { CI: "true" },
});
```

#### Use a specific shell

```typescript {2} theme={null}
const devbox = await client.devboxes.get("sdk-example");
await devbox.shell("echo $SHELL", { shell: "/bin/bash" });
```

## Choose between `exec()` and `shell()`

| Use       | When                                                                                                                                                   |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `exec()`  | You have an executable and structured arguments and do not need shell evaluation. This is the safer default for arguments derived from external input. |
| `shell()` | You need pipelines, redirects, variable interpolation, command chaining, or another shell feature.                                                     |

## Related documentation

<Columns cols={3}>
  <Card title="Use interactive terminals" icon="terminal" href="/docs/reference/typescript-sdk/terminals">
    Open and control interactive terminal sessions.
  </Card>

  <Card title="Create and manage Devboxes" icon="container" href="/docs/reference/typescript-sdk/devboxes">
    Create a Devbox and control its lifecycle.
  </Card>

  <Card title="Handle errors and timeouts" icon="triangle-alert" href="/docs/reference/typescript-sdk/errors">
    Cancel operations and handle SDK failures.
  </Card>
</Columns>
