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

# Run Script Action

> Run deterministic bash scripts in workflow execution containers and pass structured results to later steps.

The `script.run` action executes an inline bash script as a deterministic workflow step inside the workflow execution container. Use it when you need repeatable shell automation that does not require an AI agent or model tokens.

***

## Overview

Run Script is designed for workflow steps where the command path is already known. The script runs in bash, can read environment variables, can run inside a cloned repository, and can return structured JSON for later steps.

<CardGroup cols={2}>
  <Card title="Deterministic execution" icon="gears">
    Run the script exactly as written without asking an AI agent to decide what to do.
  </Card>

  <Card title="Workflow data in" icon="brackets-curly">
    Pass trigger data and previous step outputs through environment variables.
  </Card>

  <Card title="Structured data out" icon="code">
    Write JSON to `$OC_OUTPUT_FILE` and reference parsed fields in downstream steps.
  </Card>

  <Card title="Failure-aware" icon="circle-exclamation">
    Exit code `0` succeeds. Non-zero exits, including timeouts, fail the step.
  </Card>
</CardGroup>

***

## When to use Run Script

Use Run Script when the work is deterministic and shell-based.

| Use this action      | When your workflow needs                                                                                                                                          |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `script.run`         | A known bash script, file inspection, validation command, formatting check, artifact preparation, or data transformation that should run the same way every time. |
| `agent.run`          | A single AI agent to reason about a task, choose tools, write text, inspect code, or make judgment calls.                                                         |
| `agent.session`      | Multiple AI agents, an interactive session, or a task that benefits from agent coordination and iteration.                                                        |
| `git.clone`          | Repository checkout before another step needs files from the codebase. Use `git.clone` before Run Script when the script should run inside a repository.          |
| `ci.executeWorkflow` | An external CI/CD pipeline, such as a GitHub Actions workflow, should run outside Overcut.                                                                        |

Run Script is a good fit for steps like:

* Check whether generated files changed after a previous step.
* Extract metadata from a cloned repository.
* Convert trigger or agent output into a normalized JSON shape.
* Run a lightweight command before deciding whether a later agent step should run.

***

## Add a Run Script step in Workflow Builder

<Steps>
  <Step title="Open Workflow Builder" icon="sliders">
    Open or create a workflow in Workflow Builder.
  </Step>

  <Step title="Add the action" icon="plus">
    Add an action step and choose **Run Script**.
  </Step>

  <Step title="Configure General fields" icon="list-check">
    Set **Step ID**, **Step Name**, and **Step Timeout (minutes)**.
  </Step>

  <Step title="Enter the script" icon="code">
    Add your shell commands in **Bash Script**. The script body is not template-interpolated, so pass dynamic values through **Environment Variables** instead.
  </Step>

  <Step title="Connect downstream steps" icon="diagram-project">
    Connect later steps and reference the Run Script result with `{{outputs.<stepId>...}}` expressions.
  </Step>
</Steps>

***

## Configuration fields

### General

<ParamField path="Step ID" type="string" required>
  Unique identifier for this step. Use a stable ID because later steps reference outputs with this value, for example `{{outputs.run-script.exitCode}}`.
</ParamField>

<ParamField path="Step Name" type="string" required>
  Display name shown in Workflow Builder and workflow run details.
</ParamField>

<ParamField path="Step Timeout (minutes)" type="number" required={false}>
  Maximum time the whole step can run before Overcut stops it. Defaults to `30` minutes. This remains the outer bound even when **Timeout Seconds (optional)** is set.
</ParamField>

### Script

<ParamField path="Bash Script" type="string" required>
  Inline bash script to execute. The script is required and must not be empty.
</ParamField>

<ParamField path="Working Directory (optional)" type="string" required={false}>
  Relative path inside the workflow workspace. Use this to run a script inside a repository cloned by an earlier `git.clone` step. This field can use workflow expressions, for example `{{outputs.clone-repo.workspacePath}}`.
</ParamField>

<ParamField path="Timeout Seconds (optional)" type="integer" required={false}>
  Maximum script runtime in seconds. Defaults to `1800`. The effective limit is bounded by **Step Timeout (minutes)**.
</ParamField>

### Environment Variables

