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

# Execute bash

> Run a bash command on the computer and get its output.

On Linux, runs Bash and returns combined stdout and stderr. Linux commands run with `HOME=/root`, `DISPLAY=:99`, and `PATH=/usr/local/bin:/usr/bin:/bin`. `:99` is the boot screen. To run on another screen, pass `?screen=`, described in [Query parameters](#query-parameters).

On Windows, this endpoint runs PowerShell, despite its name. Use PowerShell syntax. The command runs from the user's Desktop folder and honors `timeout` the same way. The response carries `stdout`, `stderr`, `exit_code`, and `output` (stdout followed directly by stderr) instead of the fields listed under [Response](#response), plus `error` when the command could not run. A command that runs out of time returns `200` with `exit_code: 124`, `error: "timeout"`, and the output captured so far.

## Path parameters

<ParamField path="id" type="string" required>
  Computer ID (UUID).
</ParamField>

## Query parameters

<ParamField query="screen" type="string">
  Which [screen](/api-reference/screens/list) to run the command on. Optional.
  Omit it, or send `default`, to run on the screen the computer booted with. For
  any other screen, the command runs with `DISPLAY` set to that screen's
  display, so a window it opens appears on that screen. An unknown id returns
  `404` and nothing runs. Only a Linux computer has more than one screen: on any
  other computer, every id except `default` returns `404`.
</ParamField>

<Note>
  For a screen other than `default`, Orgo first checks that the screen exists,
  then prefixes your command with `export DISPLAY=:N;` for that screen's display:
  `:100` for `screen-100`. The rest of the command runs exactly as you sent it,
  and the `command` echoed in the response is yours, without the prefix. The body
  is checked before the screen, so an invalid `command` returns `400` even when
  the screen does not exist.
</Note>

## Body parameters

<ParamField body="command" type="string" required>
  A non-empty command string. Bash on Linux; PowerShell on Windows.
</ParamField>

<ParamField body="timeout" type="integer" default="200">
  How long the command may run, in seconds. Optional, and clamped to 1-300 when
  you send it: a larger value silently becomes 300, and `0` or a non-numeric
  value becomes 10. Omitting it entirely allows the command 200 seconds.
</ParamField>

<Note>
  Omitting `timeout` allows 200 seconds. The API proxy waits 30 seconds longer than the command timeout. Send an explicit timeout up to 300 seconds for a longer command. This is synchronous execution; it does not return a background job ID.
</Note>

## Response

<ResponseField name="success" type="boolean">
  `true` whenever the command ran at all, regardless of what it exited with.
  Read `exit_code` to find out whether the command itself succeeded.
</ResponseField>

<ResponseField name="action" type="string">
  Always `bash`.
</ResponseField>

<ResponseField name="command" type="string">
  Echo of the command you sent. With `?screen=`, the `DISPLAY` prefix Orgo adds
  is left out.
</ResponseField>

<ResponseField name="output" type="string">
  Combined stdout and stderr, in that order, joined by a newline when both are
  non-empty.
</ResponseField>

<ResponseField name="exit_code" type="integer">
  The command's exit status, or `-1` when it was killed by a signal. A command
  killed by `timeout` returns `-1`. There is no separate timeout flag: a `-1`
  with truncated output is the only signal that the time ran out.
</ResponseField>

<ResponseField name="error" type="string | null">
  Always `null` on a `200`. A command that fails is reported through `exit_code`
  and `output`, not here.
</ResponseField>

<ResponseField name="error_type" type="string | null">
  Always `null` on a `200`.
</ResponseField>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://www.orgo.ai/api/computers/$COMPUTER_ID/bash \
    -H "Authorization: Bearer $ORGO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command": "ls -la /home/user"}'

  # Run on a second screen, where $DISPLAY is :100
  curl -X POST "https://www.orgo.ai/api/computers/$COMPUTER_ID/bash?screen=screen-100" \
    -H "Authorization: Bearer $ORGO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command": "echo $DISPLAY"}'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      f"https://www.orgo.ai/api/computers/{computer_id}/bash",
      headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
      json={"command": "ls -la /home/user"}
  )

  result = response.json()
  print(result["output"])
  print(f"Exit code: {result['exit_code']}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`https://www.orgo.ai/api/computers/${computerId}/bash`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ command: 'ls -la /home/user' })
  });

  const { output, exit_code } = await response.json();
  console.log(output);
  console.log(`Exit code: ${exit_code}`);
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "success": true,
  "action": "bash",
  "command": "ls -la /home/user",
  "output": "total 32\ndrwxr-xr-x 4 user user 4096 Jan 15 10:30 .\ndrwxr-xr-x 3 root root 4096 Jan 15 10:00 ..\n-rw-r--r-- 1 user user  220 Jan 15 10:00 .bashrc\ndrwxr-xr-x 2 user user 4096 Jan 15 10:30 Desktop\n",
  "exit_code": 0,
  "error": null,
  "error_type": null
}
```

<Tip>
  For Python code execution, use [Execute Python](/api-reference/computers/exec) instead.
</Tip>

## Errors

| Status | Meaning |
| - | - |
| `400` | The computer has no VM attached: `{"error": "Desktop instance not available"}`. A body that is not JSON returns `{"error": "Expected a JSON object"}`. A missing, empty, or non-string `command` returns `{"error": "command must be a non-empty string"}`. |
| `401` | Invalid API key: `{"error": "Invalid API key"}`. A request with no `Authorization` header returns `{"error": "Authentication required"}`. Access failures also return `401` on this endpoint, not `403`: `{"error": "You do not have access to this workspace."}` when you are neither the owner nor a member of the computer's workspace, `{"error": "This workspace is view-only. Ask the owner for write access (workspace_read_only)."}` for a view-only member, and `{"error": "This API key cannot access this workspace (workspace_scope_mismatch)."}` for a workspace-scoped key used outside its workspace. A server-side fault while verifying the credential also returns `401`, with `{"error": "Service temporarily unavailable. The database is not accepting requests. Retry shortly."}`. Retry that one; the key is fine. |
| `402` | The computer is a trial computer whose trial is not active: `{"error": "Choose a plan to continue."}`. |
| `404` | No computer with this id: `{"error": "Desktop not found"}`, plus a `hint` explaining that computer ids do not survive a rebuild. Also returned when `?screen=` names a screen this computer does not have, and then nothing runs: `{"error": "no screen \"screen-101\"", "request_id": "…", "upstream_status": 404}`. |
| `500` | The command could not be started at all, with the computer's own message in `error` and `upstream_status: 500`. |
| `503` | The computer could not be reached. The body is `{"error": "Could not reach the desktop. Try again in a moment."}` with a `code` and a diagnostic: `vm_status`, `desired_status`, `host_reachable`, `desktop_api_reachable`, and a `hint`. Safe to retry. Also returned when the computer never finished provisioning: `{"error": "Computer not ready"}`. |
| `504` | The command outlived the time the API hop allows: `{"error": "The command exceeded the allowed time and was aborted.", "code": "timeout"}`. No output comes back. |

A command that merely exits non-zero is **not** an error status: it is a `200`
with a non-zero `exit_code`. Every failure raised after the request leaves the
API layer carries a `request_id`. Quote it in support requests. When the
computer agent itself answered non-2xx, the body additionally carries
`upstream_status`.

```json theme={null}
{
  "error": "The command exceeded the allowed time and was aborted.",
  "request_id": "9f2b7c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
  "code": "timeout"
}
```


## OpenAPI

````yaml POST /computers/{id}/bash
openapi: 3.1.0
info:
  title: Orgo API
  description: >-
    Launch cloud computers that AI agents can control and interact with. Create
    workspaces, provision computers, and control them programmatically.
  version: 2.0.0
  contact:
    name: Orgo Support
    email: spencer@orgo.ai
    url: https://orgo.ai
servers:
  - url: https://www.orgo.ai/api
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Account
    description: >-
      Account capacity: how many computers an account may run, and adding or
      giving back more.
  - name: Clients
    description: >-
      Run Orgo for your clients from your own app: a workspace and scoped key
      each, billed to you or to them.
  - name: Workspaces
    description: Organize computers into named workspaces
  - name: Computers
    description: Provision and manage virtual computers
  - name: Computer Lifecycle
    description: Start, stop, and restart computers
  - name: Computer Actions
    description: Control mouse, keyboard, and execute commands
  - name: Screens
    description: >-
      More than one desktop on a single computer. Each screen is its own X
      server with its own cursor and window manager, so an agent working on one
      cannot disturb another.
  - name: Files
    description: Upload and download files
  - name: Templates
    description: Author, build, and launch reproducible computers from templates
paths:
  /computers/{id}/bash:
    post:
      tags:
        - Computer Actions
      summary: Execute bash
      description: >-
        Runs Bash on Linux or PowerShell on Windows. `timeout` defaults to 200
        seconds (maximum 300) on both, and the API waits 30 seconds longer than
        the command timeout. No background job ID is returned. On Windows the
        response carries `stdout`, `stderr`, `exit_code`, and `output` (stdout
        followed directly by stderr) instead of the Linux fields, plus `error`
        when the command could not run. A Windows command that runs out of time
        returns `200` with `exit_code` `124`, `error` `"timeout"`, and the
        output captured so far. On Linux, `?screen=` runs the command on another
        screen: Orgo prefixes it with `export DISPLAY=:N;` for that screen's
        display and echoes your command without the prefix. An unknown screen
        returns `404` and nothing runs.
      operationId: executeBash
      parameters:
        - name: id
          in: path
          required: true
          description: Computer ID
          schema:
            type: string
        - name: screen
          in: query
          required: false
          description: >-
            Which screen to run the command on. Omit it, or send `default`, for
            the boot screen. For any other screen the command runs with
            `DISPLAY` set to that screen's display. An unknown id returns 404
            and nothing runs. Only Linux computers have more than one screen; on
            any other computer every id but `default` returns 404.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BashRequest'
            example:
              command: ls -la /home/user
      responses:
        '200':
          description: >-
            The command ran. A non-zero exit is still a `200`; read `exit_code`.
            On Windows the body carries `stdout`, `stderr`, `exit_code`, and
            `output` instead, and a command that ran out of time is also a
            `200`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BashResponse'
              example:
                success: true
                action: bash
                command: ls -la /home/user
                output: |
                  total 32
                  drwxr-xr-x 4 user user 4096 Jan 15 10:30 .
                  drwxr-xr-x 3 root root 4096 Jan 15 10:00 ..
                  -rw-r--r-- 1 user user  220 Jan 15 10:00 .bashrc
                  drwxr-xr-x 2 user user 4096 Jan 15 10:30 Desktop
                exit_code: 0
                error: null
                error_type: null
        '400':
          description: >-
            The computer has no VM attached, the body is not JSON, or `command`
            is missing, empty, or not a string.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                no-instance:
                  summary: The computer has no VM attached. Start it first.
                  value:
                    error: Desktop instance not available
                not-json:
                  summary: Body is not JSON
                  value:
                    error: Expected a JSON object
                no-command:
                  summary: No command
                  value:
                    error: command must be a non-empty string
        '401':
          $ref: '#/components/responses/UnauthorizedWithAccess'
        '402':
          $ref: '#/components/responses/TrialInactive'
        '404':
          description: >-
            No computer with this id, or `?screen=` names a screen this computer
            does not have. A missing computer's body carries a `hint` explaining
            that computer ids do not survive a rebuild. For an unknown screen,
            nothing runs.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/Error'
                  - $ref: '#/components/schemas/UpstreamError'
              examples:
                no-computer:
                  summary: Unknown computer
                  value:
                    error: Desktop not found
                    hint: >-
                      This id isn't on your account. Computer ids are not stable
                      across rebuilds. If the VM was recreated, re-fetch the
                      current one from GET /api/computers.
                no-screen:
                  summary: Unknown screen
                  value:
                    error: no screen "screen-101"
                    request_id: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
                    upstream_status: 404
        '500':
          description: >-
            The command could not be started at all, with the computer's own
            message in `error` and `upstream_status: 500`.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/UpstreamError'
                  - $ref: '#/components/schemas/InternalError'
              example:
                error: …
                request_id: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
                upstream_status: 500
        '503':
          description: >-
            The computer could not be reached. It may be resuming, or its host
            may be unhealthy. Retry in a moment. The body carries a diagnostic:
            `vm_status`, `desired_status`, `host_reachable`,
            `desktop_api_reachable`, and a `hint`. Also returned, without the
            diagnostic, when the computer never finished provisioning.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/UnreachableError'
                  - $ref: '#/components/schemas/InternalError'
              examples:
                unreachable:
                  summary: Unreachable
                  value:
                    error: Could not reach the desktop. Try again in a moment.
                    request_id: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
                    code: ECONNREFUSED
                not-ready:
                  summary: The computer never finished provisioning
                  value:
                    error: Computer not ready
                    request_id: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
        '504':
          $ref: '#/components/responses/CommandTimeout'
components:
  schemas:
    BashRequest:
      type: object
      required:
        - command
      properties:
        command:
          type: string
          description: Bash command to execute
        timeout:
          type: integer
          default: 200
          minimum: 1
          maximum: 300
          description: >-
            How long the command may run, in seconds, on Linux and Windows
            alike. Omitted, 200. When sent it is clamped to 1-300: a larger
            value becomes 300, and `0` or a non-numeric value becomes 10. A
            Windows command that runs out of time returns `200` with `exit_code`
            `124` and `error` `"timeout"`.
    BashResponse:
      type: object
      properties:
        success:
          type: boolean
          description: >-
            `true` whenever the command ran at all, regardless of its exit
            status. Read `exit_code`.
        action:
          type: string
          enum:
            - bash
        command:
          type: string
          description: >-
            Echo of the command you sent. With `?screen=`, the `DISPLAY` prefix
            Orgo adds is left out.
        output:
          type: string
          description: >-
            Combined stdout and stderr, joined by a newline when both are
            non-empty.
        exit_code:
          type: integer
          description: >-
            The command's exit status, or `-1` when it was killed by a signal,
            including by the timeout.
        error:
          type: 'null'
          description: Always `null` on a `200`.
        error_type:
          type: 'null'
          description: Always `null` on a `200`.
    Error:
      type: object
      description: >-
        The base error body. Every failure carries `error`; individual endpoints
        add the fields named in the schemas below.
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable message.
          example: Access denied
        code:
          type: string
          description: >-
            Machine-readable reason. Present on the failures that define one,
            absent otherwise.
    UpstreamError:
      type: object
      description: >-
        A failure the computer itself returned, relayed with the computer's own
        status.
      required:
        - error
        - request_id
        - upstream_status
      properties:
        error:
          type: string
          description: The message the computer returned.
        request_id:
          type: string
          description: >-
            Correlation id for this failure. The server logged the failure under
            it, so quote it in a support report.
          example: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
        upstream_status:
          type: integer
          description: >-
            The status the computer returned. Mirrors the status of this
            response.
          example: 409
    InternalError:
      type: object
      description: >-
        An unexpected failure. Retrying is reasonable; if it persists, quote
        `request_id`.
      required:
        - error
      properties:
        error:
          type: string
        request_id:
          type: string
          description: >-
            Present on failures raised by a route that talks to a computer.
            Absent on the others.
          example: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
    UnreachableError:
      type: object
      description: >-
        The computer could not be reached. The diagnostic fields, present on the
        command endpoints, say how far the request got.
      required:
        - error
        - request_id
        - code
      properties:
        error:
          type: string
          example: Could not reach the desktop. Try again in a moment.
        request_id:
          type: string
          example: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
        code:
          type: string
          description: >-
            The socket-level error code, or `network_error` when none was
            reported.
          example: ECONNREFUSED
        vm_status:
          type:
            - string
            - 'null'
          description: The computer's recorded status when the request failed.
        desired_status:
          type:
            - string
            - 'null'
          description: >-
            The status the computer was being driven towards, when one was
            recorded.
        host_reachable:
          type:
            - boolean
            - 'null'
          description: Whether the host running the computer answered.
        desktop_api_reachable:
          type:
            - boolean
            - 'null'
          description: Whether the computer's own API answered.
        hint:
          type: string
          description: What to do next, given the two reachability results.
    TimeoutError:
      type: object
      description: >-
        The command ran past the time allowed for it and was aborted. Raise
        `timeout` on the request, up to 300 seconds.
      required:
        - error
        - request_id
        - code
      properties:
        error:
          type: string
          example: The command exceeded the allowed time and was aborted.
        request_id:
          type: string
          example: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
        code:
          type: string
          enum:
            - timeout
  responses:
    UnauthorizedWithAccess:
      description: >-
        No usable credential, or an access check failed. This endpoint runs its
        workspace access checks during authentication, so it answers a missing
        membership, view-only access, or a key scoped to another workspace with
        `401`, not `403`. A server-side fault while verifying the credential
        also returns `401`, with a `Service temporarily unavailable` message.
        Retry that one; the key is fine.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalid-key:
              summary: The key is not one of yours
              value:
                error: Invalid API key
            no-credential:
              summary: No key and no session
              value:
                error: Authentication required
            no-access:
              summary: Not the owner or a member of the workspace
              value:
                error: You do not have access to this workspace.
            view-only:
              summary: View-only member, and the request changes something
              value:
                error: >-
                  This workspace is view-only. Ask the owner for write access
                  (workspace_read_only).
            scope-mismatch:
              summary: The API key is scoped to another workspace
              value:
                error: >-
                  This API key cannot access this workspace
                  (workspace_scope_mismatch).
            service-unavailable:
              summary: Server-side fault while verifying the credential. Retry.
              value:
                error: >-
                  Service temporarily unavailable. The database is not accepting
                  requests. Retry shortly.
    TrialInactive:
      description: >-
        The computer is a free trial computer whose trial is no longer active,
        or it is paid for by its own subscription or dedicated purchase and that
        payment has lapsed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            trial:
              summary: Trial no longer active
              value:
                error: Choose a plan to continue.
            payment:
              summary: The computer's own payment has lapsed
              value:
                error: Manage this computer’s payment in Account → Usage.
    CommandTimeout:
      description: >-
        The command ran past the time allowed for it and was aborted. Nothing is
        rolled back: whatever the command did before the abort has happened.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/TimeoutError'
          example:
            error: The command exceeded the allowed time and was aborted.
            request_id: 7c1e0f4a-9b2d-4a51-8f0c-2d6b1e93a4c7
            code: timeout
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key authentication. Get your key at orgo.ai/workspaces

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.