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

# Shell Commands

> Executing shell commands in Replay workflows — single, multi, parallel, and timeout.

# Shell Commands

The `shell` step type executes shell commands and captures their output for extraction and assertion.

## Single Command

```yaml theme={null}
- name: check-disk
  type: shell
  command: "df -h /"
```

## Multiple Commands

When you run multiple commands, they execute sequentially. The last command's output is stored in `stdout` and `stderr`:

```yaml theme={null}
- name: setup
  type: shell
  commands:
    - "mkdir -p /tmp/test-data"
    - "echo 'config' > /tmp/test-data/config.json"
    - "cat /tmp/test-data/config.json"
```

## Parallel Commands

Use `parallel: true` to execute commands concurrently:

```yaml theme={null}
- name: parallel-tasks
  type: shell
  parallel: true
  commands:
    - "sleep 3 && echo 'Task 1 done'"
    - "sleep 2 && echo 'Task 2 done'"
    - "sleep 1 && echo 'Task 3 done'"
```

All three commands start simultaneously. The step completes when all finish.

When parallel, outputs are stored as `stdout_0`, `stdout_1`, etc.:

```yaml theme={null}
extract:
  task1_output: $.stdout_0
```

## Timeout

Prevent runaway commands with a timeout:

```yaml theme={null}
- name: safe-command
  type: shell
  command: "long-running-process"
  timeout: "30s"
```

Valid duration formats: `30s`, `5m`, `1h`, `500ms`.

## Working Directory

Run commands from a specific directory:

```yaml theme={null}
- name: build
  type: shell
  command: "make build"
  dir: /projects/my-app
```

## Extracting JSON from Output

If the shell command outputs JSON, you can extract values:

```yaml theme={null}
- name: get-version
  type: shell
  command: 'echo "{\"version\": \"1.2.3\", \"branch\": \"main\"}"'
  extract:
    app_version: $.version
    git_branch: $.branch

- name: show-version
  type: print
  message: "App version: {{ app_version }} ({{ git_branch }})"
```

## Output Variables

After a shell step, these variables are available:

| Variable                    | Description                        |
| --------------------------- | ---------------------------------- |
| `stdout`                    | Stdout of the last command         |
| `stderr`                    | Stderr of the last command         |
| `stdout_0`, `stdout_1`, ... | Per-command stdout (parallel mode) |
| `stderr_0`, `stderr_1`, ... | Per-command stderr (parallel mode) |

## Assertions on Output

```yaml theme={null}
- name: test-output
  type: shell
  command: 'echo "{\"status\": \"ok\", \"count\": 5}"'
  assert:
    - ["$.status", "eq", "ok"]
    - ["$.count", "gt", 0"]
```

## Ignoring Shell Errors

```yaml theme={null}
- name: optional-step
  type: shell
  command: "flakey-command"
  ignore_error: true
```

## Template Variables

All command strings support template variables:

```yaml theme={null}
- name: delete-user
  type: shell
  command: "curl -X DELETE https://api.example.com/users/{{ user_id }}"
```

## What's Next?

* Learn about [database operations](/replay/guides/database-operations) — PostgreSQL and Redis
* Branch with [control flow](/replay/guides/control-flow) — if/then/else conditions
* Iterate with [loops](/replay/guides/loops) — array iteration