<ParamField path="Environment Variables" type="object" required={false}>
  Key-value pairs exposed to the script as environment variables. Names must be valid shell identifiers, such as `TICKET_TITLE` or `BUILD_ID`. Values can use dynamic workflow expressions such as `{{trigger.title}}` and `{{outputs.previous-step.field}}`.
</ParamField>

***

## Pass data into scripts

Do not template-interpolate dynamic workflow data directly into **Bash Script**. Trigger titles, comments, and agent output can contain characters that have special meaning in bash. Instead, put dynamic values in **Environment Variables** and read them in the script.

```yaml theme={null}
steps:
  - id: "summarize-title"
    name: "Summarize Trigger Title"
    action: "script.run"
    params:
      script: |
        echo "Title: $TRIGGER_TITLE"
        printf '{"titleLength": %d}\n' "${#TRIGGER_TITLE}" > "$OC_OUTPUT_FILE"
      env:
        TRIGGER_TITLE: "{{trigger.title}}"
```

Use standard double braces for escaped values and triple braces for raw values. Triple braces are useful when passing agent prose or other text that should arrive without escaping.

```yaml theme={null}
steps:
  - id: "inspect-agent-summary"
    name: "Inspect Agent Summary"
    action: "script.run"
    params:
      script: |
        echo "Agent summary length: ${#AGENT_SUMMARY}"
      env:
        ISSUE_TITLE: "{{trigger.title}}"
        PREVIOUS_FIELD: "{{outputs.previous-step.field}}"
        AGENT_SUMMARY: "{{{outputs.agent-step.message}}}"
```

Inside the script, quote environment variables like `"$ISSUE_TITLE"` so bash treats the value as data.

***

## Use secrets safely

Project secrets attached to the workflow are available to Run Script as environment variables. Use them for API tokens, package registry credentials, or other sensitive values needed by deterministic commands.

<Warning>
  Do not print secrets. Run Script captures stdout and stderr in workflow run logs and stores captured output in the step result.
</Warning>

A safer pattern is to test that a secret is present without echoing the value:

```bash theme={null}
if [ -z "$PACKAGE_TOKEN" ]; then
  echo "PACKAGE_TOKEN is missing"
  exit 1
fi

echo "Package token is configured"
```

See [Vault](/docs/reference/vault) for project secret configuration and assignment.

***

## Return structured output with `$OC_OUTPUT_FILE`

Run Script always captures `exitCode` and `stdout`. To pass structured values to later steps, write valid JSON to the file path stored in `$OC_OUTPUT_FILE`.

```yaml theme={null}
steps:
  - id: "collect-build-info"
    name: "Collect Build Info"
    action: "script.run"
    params:
      script: |
        BUILD_ID="build-$(date +%s)"
        printf '{"buildId": "%s", "ready": true}\n' "$BUILD_ID" > "$OC_OUTPUT_FILE"
```

Later steps can reference parsed fields under `output`:

```yaml theme={null}
steps:
  - id: "use-build-info"
    name: "Use Build Info"
    action: "agent.run"
    instruction: |
      The build ID is {{outputs.collect-build-info.output.buildId}}.
```

Use `{{outputs.<stepId>.output.<field>}}` for values written to `$OC_OUTPUT_FILE`. Use `{{outputs.<stepId>.exitCode}}`, `{{outputs.<stepId>.stdout}}`, or `{{outputs.<stepId>.truncated}}` for the standard result fields.

***

## Execution results and failure behavior

Run Script stores the step result under `outputs.<stepId>`.

<ResponseField name="exitCode" type="number" required>
  Script exit code. `0` means the step succeeded. Non-zero values fail the step and workflow run. A timeout reports exit code `124`.
</ResponseField>

<ResponseField name="stdout" type="string" required>
  Captured stdout and stderr from the script. The stored value may be truncated.
</ResponseField>

<ResponseField name="truncated" type="boolean" required>
  Whether captured stdout and stderr were truncated before being stored.
</ResponseField>

<ResponseField name="output" type="object" required={false}>
  Parsed JSON object written to `$OC_OUTPUT_FILE`. Omitted when the output file is missing or empty.
</ResponseField>

<ResponseField name="outputParseError" type="string" required={false}>
  Error recorded when `$OC_OUTPUT_FILE` exists but contains invalid JSON or JSON that is too large. This does not fail an otherwise successful script.
