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

# Shell

> The bash tool runs a command in the sandbox and returns buffered stdout, stderr, and an exit code.

The **`bash`** tool is how the agent runs commands on the [computer](/docs/computer/index). Each call executes `bash -c <command>` in a **non-login shell**, so a `cwd` you pass is honored as the working directory for that command. It is a single request/response — not a stream.

<Note>
  Exec on a **sleeping** computer wakes it automatically. Exec on a **parked** computer is **rejected** — resume it first. See [lifecycle](/docs/computer/sandbox#lifecycle).
</Note>

## Examples

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta computer exec box -- "ls -la /workspace"

  # with a timeout; cd inside the command, there is no --cwd
  vetta computer exec box --command "cd /workspace && npm test" --timeout-ms 30000
  ```

  ```typescript TypeScript theme={"system"}
  const result = await vetta.computers.exec(computer.id, {
    command: "npm test",
    cwd: "/workspace",
    env: { CI: "1" },        // this call only; not persisted
    timeoutMs: 30_000,
  });

  console.log(result.exitCode, result.stdout);
  ```

  ```bash cURL theme={"system"}
  curl https://api.vetta.sh/v1/computers/$COMPUTER_ID/exec \
    -H "Authorization: Bearer $VETTA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "command": "npm test",
      "cwd": "/workspace",
      "env": { "CI": "1" },
      "timeout_ms": 30000
    }'
  ```
</CodeGroup>

## Output caps at a glance

| Field    | Cap           | Behavior beyond cap |
| -------- | ------------- | ------------------- |
| `stdout` | 262,144 chars | Truncated           |
| `stderr` | 262,144 chars | Truncated           |

<Tip>
  When you expect large output, redirect it to a file (`… > /workspace/out.log 2>&1`) and read the parts you need with the [filesystem](/docs/computer/filesystem) tools instead of returning it all through `stdout`.
</Tip>

## Fields

<ParamField path="command" type="string" required>
  The command line to run. Executed as `bash -c <command>`.
</ParamField>

<ParamField path="cwd" type="string">
  Working directory for this command. Because the shell is non-login, `cwd` is respected for the call.
</ParamField>

<ParamField path="env" type="object">
  Environment variables for **this call only**. They are **not persisted** — the next `bash` call starts without them. There is no create-time environment injection.
</ParamField>

<ParamField path="timeout_ms" type="integer">
  Maximum time to wait before the command is killed and the call returns.
</ParamField>

<Warning>
  `env` is per-call and ephemeral. There is no way to bake environment variables into a computer at create time. With the coming egress pinning, secrets are supplied by the [vault](/docs/identity/vault) at the network boundary rather than as sandbox env vars — see [Networking](/docs/computer/networking#egress-pinning-coming-soon).
</Warning>

## Response

The command is run to completion and its output is **buffered**, then returned together:

<ResponseField name="stdout" type="string">
  Buffered standard output. Capped at **262,144 characters**; output beyond the cap is truncated.
</ResponseField>

<ResponseField name="stderr" type="string">
  Buffered standard error, capped at **262,144 characters** independently of `stdout`.
</ResponseField>

<ResponseField name="exit_code" type="integer">
  The process exit code.
</ResponseField>

<Info>
  The `bash` tool is **not streaming**. stdout and stderr are collected in full (up to the cap) and returned once the command exits or `timeout_ms` elapses. For long-running work, have the command write progress to a file and poll it with [`read`](/docs/computer/filesystem).
</Info>

<Card title="Next: browser" icon="globe" href="/docs/computer/browser">
  Drive a real, managed browser scoped to an allow-list of domains.
</Card>