</ResponseField>

Behavior summary:

| Behavior                                             | Result                                                                       |
| ---------------------------------------------------- | ---------------------------------------------------------------------------- |
| Script exits `0`                                     | Step succeeds.                                                               |
| Script exits non-zero                                | Step fails and the workflow run fails.                                       |
| Script exceeds its timeout                           | Step fails with `exitCode` `124`.                                            |
| Script writes to stdout or stderr                    | Output is captured in `stdout` and may be truncated.                         |
| `$OC_OUTPUT_FILE` is missing or empty                | Step can still succeed. `output` is omitted.                                 |
| `$OC_OUTPUT_FILE` contains invalid or too-large JSON | Step can still succeed if `exitCode` is `0`. `outputParseError` is recorded. |

***

## Validation rules

Overcut validates Run Script configuration when you save the workflow.

| Field                               | Rule                                                                                                                               |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| **Bash Script**                     | Required and non-empty.                                                                                                            |
| **Working Directory (optional)**    | Must be a relative path inside the workspace. It cannot start with `/`, use a Windows drive prefix, or include `..` path segments. |
| **Variable Name**                   | Must be a valid shell identifier matching letters, numbers, and underscores, and cannot start with a number.                       |
| **Variable Name** with `OC_` prefix | Not allowed. `OC_` is reserved for Overcut runtime variables such as `OC_OUTPUT_FILE`.                                             |
| **Timeout Seconds (optional)**      | Must be a positive integer with a maximum of `21600` seconds.                                                                      |

***

## Examples

### Run inside a cloned repository

Use `git.clone` first, then set **Working Directory (optional)** to the cloned repository folder.

```yaml theme={null}
steps:
  - id: "clone-repo"
    name: "Clone Repository"
    action: "git.clone"
    params:
      repoFullName: "{{trigger.repository.fullName}}"
      branch: "{{trigger.pullRequest.headBranch}}"

  - id: "inspect-repo"
    name: "Inspect Repository"
    action: "script.run"
    params:
      cwd: "{{outputs.clone-repo.workspacePath}}"
      script: |
        SHA=$(git log -1 --format=%H)
        BRANCH=$(git rev-parse --abbrev-ref HEAD)
        printf '{"sha": "%s", "branch": "%s"}\n' "$SHA" "$BRANCH" > "$OC_OUTPUT_FILE"
```

### Chain script output into another script

```yaml theme={null}
steps:
  - id: "produce-output"
    name: "Produce Output"
    action: "script.run"
    params:
      script: |
        echo '{"buildId": "build-7788", "color": "blue"}' > "$OC_OUTPUT_FILE"

  - id: "consume-output"
    name: "Consume Output"
    action: "script.run"
    params:
      script: |
        echo "Received build $BUILD_ID with color $COLOR"
        printf '{"label": "%s-%s"}\n' "$BUILD_ID" "$COLOR" > "$OC_OUTPUT_FILE"
      env:
        BUILD_ID: "{{outputs.produce-output.output.buildId}}"
        COLOR: "{{outputs.produce-output.output.color}}"
```

### Fail fast on a validation command

```yaml theme={null}
steps:
  - id: "check-package"
    name: "Check Package Metadata"
    action: "script.run"
    params:
      script: |
        test -f package.json || { echo "package.json not found"; exit 2; }
        node -e 'JSON.parse(require("fs").readFileSync("package.json", "utf8"))'
```

If `package.json` is missing or invalid, the script exits non-zero and the step fails.

***

## Related documentation

* [Workflows](/docs/workflows/workflows): Understand workflow components and step outputs.
* [Git Clone Action](/docs/workflows/git-clone): Clone repositories before running scripts against code.
* [Agent Run Action](/docs/workflows/agent-run): Use an AI agent when the task requires reasoning or judgment.
* [Agent Session Action](/docs/workflows/agent-session): Coordinate multi-agent or interactive work.
* [Execute CI Workflow Action](/docs/workflows/ci-execute-workflow): Trigger external CI/CD pipelines from workflows.
* [Event Context Reference](/docs/reference/event-context): Find trigger fields and expression examples.
* [Vault](/docs/reference/vault): Configure project secrets for workflows.
